Less 32
JSP
可能是闲着没事多做了一关,名字就是Fun with JSP,可能确实是用来娱乐的。
单引号小括号字符型,无过滤。
唯一的乐趣是有一个index.jsp1
的备份文件,可以看到源码,这也是 Web 题的一种套路,一般用在 PHP 代码审计和 SQL 注入的混合关。
PHP
基于错误_GET_单引号_字符型_转义引号反斜杠_宽字节注入
0x01. 宽字节注入
在旧版本的 MySQL 安装时,会有编码问题导致中文乱码,需要手动设置编码为 UTF-8。而安装 MySQL 5.7 时并没有出现这个问题,默认编码已经是 UTF-8。
SHOW VARIABLES LIKE 'character%';
PHP 自带一些转义特殊字符的函数,如addslashes()
,mysql_real_escape_string()
,mysql_escape_string()
等,这些函数可用来防止 SQL 注入。
如id=1'or'1'='1
,单引号本用来闭合语句,这些函数会自动转义这些闭合的单引号,在这些单引号前面加上转义符\
,变为1\'or\'1\'=\'1
,如此在 SQL 查询中仍然一个普通的字符串,不能进行注入。
而网站在过滤'
的时候,通常的思路就是将'
转换为\'
,因此我们在此想办法将'
前面添加的\
去掉,一般有两种思路:
%bb
连带\
如果程序的默认字符集是GBK
等宽字节字符集,就有可能产生宽字节注入,绕过上述过滤。
若在 PHP 中使用mysql_query("set names gbk")
将默认字符集设为GBK
,而使用addslashes()
转义用户输入,这时如果用户输入%bb%27
,则addslashes()
会在%27
前面加上一个%5c
字符,即转义字符\
。
而 MySQL 在使用GBK
编码时,会认为两个字符为一个汉字,%bb%5c
是一个宽字符(前一个 ASCII 码大于 128 才能到汉字的范围),也就是籠
,也就是说%bb%5c%27
=籠'
,这样单引号就未被转义能闭合语句,从而产生 SQL 注入。%bb
并不是唯一一个可以产生宽字节注入的字符,理论上%81
-%FE
均可。过滤
\'
中的\
构造%bb%5c%5c%27
,addslashes()
会在两个%5c
和%27
前都加上\
即%5c
,变为%bb %5c%5c %5c%5c %5c%27
,但宽字符集认为%bb%5c
是一个字符即籠
,则变为%bb%5c %5c%5c %5c%5c %27
即籠\\\\'
,四个\
正好转义为两个\
,即'
未被转义。这也是 bypass 的一种方法。
0x02. 注入过程
知道这关是宽字节注入,先以上帝视角看看源码:
mysql_query("SET NAMES gbk");
$id = check_addslashes($_GET['id']);
function check_addslashes($string)
{
$string = preg_replace('/'.preg_quote('\\').'/',"\\\\\\",$string); //escape any backslash
$string = preg_replace('/\'/i','\\\'',$string); //escape single quote with a backslash
$string = preg_replace('/\"/',"\\\"",$string); //escape double quote with a backslash
return $string;
}
可以看到这个函数是个过滤\
、'
、"
的函数,分别在前面加上\
。
步骤1:确定宽字节注入
1
、1'
、1"
都能正常回显,可以猜测输入的引号被过滤,从页面给的 hint 也证实了这一点。
猜测是引号是被转义而并非被纯粹过滤,尝试宽字节注入:
http://localhost:8088/sqlilabs/Less-32/?id=1%bb%27
有错误回显,从其中可以看到被单引号闭合。
若无错误回显,可注释后面的查询语句:
http://localhost:8088/sqlilabs/Less-32/?id=1%bb%27--+
用上述第二种方法同样可以做到:
http://localhost:8088/sqlilabs/Less-32/?id=1%bb%5c%5c%27--+
已经确定了单引号闭合且宽字节注入可以绕过,剩下的就是正常的注入,无其他过滤条件。
因未过滤注释,所以只有开头的单引号需要宽字节注入。
0x03. 吐槽
总觉得越到后面越简单了,可能是没把过滤条件都结合起来,后来还得总结一下过滤条件和注入方式。
Less 33
基于错误_GET_单引号_字符型_addslashes()_宽字节注入
Less 32 是自定义的过滤器,本关直接使用了 PHP 的addslashes()
函数,在 Less 17 中介绍过:
addslashes()与stripslashes()函数
addslashes(string)
函数返回在预定义字符之前添加反斜杠\
的字符串:
- 单引号
'
- 双引号
"
- 反斜杠
\
- 空字符
NULL
该函数可用于为存储在数据库中的字符串以及数据库查询语句准备字符串。
注意:默认地,PHP对所有的GET、POST和COOKIE数据自动运行
addslashes()
。所以不应对已转义过的字符串使用addslashes()
,因为这样会导致双层转义。遇到这种情况时可以使用函数get_magic_quotes_gpc()
进行检测。
stripslashes(string)
函数删除由addslashes()
函数添加的反斜杠。
判断和注入过程同 Less 32 完全相同。