- 转自一个不知名大佬的笔记
--------------------------------less-32--------------------------------------
原url:
http://192.168.137.138/sqli-labs-master/Less-32/
添加id值
编码知识
涉及到的一些概念
字符、字符集与字符序
字符(character)是组成字符集(character set)的基本单位。对字符赋予一个数值(encoding)来确定这个字符在该字符集中的位置。
字符序(collation)指同一字符集内字符间的比较规则。
UTF8
由于ASCII表示的字符只有128个,因此网络世界的规范是使用UNICODE编码,但是用ASCII表示的字符使用UNICODE并不高效。因此出现了中间格式字符集,被称为通用转换格式,及UTF(Universal Transformation Format)。
宽字节
GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。宽字节带来的安全问题主要是吃ASCII字符(一字节)的现象。
MYSQL的字符集转换过程
-
MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection;
-
进行内部操作前将请求数据从character_set_connection转换为内部操作字符集,其确定方法如下:
? 使用每个数据字段的CHARACTER SET设定值;
? 若上述值不存在,则使用对应数据表的DEFAULT CHARACTER SET设定值(MySQL扩展,非SQL标准);
? 若上述值不存在,则使用对应数据库的DEFAULT CHARACTER SET设定值;
? 若上述值不存在,则使用character_set_server设定值。
将操作结果从内部操作字符集转换为character_set_results。
重点:宽字节注入发生的位置就是PHP发送请求到MYSQL时字符集使用character_set_client设置值进行了一次编码。
PHP测试代码:
<!DOCTYPE html>
<meta charset="gbk">
<?php
error_reporting(0);
conn);
mysql_query("set names gbk"); //不安全的编码设置方式
row = mysql_fetch_array(
row);
}
_GET['sql']); //mysql_real_escape_string() magic_quote_gpc=On addslashes() mysql_escape_string()功能类似
user}'";
echo res = mysql_query(
row = mysql_fetch_array(
row);
}
}
else{
echo "Error".mysql_error()."
";
}
?>
http://localhost/xl.php?sql=root%df%27%20or%201=1%23
是可以执行成功的!
解析过程:
$_GET[‘sql’] 经过 addslashes编码之后带入了‘\’
1、root%df%5C%27%20or%201=1%23
2、带入mysql处理时使用了gbk字符集
%df%5c -> 運 成功的吃掉了%5c
%27 -> ‘ 单引号成功闭合
怎么吃的:
GBK编码,它的编码范围是0×8140~0xFEFE(不包括xx7F),在遇到%df(ascii(223)) >ascii(128)时自动拼接%5c,因此吃掉‘\’,而%27、%20小于ascii(128)的字符就保留了。
补充:
GB2312是被GBK兼容的,它的高位范围是0xA10xF7,低位范围是0xA10xFE(0x5C不在该范围内),因此不能使用编码吃掉%5c。
其它的宽字符集也是一样的分析过程,要吃掉%5c,只需要低位中包含正常的0x5c就行了。
总结一下漏洞成因:
1、使用了不安全的字符集设置函数与过滤函数。
2、漏洞发生在PHP请求mysql时使用character_set_client值进行一次转码。
GBK 编码,编码范围是 0x8140 ~ 0xFEFE(不包括xx7F)。
常规测试
先添加一个 ' 或者 "
返回页面都是正确的
页面hint:
Hint: The Query String you input is escaped as : 1'
The Query String you input in Hex becomes : 315c27
总会多出一个,都是被转义了
使用宽字节字符测试
在要测试的字符前加上 %bf(bf是十六进制,%是url编码格式)(或者其他宽字节字符的高位)
语句:
1%bf'
返回效果:
页面报错:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1?'' LIMIT 0,1' at line 1
页面hint:
Hint: The Query String you input is escaped as : 1?'
The Query String you input in Hex becomes : 31bf5c27
由语法错误可以看出,闭合条件是 '
再继续爆字段位置:
语句:
1%bf' and 1=2 union select 1,2,3 --+
效果如下:
Your Login name:2
Your Password:3
页面hint:
Hint: The Query String you input is escaped as : 1?' and 1=2 union select 1,2,3 --
The Query String you input in Hex becomes : 31bf5c2720616e6420313d3220756e696f6e2073656c65637420312c322c33202d2d20
后面的就不继续了
那么为什么就加上个 bf 就行了呢?
去看看源码
------------------------------------源码部分---------------------------------
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
function check_addslashes(string = preg_replace('/'. preg_quote('\') .'/', "\\\",
string = preg_replace('/'/i', '\'',
string = preg_replace('/"/', "\"", $string); //escape double quote with a backslash
return $string;
}//可见,这个 转义处理 函数只是把一些特定的字符转义
// take the variables
if(isset(id=check_addslashes(
id . "
";
//logging the connection parameters to a file for analysis.
fp,'ID:'.
fp);
// connectivity
mysql_query("SET NAMES gbk");//很重要!!!!设置字符集,为 GBK。字符集被设置后,mysql就要进行设置的字符集去理解 sql 语句
id' LIMIT 0,1";
sql);
result);
if($row)
{
echo '<font color= "#00FF00">';
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
</font> </div></br></br></br><center>
<img src="../images/Less-32.jpg" />
</br>
</br>
</br>
</br>
</br>
<font size='4' color= "#33FFFF">
<?php
function strToHex(hex='';
for (i < strlen(
i++)
{
string[
hex;
}
echo "Hint: The Query String you input is escaped as : ".id). "
";
?>
1.编码转换
在php代码中,我们发现 mysql_query("SET NAMES gbk");它表示在进行 mysql 连接时,使用 GBK 字符集,这样就有一个编码转换的过程,其中 转义处理函数 不识别字符集,他只是处理特定的字符,如 \ ' " 之类的,在 %bf' 语句被放入 转义处理函数 时,函数会在 ' 前面加上 \(%5c)
2.原理解释
当我们的参数为 id=1%bf%27 时,过滤函数首先进行转义,将其变为
id=1%bf%5c%27(%5c 就是 \),然后交由 mysql 处理, mysql 按照双字节去理
解这条语句 ,这样 %bf%5c 刚好可以组成一个 双字节字符,那么我们 称之为 吃
掉了 字符 '\' 。如此一来,对单引号的转义 字符(\)就失去了作用,出现单引
号又破坏了 sql 语句的结构,就造成了 注入
还记得在科普中说的 gbk 编码范围吗?
0x8140 ~ 0xFEFE(除去 xx7F)
那么照着上文的思路
%5c就等于是和%bf组成的 宽字节字符 中的 低位
那么,在 高位 添加 任意字符集(正确范围内的),都会 吃掉 \ (%5c)
现在又想:那么为什么 %5c 和 %bf(或者其他高位)能组成宽字节,而不和 %27(')组合呢?
因为,编码范围 就是 81 40 ~ FE FE(81~FE 是高位,40~FE 是低位)
如果是 5c 27 组合,很明显
作为高位的 5c 不在编码范围中, 低位的 27 也不在 范围中
同样的分析 bf 5c 组合:
bf 在高位范围中,5c 在低位范围中
这样,使得 ' 释放
后续注入过程就不一一记录
网友评论