没人比我更懂waf之一点寒芒先到随后枪出如龙
2020-08-13 11:35:58 Author: xz.aliyun.com(查看原文) 阅读量:271 收藏

前言

同事遇到一个站有注入,然后有waf,waf检测了一些关键字不是很好弄,于是丢给了我,所以有了这次的故事,话不多说,我们直接进入正题。

First Step

如果遇到注入首先第一步是干啥呢,我一般先判断后台数据库类型,所以我们先来说一下判断数据库类型的几种常用方法,要判断是什么类型的数据库当然要利用不同数据库各自独特的特点,此处就讨论比较常见的oracle,mssql,mysql不针对access数据库,这个access比较刚,我玩不过他.

(下面的这些方法也许不是所有情况都有用,需要结合具体场景,结合不同的返回包情况自主判断)
利用mssql特有的延时方法 waitfor delay payload如下:
id=1';waitfor delay '0:0:5' --
如果上面这个payload发了之后 成功演延时了5s 那么可以确定后端数据库是mssql
利用Mssql特有的 top 关键词来判断 TOP 子句用于规定要返回的记录的数目 所以可以利用如下payload判断是否mssql
id=1' and (select top 1 'aaa')='aaa
mssql 可以通过特殊的爆错 Microsoft ODBC Database Engine 错误 识别

mssql 通过特有的系统表 sysobjects 识别

id=1' and (select count(*) from sysobjects)>0 and '1'='1

current_user函数 current_user 返回当前数据库的所有者,授权者 这个函数mssql 和 oracle mysql都有
在mssql中 可以用来判断是否是dba 权限 如果是dba select current_user 的返回值就是 dba
在oracle中 经过我实测 发现
select current_user from dual 的效果等于 select user from dual
都是查看当前数据库的用户

mysql中效果与 select user() 效果一致

利用字符串连接方式判断:
在mysql中 字符串连接可以用 select 'a' 'bc' ; 结果就是 abc
oracle中 字符串连接是利用|| select 'a' || 'bc' 结果是 abc
在mssql中 字符串连接利用+ select 'a'+'bc' 结果是 abc 这三种 这三种字符串连接方法都是各自独特的 可以很好的区分不同数据库

mysql中#是作为注释符的 而且是Mysql独有 利用#可以判断后台是否mysql 例如:
id=1' and 1=1 #
mysql中需要--空格才是单行注释如果只有--是语法不对的 而在mssql 和 mssql 中 --都是单行注释
mysql特有的函数 CURRENT_DATE
select CURRENT_DATE ;
id=1' and (select CURRENT_DATE)='aaa

mysql 特有的 now函数

id=1' and (select now())='aaa


mysql中通过特有的表
id=1' and (select count(*) from information_schema.TABLES)>0 and '1'='1
mysql中通过特殊时间延迟函数benchmark 下面这句是将md5('admin') 执行100000次
id=1' and (select BENCHMARK(100000,MD5('ADMIN'))) and '1'='1
效果类似下图

oracle 通过特有函数 NLV2
介绍:
NVL2(expr1,expr2,expr3),含义是:如果Oracle中第一个参数的值为空,那么显示第二个参数的值,如果第一个参数的值不为空,那么显示第三个参数的值。 类似于mysql中的 if
判断payload:
id=1' and (select NVl2('a','aaa','b')='aaa

oracle 通过爆错信息识别
ORA-01756:quoted string not properly terminated

ORA-00933:SQLcommand not properly ended
oracle 通过特有的表 sys.user_tables
payload 如下:
id=1 ' and (select count(*) from sys.user_tables)>'0

orcale中 select '123' 这种是不正确的语法 这种语法在mysql和mssql中可以 但是在oracle中 需要 加上from drual 在oracle 中select 必须要指明表名。若并非对真实的表进行查询,则需要用 dual 作为表名。这也是一个可以用来判断是否oralce的特点 比如下面的payload:
id=1' and (select 'aaa' from drual)='aaa
如果报语法出错那么显然不是oracle 否则是oracle
还有 len函数 这个函数是mssql 和 oracle 有. mysql 没有这个函数 所以利用这个函数也可以判断后端数据库是否是mysql

Second step
好了第一步判断数据库的说了很多了 现在来说这次遇到的waf情况 首先它是个注入

并且会把爆错位置显示出来

可以看出来是有waf的 首先我们先来判断一下 后端数据库是什么类型

似乎遇到了一点困难 好我们先得用上and, 绕过它就完事

一根烟的功夫 and已经可以用了 好咱们来判读判断后端数据库类型 此处利用 oracle 特有的函数 nvl2 轻松判读出后端数据库是oracle

尝试爆错注入 但是不知道为什么没有成功爆错

注入有waf的情况很容易就走到现在这种情景下 绕过了一个限制 还有另外的限制 这样的注入其实利用起来根本没用,要想拖数据就得找到一个关键点,让waf懵逼,让它全部检测不到 但是这种关键点是很难找的,不仅要技术 奇思妙想 还要天时地利人和 运气好

我们这个地方硬刚是比较难刚了,注意到是json数据,那么waf怎么解析数据并且过滤呢,很可能是通过 request头部的信息来判断
当然比较厉害的waf也应该能够自动检测 数据包内容的格式
有了这个思路 所以把 requests头部的 application/json 改为 其他的任意东西 比如 application/text 然后我们在来看一下 用相同的payload 之前会被检测到的 现在已经不检测了

waf懵逼了 直接解析不鸟数据 当然也就检测不鸟了 刚才硬刚苦思冥想也绕不过的waf 现在只修改了4个字符就大路通畅了 这就是绕waf 真是神奇 .

接下来就是sqlmap 一把嗦了.


文章来源: http://xz.aliyun.com/t/8097
如有侵权请联系:admin#unsafe.sh