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

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

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

Это связано с тем, что если ваш escaper настроен неправильно, он увидит 0x27 и попытается избежать его, чтобы он стал \xbf\x5c\x27 . Тем не менее, \xbf\x5c на самом деле является одним символом в этих кодировках, поэтому цитата ( 0x27 ) остается 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 интерпретирует это совершенно по-другому?

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

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

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

На данный момент ваш вопрос становится таким же простым:

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

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

0x815C 0x2015 # ГОРИЗОНТАЛЬНЫЙ БАР

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

Некоторые документы Oracle подтверждают, что 0x815c является 0x815c и тем же символом для cp932 и sjis и 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"); }