前言

今天看一本PHP书籍的时候,看到里面提到了数据库的字符集,让我想到了宽字节注入,自己好像对此也是一知半解。查了点资料,特此做个笔记。

原因

宽字节注入,相信大家都知道是什么东西,利用GBK编码的问题通过%df\给吃掉,从而使'逃离出来,这里说得是gbk,但并不一定就只有gbk,只要字符通过转码,就有可能出现这类问题。

那么gbk转码到底是从哪里来的呢?

我们看下这张图,原来就是从clientconnection这里,会有一个gbk转码

再看下下面的代码,来个案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
<?php
//连接数据库部分,注意使用了gbk编码
$conn = mysql_connect('localhost', 'root', 'root') or die('bad!');
mysql_query("SET NAMES 'gbk'");
mysql_select_db('test', $conn) OR emMsg("连接数据库失败,未找到您填写的数据库");
//执行sql语句
$uid = isset($_GET['uid']) ? addslashes($_GET['uid']) : 1;
echo addslashes($_GET['uid'])."<br>";
$sql = "SELECT * FROM admin WHERE uid='{$uid}'";
echo $sql."<br>";
$result = mysql_query($sql, $conn) or die(mysql_error());
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="gbk" />
<title>新闻</title>
</head>
<body>
<?php
$row = mysql_fetch_array($result, MYSQL_ASSOC);
echo "<h2>{$row['name']}</h2><p>{$row['uid']}<p>\n";
mysql_free_result($result);
?>
</body>
</html>

首先set names gbk 等同于character_set_client=gbk,character_set_connection=gbk,character_set_results=gbk

然后我们看下代码,对GET来的uidaddslashes过滤一下,然后执行到数据库,我们注意,在这里set names gbk就起作用了,在传输到数据库的时候,会把代码gbk编码一下,就是在这里产生了注入,当我们输入%df'

经过addslashes变成%df\',然后gbk编码,%df\会变成一个汉字,从而使'逃逸出来,产生了注入

理解

1:少用iconv,可能产生编码问题

2:用mysql_set_charset代替set names,因为mysql_set-charset会修改mysql->charset为设定的字符集

3:用mysql_real_escape_string()代替ddslashes,因为前者会根据当前字符集进行过滤

参考地址

http://www.freebuf.com/articles/web/31537.html

http://www.91ri.org/8611.html

http://www.laruence.com/2008/01/05/12.html