美文网首页
SQL注入之WAF-Bypass

SQL注入之WAF-Bypass

作者: Miracle778 | 来源:发表于2019-06-15 14:37 被阅读0次

    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=1<位置1>union<位置2>select<位置3>1,2,table_name<位置4>from<位置5>information_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做具体分析。

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

    1. mysql版本:5.5.40
    2. 数据库名:hdu
    3. 表名:user
    4. user表结构


      image
    5. user表内容


      image

    位置1——参数跟union之间

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


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


      image
    2. 用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
    3. 浮点数形式代替空格


      image
    4. 科学计数法代替空格


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


      image

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

    1. 注释和mysql内联注释


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


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

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


      image

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

    1. 注释和mysql内联注释


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


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

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


      image

      下面是{},()的测试


      image

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

    1. 注释和mysql内联注释代替空格可用,此处就不截图了。
    2. mysql里的空白字符,与上面一样,此处不截图
    3. 浮点数和科学计数法代替空格,当与from相邻的查询参数是数字时可用


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


      image

    位置5——from之后的空格

    1. 注释和mysql内联注释代替空格可用,此处就不截图了。
    2. mysql里的空白字符,与上面一样,此处不截图
    3. 浮点数和科学计数法代替空格不可用
    4. 特殊字符,经测试`,{},()可用


      image

    实战应用

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

    题目描述:

    题目名称:In A Mess
    连出题人自己都忘了flag放哪了,只记得好像很混乱的样子。
    题目入口:http://web.jarvisoj.com:32780/

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


    image

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

    <?php
    
    error_reporting(0);
    echo "<!--index.phps-->";
    
    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}


    参考

    WAF Bypass数据库特性(Mysql探索篇)

    相关文章

      网友评论

          本文标题:SQL注入之WAF-Bypass

          本文链接:https://www.haomeiwen.com/subject/cojbfctx.html