Недавно на milw0rm’е был опубликован эксплоит для популярного форумного движка Simple Machines Forum версии 1.1.4, являющейся довольно распространенной на просторах интернета. Уязвимость связана с реализацией SQL-инъекции, основанной на особенностях мультибайтовых кодировок, которые позволяют обойти экранирование опасных символов с помощью функции addslashes().
Итак, уязвимость возможна благодаря тому, что при установке SMF переменная $db_character_set не записываются в конфигурационный файл, если пользователь оставил кодировку соединения с базой данных по умолчанию (в SMF это UTF-8). При включенной опции register_globals злоумышленник может назначить этой переменной любое значение, состоящее из буквенно-цифровых символов. Таким образом, вместо стандартной кодировки можно назначить любую другую, включая определенные мультибайтовые кодировки, позволяющие обойти фильтрацию входящих данных посредством addslashes() на символ одинарной кавычки. К таким кодировкам относятся SJIS, BIG5 и GBK. В чем же заключается ошибка addslashes()? Дело в том, что addslashes() просто добавляет обратный слэш перед одинарными (0x27) и двойными кавычками (0x22), перед бэклсэшем (0x5c) и перед null байтом (0x00), причем эта функция не проверяет какой символ в итоге будет создан. Например, в кодировке GBK мультбайтовый символ 0xbf27 не является допустимым, однако 0xbf5c воспринимается как приемлемый. Точно так же и для BIG5: 0xa327 – неправильный символ, но после того, как addslashes() добавит слэш перед 0x27, у нас получится следующая последоавтельность байтов: 0xa35c27. 0xa35c является корректным мультибайтовым символом для кодировки BIG5, т.е. он будет рассматриваться как один символ, в то время как 0x27 станет самостоятельным и одинарная кавычка останется без экранирования.
Рассмотрим простой пример:
<?php $_POST['username'] = chr(0xa3) . chr(0x27) . ' OR 1=1 /*'; $_POST['password'] = 'blah'; $username = addslashes($_POST['username']); $password = addslashes($_POST['password']); $sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'"; $result = mysql_query($sql); if (mysql_num_rows($result)) { /* авторизован */ } else { /* не авторизован */ } ?>
0xa327 после обработки функцией addslashes() превратится в 0xa35c27. Таким образом, в $username окажется:
переданное пользователем значение + мультибайтовый символ 0xa35c + кавычка (0x27) + SQL-выражение OR 1=1 /*, которое позволит авторизоваться без правильного пароля.
Несмотря на то, что UTF-8 относится к мультибайтовым кодировкам (т.е. один символ может занимть более одного байта), данной уязвимости эта кодировка не подвержена, так как этот вид атак возможен для любой кодировки, в которой мультибайтовым считается символ заканчивающийся на 0x5c. UTF-8 к таковым не относится в силу того, что в ней каждый последующий байт мультибайтового символа должен иметь значение больше 128 в десятичном представлении. 0x5c в десятичном виде равняется 92, что меньше 128.
Автор эксплоита указывает на то, что в SMF имеется множество SQL-инъекций, возможных благодаря неправильной обработке опасных символов функцией addslashes(). Похожая уязвимость была найдена в прошлом году в WordPress. Однако уязвимы были лишь те блоги, где использовались мультибайтовые кодировки (например китайские сайты) и изменить ее удаленно атакующий не мог, чего не скажешь о недавно опубликованной уязвимости в SMF.
В целях безопасности рекомендуется использовать функцию mysql_real_escape_string() вместо addslashes() и mysql_escape_string(). Функция mysql_real_escape_string() учитывает кодировку текущего соединения с базой данных, поэтому ей необходимо передавать указатель соединения. Надеюсь теперь понятно какой смысл разработчики вкладывают в real в названии функции =)
Leave a Reply