前言
想必师傅们都知道宽字节注入的前提必须要目标使用了GBK编码,才能够加上一些字符结合转义字符构造成汉字,吞掉了转义字符,使得引号逃逸出来,导致注入。但是这里的"使用了GBK编码"具体指的是谁的编码呢?数据库的编码(数据库服务器的默认字符集、数据库的字符集、数据表的字符集、列的字符集)吗,网站的编码吗,还是什么编码?还是这两个都是?或者是其他的什么编码呢?
既然不知道,那么我先查查网上其他师傅怎么说吧:
资料查询
查文章
先是查了大量的有关宽字节注入的文章,发现都没有得到想要的答案:
发现绝大多数文章,要么没有提到宽字节的利用前提,文章重心一直放在怎么利用上,要么文章的相关措辞都是"mysql使用了GBK编码",也就是说这个编码前提是指的数据库的gbk编码,但是都没有指明该gbk编码具体到底在哪里,因为mysql配置编码的地方很多
拷打ChatGPT
ok,首先GPT排除了网站编码的可能性,它也认为是数据库的编码影响的,继续拷打
啊嘞?GPT给我说这四个配置项共同决定了数据库在处理字符时的编码行为,咋越来越离谱了呢,有点懵圈……
没事我直接写个宽字节注入的Demo自己做实验,看看到底是哪个编码影响的,不就行了吗?
动手实验
Demo
<?php
$servername = "localhost";
$username = "root";
$password = "root";
$dbname = "security";
$conn = new mysqli($servername, $username, $password, $dbname);
$conn->set_charset("gbk");
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$db_encoding = $conn->character_set_name();
$website_encoding = ini_get("default_charset");
echo "<p>Debug: Database Encoding - <strong>" . htmlspecialchars($db_encoding) . "</strong></p>";
$id = addslashes($_GET['id']);
$sql = "SELECT * FROM users WHERE id = '$id'";
echo "<p>Debug: Executing SQL Query - <strong>" . htmlspecialchars($sql) . "</strong></p>";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "ID: " . $row["id"] . " - Username: " . $row["username"] . " - Password: " . $row["password"] . "<br>
";
}
} else {
echo "0 results";
}
$conn->close();
?>
这段demo实现了宽字节注入的场景,并且添加了一些调试输出,打印了执行的sql语句,打印了数据库连接时采用的字符集编码
实验变量-各种gbk编码
首先看看有哪些地方能配置gbk编码,也就是首先找出所有的影响实验结论的变量,再逐一控制变量实验,就能找到到底哪一个才是宽字节注入的真正前提
1. 网站编码
网站编码(如<meta charset="UTF-8">
)主要用于控制前端显示,这个编码定义了网页上显示内容的字符编码方式,比如是 UTF-8、GBK 等。但它还会影响浏览器向服务器发送数据时的编码。
比如,当用户在网页上填写表单并提交时,浏览器会根据网页的编码(如 GBK)对数据进行编码后,再发送到服务器。这意味着网页编码决定了浏览器如何对用户输入进行编码。
服务器收到数据后,会根据约定的编码方式对数据进行解码。如果服务器预期收到的数据是 UTF-8 编码,而前端传过来的实际是 GBK 编码的数据,那么解码可能会失败。
关键点在于:无论前端数据传输使用的是什么编码,服务器端应用在接收到数据后可以根据需要进行重新编码和转换。所以,前端编码的影响主要是在数据进入服务器的那一刻,之后数据的编码转换完全由服务器端控制。
那么,从这里就已经可以看出,网站编码影响的是网站前端到服务器端之间传输的数据编码,并没有真正影响到数据库,因为和数据库直接交互的是服务器端,那么由此推测:网站编码不是宽字节注入的真正前提
我使用这个谷歌插件修改网站编码
2. 数据库字符集
这个gbk编码又是干什么的呢?这是数据库整理字符集编码:
数据存储:设置数据库(整理)字符集编码会影响存储的数据的实际编码方式。例如,如果表的字符集是utf8mb4
,插入数据时会按照utf8mb4
编码存储,读取时也会按utf8mb4
解码。
查询和排序:整理规则影响查询时的比较和排序方式。例如,如果表的整理规则是utf8_general_ci
,那么查询时会忽略大小写进行比较。
也就是这个数据库编码是纯只在数据库中的,只影响数据库中的数据存储、排序、整理的,也和网站编码一样,没有与服务器直接交互,仅仅影响数据库本身,那么推测:数据库编码也不是宽字节注入的真正前提
3. 表字符集
如果上述推测正确,那么同理可得,表的字符集仅仅影响表中数据以什么编码进行存储和读取,并不会直接影响与服务器的交互或者导致宽字节注入
4. 列字符集
如果推测正确,同上