Всем привет, сегодня был напряжённый день, так что самое время решить задачку на информационную безопасность web-серверов. Сегодня задачка с портала root-me.org, называется "SQL injection - Authentication - GBK". За решение задачки дают 30 баллов, ближе к среднему уровню.
По названию становится понятно, что иметь дело придётся с SQL инъекцией.
SQL injection — это атака на базу данных, которая позволит выполнить некоторое действие, которое не планировалось создателем скрипта. Атака осуществляется путём внедрения (инъекции) стороннего кода в SQL запрос.
В подсказках много ссылок на статьи по SQL инъекциям, но самая главная подсказка в названии и описании: "Вы говорите по-китайски?". А ещё аббревиатура GBK.
GBK (Guojia Biaozhun Kuozhan) — расширенный национальный стандарт. Зарегистрированное интернет-имя кодировки, распространённой в Китайской Народной Республике, в которой используется китайское письмо.
https://en.wikipedia.org/wiki/GBK_(character_encoding)
Можно сделать вывод, что уязвимость будет связана с мультибайтовой SQL инъекцией.
Ссылки
https://raz0r.name/vulnerabilities/sql-inekcii-svyazannye-s-multibajtovymi-kodirovkami-i-addslashes/
Решение
Переходим на страницу задания:
http://challenge01.root-me.org/web-serveur/ch42/
Здесь у нас форма логина, по-французски, но это не имеет значения. Над формой ссылка, посмотрим.
Список пользователей. Есть admin с идентификатором 1. Отлично, имя пользователя мы теперь знаем. Видимо, под ним мы и должны выполнить вход.
Обычный способ сделать инъекцию в SQL код — это использовать символ кавычки. Допустим, у нас есть запрос:
SELECT * FROM table1
WHERE user=' + user + ' AND Passsword = ' + password + '
Если в пароль вставить строку:
' OR 1=1; --
То получится:
SELECT * FROM table1
WHERE user='admin' AND Password = '' OR 1=1; --'
Т.е. получится запрос, который будет всегда верен, независимо от указанного пароля.
Можно подобрать комбинацию и для поля имени пользователя, к примеру:
admin' OR 1=1; -- '
Получится:
SELECT * FROM table1
WHERE user='admin' OR 1=1; -- ' ' AND Passsword = ' + password + '
Проверим эту комбинацию. Ничего не вышло, но не расстраиваемся. Это было бы слишком просто.
Для защиты от SQL инъекций кавычка в полях форм фильтруется различными способами. К примеру, addlashes() и magic_quotes_gpc.
Функция addlashes() возвращает строку с добавленными обратными слешами перед специальными символами, которые необходимо экранировать. magic_quotes_gpc — конфигурационный параметр PHP, который делает то же самое. Он влияет на то, как будут обрабатываться специальные символы, содержащиеся в данных, передаваемых пользователем (массивы $_GET, $_POST, $_COOKIE). При magic_quotes_gpc = 1 эти спецсимволы автоматически экранируются интерпретатором PHP, перед каждым таким символом также добавляется обратный слеш. Специальные символы:
- одинарная кавычка ( ' ) — 0x27
- двойная кавычка ( " ) — 0x22
- backslash (\) — 0x5c
- NUL (NUL байт) — 0x00
Идея прекрасная, но в некоторых редких случаях при определённых условиях такую фильтрацию кавычек можно обойти. Например, если уязвимый SQL сервер использует определенные наборы символов, такие как набор символов SJIS, BIG5 и GBK. В этом случае addlashes() и magic_quotes_gpc становятся бесполезными.
Эти функции просто находят байты одинарной кавычки (0x27), двойной кавычки (0x22), бэкслэша (0x5c), null байта (0x00) и добавляют перед ними байт обратного слэша (0xbf). А сочетание байтов бэкслеша и обратного слеша (0xbf5с) является легитимным символом в кодировке GBK, и это можно использовать при инъекции. Разберём конкретный пример. Раз мы знаем китайский язык, то возьмём любой символ GBK, который оканчивается на 5c. Нам отлично подойдёт символ 乗 с кодом 0x815c.
А теперь посмотрим, что получится, если мы укажем сочетание этого символа с одинарной кавычкой (乗'):
0x815c & 0x27 = 0x815c27
Этот набор байтов прогонится через обработку addlashes() или magic_quotes_gpc, которые найдут запрещённые байты (0x5c и 0x27) и добавят перед ними байт обратного слэша (0xbf), получится:
0x81bf5cbf27 = 0x81bf & 0x5cbf & 0x27
И получится два символа GBK плюс байт одинарной кавычки (0x27). Формируем инъекцию:
admin乗' OR 1=1 -- 乗'
Пробуем.
Мы успешно залогинились под админом и получили флаг. Валидируем.
Флаг подходит, зарабатываем 30 очков. Вот так мы выучили китайский язык.
Безопасность
Можно было использовать в инъекции любой символ GBK, который заканчивается на байт 0x5c:
admin乗' OR 1=1 -- 乗' admin俓' OR 1=1 -- 俓' admin僜' OR 1=1 -- 僜'
- В целях безопасности рекомендуется использовать функцию mysql_real_escape_string() вместо addslashes() и mysql_escape_string().
- Защищайтесь от SQL инъекций. Одним из хороших способов является использование "параметризированных запросов".
- Не используйте стандартные логины.
- Названия полей таблицы не имеет смысла усложнять, инъекцию можно проводить по идентификаторам колонок.