mysql 注入 waf_SQL注入之WAF-Bypass

title: SQL注入之WAF Bypass

date: 2019-05-07 12:00:26

tags:

- Mysql

- SQL注入

- Bypass

- WAF

categories:

- Web安全

- SQL注入

针对CTF中SQL注入题里的绕过过滤,Bypass WAF做的一些归纳总结。

前言

之前做SQL注入相关的CTF题,总是有力不从心的感觉,每次都会被过滤搞到自闭,也是因为自己没有好好总结,导致遇到这种过滤题无从下手。。而看别人的wp的话,经常会看到,用/*1*/、%0b代替空格,用/*!12345 select 1*/直接进行sql语句注入等等。。每次看到这种,总是云里雾里,网上搜索也不好确定关键词,找不到想要的答案。。

所以今天就来系统总结一波。

起手

select * from user where id = 1 union select 1,2,table_name from information_schema.tables···

上面这条sql语句,是一条正常的SQL注入语句。它的斜体是后台PHP进行的正常查询,斜体后面的语句则是我们的注入语句。不过实践中,肯定会存在WAF,会对我们输入的空格、SQL语句关键词做处理。那我今天要研究的就是,如何绕过WAF的检测过滤,重点关注的是绕过WAF对空格的过滤。

既然我们要研究的是绕过空格,那我们把上面的SQL语句按空格的位置来标记分类一下,然后再进行相应研究。

select * from user where id=1unionselect1,2,table_namefrominformation_schema.tables···

这里先归纳一下,sql语句中空格的代替方法:

/*!50540select user()*/ mysql(独有)内联注释,!后面的数字是版本号,表示当数据库版本>=5.5.40时执行SQL语句

/**/ mysql多行注释

%09,%0a,%0b,%0c,%0d,%20,%a0 一些空白字符

1.1、2.3、1. 浮点数形式

0e1、1e7 科学计数法

+、-、!、@、~、{}、"、'、()、`` 一些特殊字符

上面总结的各种代替空格的方法,只对SQL语句某些位置起局部代替空格作用,并不适用整体SQL语句语法。所以下面就针对上面对sql语句分的位置1-5做具体分析。

在开始测试前,先对本地环境做个记录。

mysql版本:5.5.40

数据库名:hdu

表名:user

user表结构

image

user表内容

image

位置1——参数跟union之间

先看一下正常查询返回的结果

image

使用/**/、和内联注释代替参数跟union中间的空格,关于内联注释里的5位数字在前面以及说过了,这里就不解释了。

image

用mysql里的空白字符%09(\t),%0a(\n),%0b,%0c,%0d(\r),%20,%a0代替空格,这里说明一下,因为我这里是在mysql客户端下测试,所以%09、%0a、%0b这种输入肯定是不行的,要转成%0b、%0c这种的url解码结果输入才行。正常SQL注入的话是在网页输入框中输入,浏览器会自动解码,所以填%09,%0a这种形式。

于是我们把%0b、%0c解码后的字符复制粘贴代替参数和union之间的空格。

image

image

浮点数形式代替空格

image

科学计数法代替空格

image

特殊符号代替空格,这里测了一下,发现只有()有效,不过挺感觉挺鸡肋的。

image

位置2——union跟select之间的位置

注释和mysql内联注释

image

mysql里的空白字符,同样用%0b,%0c url解码后的字符代替空格进行测试

image

浮点数和科学计数法代替空格此位置处不可用

特殊字符的话,经测试后,也只有()有用。

image

位置3——select和查询参数之间的位置

注释和mysql内联注释

image

mysql里的空白字符,同样用%0b,%0c url解码后的字符代替空格进行测试

image

浮点数和科学计数法代替空格此位置处不可用

特殊字符,经测试~,!,@,+,-,"",'',{},()可用

image

下面是{},()的测试

image

位置4——查询参数和from之间的空格

注释和mysql内联注释代替空格可用,此处就不截图了。

mysql里的空白字符,与上面一样,此处不截图

浮点数和科学计数法代替空格,当与from相邻的查询参数是数字时可用

image

特殊字符,这里经测试只有{},(),"",'',`加字母可用

image

位置5——from之后的空格

注释和mysql内联注释代替空格可用,此处就不截图了。

mysql里的空白字符,与上面一样,此处不截图

浮点数和科学计数法代替空格不可用

特殊字符,经测试`,{},()可用

image

实战应用

感觉上面总结的挺垃圾的,想搞个实例再详细写一下,刚好在Jarvis OJ做到一题SQL注入绕过WAF,于是就拿来分析一下。

题目描述:

题目名称:In A Mess

连出题人自己都忘了flag放哪了,只记得好像很混乱的样子。

题目入口:http://web.jarvisoj.com:32780/

题目一进去,查看源码得到提示,访问index.phps文件

image

访问index.phps文件,得到一份源码

error_reporting(0);

echo "";

if(!$_GET['id'])

{

header('Location: index.php?id=1');

exit();

}

$id=$_GET['id'];

$a=$_GET['a'];

$b=$_GET['b'];

if(stripos($a,'.'))

{

echo 'Hahahahahaha';

return ;

}

$data = @file_get_contents($a,'r');

if($data=="1112 is a nice lab!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)

{

require("flag.txt");

}

else

{

print "work harder!harder!harder!";

}

?>

从上面代码的第4行和刚刚index.php页面源码截图来看,很容易推测出,这份代码是index.php的源码。

而这里源码的漏洞和之前Bugku上一题类似,id利用弱类型比较,data利用php://input,b利用ereg的00截断进行绕过如下图,这里就不细讲了,毕竟重头戏是SQL注入。

image

绕过上面那关之后,可以看到有一个地址^HT2mCpcvOLf,继续访问。

image

经测试,当将id改为1之外的数的话,会直接显示sql语句

image

把id改为2-1,会回显hi666,说明id是整数型,这里可注入。

image

然后尝试进行注入,但是发现当输入注入语句,会回显you bad boy/girl!

image

结合三种回显,可以梳理一下逻辑。当id存在于服务器数据库时,回显表中的内容,当id不在服务器数据库里时(或者执行出错),回显sql语句,当检测到注入时,回显you bad boy/girl!。

说明有waf,存在过滤,经测试,在id后输入空格即会被检测成注入(位置1)。于是可以采用上述的空格绕过姿势进行尝试。

经测试,发现id和union之间的空格可以用/*1*/或者浮点数、科学计数法等绕过,而内联注释,和空注释会被检测。图为用浮点数绕过空格,但是输入了union却发现回显语句没有union,说明union等关键字被替换成空了。

image

于是输入要用到的sql关键词,看看回显结果,输入id=2.2union;select;and;from;or,回显结果如下图。

image

可以看到,除了and和or,其余关键词都被替换为空了。这里尝试一下双写、大小写绕过,发现双写和大小写都可以。

image

解决了id和union直接的空格和关键词过滤后,然后再进一步进行sql注入。

然后发现union和select之间(位置2)要是存在空格的话,空格及后面的内容会被替换为空。

image

所以这里用到我们在位置2处测试的替换空格方案进行绕过,我测试时用到%0b,/*1*/可以绕过此处空格

image

然后从上图又发现select和查询参数间空格(位置3)及以后的内容会被替换成功,于是采用我们上面在位置3处分析总结的方法进行尝试,最后发现%0b,%0c可以进行替换,而/*1*/会被检测出注入。

于是用%0b替换select和查询参数间的空格,然后继续注入,逐步增加select后面的数字,发现加到3的时候,页面回显变为了3。。到这里已经看到了成功的希望(2333)

image

知道3字段位置有回显,然后利用这个字段进行查询。然后再进一步测试,然后发现,只要有空格就会把空格及空格后面的内容置换为空。这里懒得截图了,反正一步步测试下来,发现后面空格都可以用%0b绕过。

这里就跳过后续空格测试验证过程了。

直接爆表,payload:

id=2.2Union/*1*/%0bSelect%0b1,2,group_concat(table_name)%0bFrom%0binformation_schema.tables%0bwhere%0btable_schema=database()

image

得到表名content。

然后爆列,payload:

id=2.2Union/*1*/%0bSelect%0b1,2,group_concat(column_name)%0bFrom%0binformation_schema.columns%0bwhere%0btable_schema=database()

image

得到列名id,context,title

然后爆值,payload:

id=2.2Union/*1*/%0bSelect%0b1,2,group_concat(id,context,title)%0bFrom%0bcontent

image

得到flag:PCTF{Fin4lly_U_got_i7_C0ngRatulation5}

参考

你可能感兴趣的:(mysql,注入,waf)