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