sqlmap waf识别模块identYwaf
知己知彼,百战不殆。
WAF是什么?假设大家都知道了,如果想绕过WAF,首先得清楚,waf是哪个厂的,有哪些特点。waf是哪个厂的可以通过返回的一些特征来判断,当然,WAF完全有可能隐藏自己背后的厂商或者给出错误的引导信息。
switch/option ‘–identify-waf’ is obsolete (hint: functionality being done automatically)
sqlmap --identify-waf这个选项已经被废弃了,但是sqlmap依然有waf识别能力,例如有如下日志
WAF/IPS identified as ‘AliYunDun (Alibaba Cloud Computing)’
那么,sqlmap到底是怎么识别到WAF的呢?主要是identywaf这个库。
sqlmap的源码太难了,我先看看另一个比较简单的,identYwaf.py。
下面这段代码是什么意思?
if hasattr(ssl, "_create_unverified_context"):
# 全局取消证书验证
ssl._create_default_https_context = ssl._create_unverified_context
load_data()函数
这个函数读取了data.json中的数据,主要是为了构造WAF_RECOGNITION_REGEX
WAF_RECOGNITION_REGEX 就是把data.json中所有的关于waf的正则表达式拼接起来,比较令人困惑的就是?P这个符号了,
正则表达式中?P是什么意思?
(?P<name>expr)
这样的模式会匹配expr,并将匹配结果存放到名为name的组中。 很开心又遇到我知识盲点了。
SIGNATURES是什么?
我打印了一下,其实就是一个键值对字典。load_data中只是从data.json中把这个字典提取出来,后面还有其他应用。
flags那一行是什么意思?
正则表达式的修饰符,例如(?i)忽略大小写
但这里是不是有个问题?原来是作用在每一个上面的,你把他提到最前面,是不是全作用了?存疑。
def load_data():
global WAF_RECOGNITION_REGEX
if os.path.isfile(DATA_JSON_FILE):
with codecs.open(DATA_JSON_FILE, "rb", encoding="utf8") as f:
DATA_JSON.update(json.load(f))
WAF_RECOGNITION_REGEX = ""
for waf in DATA_JSON["wafs"]:
if DATA_JSON["wafs"][waf]["regex"]:
WAF_RECOGNITION_REGEX += "%s|" % ("(?P<waf_%s>%s)" % (waf, DATA_JSON["wafs"][waf]["regex"]))
for signature in DATA_JSON["wafs"][waf]["signatures"]:
SIGNATURES[signature] = waf
WAF_RECOGNITION_REGEX = WAF_RECOGNITION_REGEX.strip('|')
flags = "".join(set(_ for _ in "".join(re.findall(r"\(\?(\w+)\)", WAF_RECOGNITION_REGEX))))
WAF_RECOGNITION_REGEX = "(?%s)%s" % (flags, re.sub(r"\(\?\w+\)", "", WAF_RECOGNITION_REGEX)) # patch for "DeprecationWarning: Flags not at the start of the expression" in Python3.7
else:
exit(colorize("[x] file '%s' is missing" % DATA_JSON_FILE))
parse_args()函数:
使用了optparse
parser = optparse.OptionParser(version=VERSION)
init()函数:
做了几件事,设置cookie处理,设置http/https代理,设置user-agent
urllib.request.build_opener
urllib.request.install_opener
http.cookiejar.CookieJar
urllib.request.HTTPCookieProcessor
urllib.request.ProxyHandler
run()函数
调用了retrieve函数,等下我们看下此函数
original = retrieve(options.url)
retrieve函数
在此函数中,主要是请求url,并返回响应的数据。
non_blind_check函数
check_payload函数
一个最基本的payload,通过这个负载可以用来第一轮测试
HEURISTIC_PAYLOAD = “1 AND 1=1 UNION ALL SELECT 1,NULL,‘’,table_name FROM information_schema.tables WHERE 2>1–/**/; EXEC xp_cmdshell(‘cat …/…/…/etc/passwd’)#”
在data.json中保存的payload
info, payload = item.split("::", 1)
"payloads": [
"HTML::<img>",
"SQLi::1 AND 1",
"SQLi::1/**/AND/**/1",
"SQLi::1/*0AND*/1",
"SQLi::1 AND 1=1",
"SQLi::1 AND 1 LIKE 1",
"SQLi::1 AND 1 BETWEEN 0 AND 1",
"SQLi::1 AND 2>(SELECT 1)-- -",
"SQLi::' OR SLEEP(5) OR '",
"SQLi::admin'-- -",
"SQLi::information_schema",
"SQLi::;DROP TABLE mysql.users",
"SQLi::';DROP DATABASE mysql#",
"SQLi::1/**/UNION/**/SELECT/**/1/**/FROM/**/information_schema.*",
"SQLi::SELECT id FROM users WHERE id>2",
"SQLi::1 UNION SELECT information_schema.*",
"SQLi::1;EXEC xp_cmdshell('type autoexec.bat');",
"SQLi::1;INSERT INTO USERS values('admin', 'foobar')",
"XSS::<img src=x οnerrοr=alert('XSS')>",
"XSS::<img onfoo=f()>",
"XSS::<script>",
"XSS::<script>alert('XSS')</script>",
"XSS::\\\";alert('XSS');//",
"XSS::1' οnerrοr=alert(String.fromCharCode(88,83,83))>",
"XSS::<![CDATA[<script>var n=0;while(true){n++;}</script>]]>",
"XSS::<meta http-equiv=\"refresh\" content=\"0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K\">",
"XSS::javascript:alert(/XSS/)",
"XSS::<marquee onstart=alert(1)>",
"XPATHi::' and count(/*)=1 and '1'='1",
"XPATHi::count(/child::node())",
"XPATHi::' and count(/comment())=1 and '1'='1",
"XPATHi::' or '1'='1",
"XXE::<!ENTITY xxe SYSTEM \"file:///etc/passwd\" >]><foo>&xxe;</foo>",
"LDAPi::admin*)((|userpassword=*)",
"LDAPi::user=*)(uid=*))(|(uid=*",
"LDAPi::*(|(objectclass=*))",
"NOSQLi::true, $where: '1 == 1'",
"NOSQLi::{ $ne: 1 }",
"NOSQLi::' } ], $comment:'success'",
"PHPi::<?php include_once(\"/etc/passwd\"); ?>",
"ACE::netstat -antup | grep :443; ping 127.0.0.1; curl http://www.google.com",
"PT::/.htaccess",
"PT::/etc/passwd",
"PT::../../boot.ini",
"PT::C:/inetpub/wwwroot/global.asa"
]
签名计算:
在data.json保存了signature和waf的对应关系,只要弄清楚signature是怎么计算的
if signature in SIGNATURES:
waf = SIGNATURES[signature]
说实在的,这也太难了吧,受不了饿了。
identitywaf中关于re模块的使用
总结:将近600行的源码,2021年12月12日星期日 下午1:45把源码下载下来,开始读,到今天12月18日截止,没有完全读懂,掌握程度应该在60%。感觉这里面的核心就是re的使用。学到了这个(?P<name>)
语法就已经算赚了。还有就是一些payload,看看以后这些payload能不能用吧。
顺便提了个issue, stamparm还回复了。