当前位置: 首页 > news >正文

DVWA靶场通关笔记-SQL Injection Blind(SQL盲注 Impossible级别)

目录

一、源码分析

1、index.php

2、impossible.php

二、SQL注入防范分析

1、CSRF Token 验证

2、输入数字强制校验

3、PDO 预处理语句


本系列为通过《DVWA靶场通关笔记》的SQL Injection Blind关卡(low,medium,high,impossible共4关)渗透集合,通过对相应关卡源码的代码审计找到讲解渗透原理并进行渗透实践。本文为SQL Injection  Blind impossible关卡的原理分析部分,讲解相对于low、medium和high级别,为何对其进行渗透测试是Impossible的。

一、源码分析

1、index.php

进入DVWA靶场源目录,找到index.php源码。

这段 PHP 代码是 Damn Vulnerable Web Application (DVWA) 中 SQL盲注演示页面的主控制器,根据用户设置的安全级别(低 / 中 / 高 / 安全)加载不同级别安全成都程度的代码,通过表单让用户输入或选择用户 ID,动态生成页面并展示查询结果,同时检测 PHP 不安全配置并提供 SQL 注入学习资源链接,用于演示不同防护等级下的盲注攻击场景及防御方式。

经过注释后的详细代码如下所示。

<?php
// 定义网站根目录路径常量,用于后续文件引用
define( 'DVWA_WEB_PAGE_TO_ROOT', '../../' );
// 引入DVWA页面基础功能库
require_once DVWA_WEB_PAGE_TO_ROOT . 'dvwa/includes/dvwaPage.inc.php';// 启动页面,验证用户是否已认证并初始化PHPIDS(入侵检测系统)
dvwaPageStartup( array( 'authenticated', 'phpids' ) );// 创建新页面实例
$page = dvwaPageNewGrab();
// 设置页面标题
$page[ 'title' ]   = 'Vulnerability: SQL Injection (Blind)' . $page[ 'title_separator' ].$page[ 'title' ];
// 设置页面ID,用于导航和标识
$page[ 'page_id' ] = 'sqli_blind';
// 添加帮助按钮和源代码按钮
$page[ 'help_button' ]   = 'sqli_blind';
$page[ 'source_button' ] = 'sqli_blind';// 连接数据库
dvwaDatabaseConnect();// 设置HTTP请求方法(默认为GET)
$method            = 'GET';
// 初始化不同安全级别对应的源文件
$vulnerabilityFile = '';// 根据安全级别Cookie值选择不同的实现文件
switch( $_COOKIE[ 'security' ] ) {case 'low':// 低安全级别:存在明显SQL注入安全风险$vulnerabilityFile = 'low.php';break;case 'medium':// 中安全级别:部分防御措施,使用POST方法和下拉菜单$vulnerabilityFile = 'medium.php';$method = 'POST';break;case 'high':// 高安全级别:增强防御,但仍可能存在安全风险$vulnerabilityFile = 'high.php';break;default:// 安全模式:使用预处理语句,理论上无SQL注入风险$vulnerabilityFile = 'impossible.php';break;
}// 引入选定的实现文件
require_once DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/sqli_blind/source/{$vulnerabilityFile}";// 检查PHP配置中的安全风险
$WarningHtml = '';
// 检测Magic Quotes是否启用(已弃用的安全机制)
if( ini_get( 'magic_quotes_gpc' ) == true ) {$WarningHtml .= "<div class=\"warning\">The PHP function \"<em>Magic Quotes</em>\" is enabled.</div>";
}
// 检测Safe Mode是否启用(已弃用的安全机制)
if( ini_get( 'safe_mode' ) == true ) {$WarningHtml .= "<div class=\"warning\">The PHP function \"<em>Safe mode</em>\" is enabled.</div>";
}// 构建页面主体内容
$page[ 'body' ] .= "
<div class=\"body_padded\"><h1>Vulnerability: SQL Injection (Blind)</h1>{$WarningHtml}<div class=\"vulnerable_code_area\">";// 根据不同安全级别显示不同的用户交互界面
if( $vulnerabilityFile == 'high.php' ) {// 高级别安全:通过JavaScript弹窗设置用户ID$page[ 'body' ] .= "Click <a href=\"#\" onclick=\"javascript:popUp('cookie-input.php');return false;\">here to change your ID</a>.";
}
else {// 低、中级别安全:显示表单让用户输入ID$page[ 'body' ] .= "<form action=\"#\" method=\"{$method}\"><p>User ID:";// 中级别安全:使用下拉菜单限制用户选择范围if( $vulnerabilityFile == 'medium.php' ) {$page[ 'body' ] .= "\n				<select name=\"id\">";// 查询用户数量用于生成下拉选项$query  = "SELECT COUNT(*) FROM users;";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );$num    = mysqli_fetch_row( $result )[0];$i      = 0;// 动态生成下拉选项(1到用户总数)while( $i < $num ) { $i++; $page[ 'body' ] .= "<option value=\"{$i}\">{$i}</option>"; }$page[ 'body' ] .= "</select>";}else// 低级别安全:允许用户自由输入$page[ 'body' ] .= "\n				<input type=\"text\" size=\"15\" name=\"id\">";$page[ 'body' ] .= "\n				<input type=\"submit\" name=\"Submit\" value=\"Submit\"></p>\n";// 安全模式:添加CSRF防护令牌if( $vulnerabilityFile == 'impossible.php' )$page[ 'body' ] .= "			" . tokenField();$page[ 'body' ] .= "</form>";
}// 显示查询结果(由引入include的指定文件生成)
$page[ 'body' ] .= "{$html}</div><h2>More Information</h2><ul>// 提供SQL注入相关的参考链接<li>" . dvwaExternalLinkUrlGet( 'http://www.securiteam.com/securityreviews/5DP0N1P76E.html' ) . "</li><li>" . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/SQL_injection' ) . "</li><li>" . dvwaExternalLinkUrlGet( 'http://ferruh.mavituna.com/sql-injection-cheatsheet-oku/' ) . "</li><li>" . dvwaExternalLinkUrlGet( 'http://pentestmonkey.net/cheat-sheet/sql-injection/mysql-sql-injection-cheat-sheet' ) . "</li><li>" . dvwaExternalLinkUrlGet( 'https://www.owasp.org/index.php/Blind_SQL_Injection' ) . "</li><li>" . dvwaExternalLinkUrlGet( 'http://bobby-tables.com/' ) . "</li></ul>
</div>\n";// 输出最终HTML页面
dvwaHtmlEcho( $page );?>

2、impossible.php

进入DVWA靶场SQL Injection Blind的source源码目录,找到impossible.php源码,分析其为何能让这一关卡名为不可能实现SQL盲注渗透。

打开源码impossible.php,分析可知这段代码实现了用户 ID 查询功能,通过登录校验、CSRF Token、数字输入验证及 PDO 预处理,彻底防范注入与 CSRF 攻击,保障安全,如下所示。

详细注释后的impossible.php源码如下所示。

<?php// 检查是否通过GET方式提交了表单
if( isset( $_GET[ 'Submit' ] ) ) {// 验证CSRF令牌,防止跨站请求伪造攻击// 比较用户请求中的令牌与会话存储的令牌是否一致checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );// 从GET参数中获取用户输入的ID$id = $_GET[ 'id' ];// 验证输入是否为数字(防止非数字类型的SQL注入)if(is_numeric( $id )) {// 准备SQL查询:从users表中查询指定ID的用户信息// 使用预处理语句防止SQL注入$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );// 将用户输入的ID绑定为整数类型参数// 这一步确保即使输入包含非数字字符也会被转换为整数$data->bindParam( ':id', $id, PDO::PARAM_INT );// 执行SQL查询$data->execute();// 检查查询结果是否为1条记录if( $data->rowCount() == 1 ) {// 用户存在时的反馈信息$html .= '<pre>User ID exists in the database.</pre>';}else {// 用户不存在时返回404状态码header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );// 用户不存在时的反馈信息$html .= '<pre>User ID is MISSING from the database.</pre>';}}
}// 生成新的CSRF令牌并存储到会话中
generateSessionToken();?>

二、SQL注入防范分析

impossible.php 是 DVWA 中 SQL 盲注模块的最高防护级别页面,核心功能是在实现 “根据用户 ID 查询姓名” 业务的同时,通过多重机制杜绝安全风险。它先校验用户登录状态与 CSRF Token,确保请求合法;再对输入的 id 进行数字强制校验,过滤非预期输入;最后用 PDO 预处理语句执行数据库查询,彻底隔离用户输入与 SQL 逻辑。此外,页面还限制查询结果仅一条,避免数据泄露,通过 “请求校验 - 输入过滤 - 安全查询” 的闭环,既实现了用户数据查询的基础功能,又完全抵御 SQL 注入、CSRF 等攻击,是 Web 安全中数据库操作的标准安全实现。相对于Low级别、Medium级别、High级别,四个级别的防范措施对比如下所示。

级别输入方式防护措施注入难度核心特点
LowGET 参数无任何防护极低直接拼接 SQL 语句,可通过页面反馈判断注入结果
MediumPOST 参数(下拉)字符串转义(数字型查询无引号)转义无法防御数字型注入,可直接构造逻辑表达式
HighCookie 参数无过滤但有随机延迟中等依赖时间盲注,输入位置隐蔽,需通过延迟判断结果
ImpossibleGET 参数 + Token数字验证 + PDO 预处理 + CSRF 防护彻底隔离用户输入与 SQL 逻辑,无注入风险,完全防御各类攻击

impossible.php 并非仅实现 “查询用户数据” 的简单功能,而是通过 三重防护机制 构建了完整的安全闭环,彻底杜绝 SQL 注入及相关攻击:

防护机制作用场景核心目标
CSRF Token 验证请求合法性校验防止第三方伪造用户请求
输入数字强制校验输入源过滤阻断非预期格式的恶意输入
PDO 预处理语句数据库查询安全彻底隔离用户输入与 SQL 逻辑

1、CSRF Token 验证

CSRF 攻击利用用户已登录的会话伪造恶意请求,impossible.php 通过 Token 验证 确保请求由用户主动发起,而非第三方伪造。

// 5. 若用户点击「Submit」提交请求,先验证 CSRF Token
if (isset($_GET[ 'Submit' ])) {// 核心:验证请求中的 Token 与会话中存储的 Token 是否一致checkToken($_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php');// 后续业务逻辑...
}// 6. 在表单中嵌入 CSRF Token 隐藏字段(generateSessionToken() 已生成会话 Token)
$page[ 'body' ] .= '' . tokenField() . '  <!-- 生成 <input type="hidden" name="user_token" value="随机字符串"> --></form>
';
  • generateSessionToken():在用户会话($_SESSION['session_token'])中生成一个随机、唯一的 Token(如 a3f2d4e5b1),每次页面刷新或请求后可重新生成(短期有效);
  • tokenField():将会话中的 Token 嵌入表单隐藏字段,随用户请求一起提交;
  • checkToken(...):对比请求参数 user_token 与会话 session_token,若不一致则判定为恶意请求,跳转至首页并阻断后续操作。

2、输入数字强制校验

即使通过 CSRF 验证,代码仍对用户输入的 id 参数进行 强制数字校验,从源头阻断非预期格式的输入(如 SQL 注入片段)。

if (isset($_GET[ 'Submit' ])) {checkToken(...); // 先过 Token 验证// 7. 获取用户输入的 id 参数,并进行数字类型强制校验$id = $_GET[ 'id' ];// 核心:仅允许数字输入(整数/浮点数),非数字直接返回错误提示if (is_numeric($id)) {// 合法输入:进入数据库查询流程} else {// 非法输入:渲染错误提示,不执行任何数据库操作$page[ 'body' ] .= '<pre>ERROR: Invalid ID. Please enter a numeric value.</pre>';}
}
  • 若用户输入恶意字符串(如 1' OR '1'='1UNION SELECT...),is_numeric($id) 会判定为 false,直接阻断后续查询,避免非法输入进入数据库层;
  • 仅允许 123.5 等数字格式,符合「用户 ID 为数字」的业务逻辑,实现 “输入格式与业务逻辑匹配” 的安全原则。

3、PDO 预处理语句

对于合法的数字输入,代码使用 PDO 预处理语句(参数化查询) 执行数据库查询,这是杜绝 SQL 注入的核心机制。

if (is_numeric($id)) {// 8. 初始化 PDO 数据库连接(DVWA 核心配置中已确保 PDO 连接安全)$pdo = dvwaDbConnect();// 9. 准备预处理 SQL:使用占位符 (:id) 代替直接拼接用户输入$data = $pdo->prepare('SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;');// 10. 绑定参数:明确指定参数类型为整数(PDO::PARAM_INT),强制类型匹配$data->bindParam(':id', $id, PDO::PARAM_INT);// 11. 执行查询(用户输入仅作为参数传递,不参与 SQL 语法解析)$data->execute();// 12. 获取查询结果(仅返回一条数据,避免批量泄露)$row = $data->fetch();// 13. 渲染查询结果:有数据则显示用户名,无数据则提示“未找到”if ($row) {$page[ 'body' ] .= "<pre>ID: {$id}<br>First name: {$row[ 'first_name' ]}<br>Surname: {$row[ 'last_name' ]}</pre>";} else {$page[ 'body' ] .= '<pre>User ID not found in the database.</pre>';}
}
http://www.xdnf.cn/news/1420417.html

相关文章:

  • kubectl-etcd
  • 【C++】内存管理机制:从new到delete全解析
  • 植物中lncRNA鉴定和注释流程,代码(包含Identified,Classification,WGCNA.....)
  • 开发中使用——鸿蒙CoreSpeechKit语音识别
  • 基于MCP架构的OpenWeather API服务端设计与实现
  • C#在物联网GPS经纬度转换为百度地图地址
  • 亚马逊云代理商:如何选择适合的AWS EC2实例类型?
  • CVE Push Service | 高危漏洞实时情报自动化推送工具
  • Vue基础知识-使用监视属性watch和计算属性computed实现列表过滤+排序
  • 【golang长途旅行第35站】Redis
  • docker中的命令(六)
  • 针对redis中的热数据该怎么处理
  • ✝常用表格✝
  • Simulink库文件-一种低通滤波模块搭建方法
  • 【stm32】定时器(超详细)
  • 重构导航之核:高德地图的深度学习架构解析 导论:从数字化世界到可计算世界
  • 手搓3D轮播图组件以及倒影效果
  • Shell 编程 —— 正则表达式与文本处理实战
  • 如何用 Kotlin 在 Android 手机开发一个文字游戏,并加入付费机制?
  • 基于运营商投诉工单的分析系统设计与实现
  • Kotlin
  • 秋招笔记-8.29
  • 哈希表-1.两数之和-力扣(LeetCode)
  • 电路学习(四)半导体
  • LeetCode 165. 比较版本号 - 优雅Java解决方案
  • LangChain开源LLM集成:从本地部署到自定义生成的低成本落地方案
  • 人工智能——课程考核
  • 移动开发如何给不同手机屏幕做适配
  • Shell脚本编程:函数、数组与正则表达式详解
  • [SWPUCTF 2018]SimplePHP