|
Песнь о багах в PHP или админ в шкуре скрипт-кидди Как обезопасить свой сервер с PHP Loh Matov (blabl@7350.org) Xakep, номер #050, стр. 050-066-3 /file.php?file=aaaaaaaaaaaaaaaaaaaaаааааааа Если скрипт уязвим, то ответом будет предупреждение о том, что не удается подключить файл: Warning: Failed opening 'aaaaaaaaaaaaaaaaaaaa' for inclusion (include_path='.:/usr/local/php-4.2.3/lib/php') in /opt2/home3/prop/public_html/file.php on line 7 В PHP до версии 4.0.3pl1 включительно была такая бага, как null-byte. Это должно быть всем знакомо еще со времен родного перла. После того, как о ней сообщили, ошибка была исправлена. В некоторых функциях она сохранилась и в более поздних версиях. Это возможно и сейчас, но "эксплоитировать" их очень сложно... При старом PHP такая ошибка реализовывается крайне просто. Допустим, на сервере есть скрипт с куском кода такого плана (порывшись в сырцах php-nuke, найдешь много подобного): <? .. fopen("$file.php"); ?> Переменная $file не определена ранее и передается как параметр, то есть мы можем ее задать как script?file=../../../../../../etc/passwd%00, получится строка: <? .. fopen("../../../../../../etc/passwd%00.php"); ?> Соответственно, открывается файл с пользователями этого сервера вместо скрипта. До сих пор очень много серверов используют старые версии пхп, скорее всего это ленивые админы. Я даже видел пхп версии 2.0. А если попался ленивый админ, то задача еще более упрощается. Теперь о сочетании функций eval(), print() и echo(). Функция eval() появилась в пхп3, она представляет текст в виде кода, который затем исполняется. Это важно в тех случаях, когда кусок кода хранится в базе данных. В php3 она не возвращает ничего. В php4 она возвращает NULL, если код ничего не возвращает. Чем нам полезна эта функция? А тем, что это потенциальная дыра, code injection, как и с функцией include(), только несколько другого плана. Вот пример из phpBB 1.4: <example code from page_header.php> if ($new_message != 0) { eval($l_privnotify); print $privnotify; } </end example code> Переменная $l_privnotify не определена ранее, а значит, мы можем определить ее в параметрах, передаваемых к скрипту, scripts.php?l_privnotify=phpinfo(). Функция phpinfo() выдает все, что нужно для успешной атаки. Вплоть до предпоследней версии PHP(4.2.2), существует ошибка, исправленная только в 4.2.3. Суть ее состоит в том, что можно обойти "safe mode" и выполнить произвольный код без ограничений "safe mode". Ошибка находится в пятом аргументе функции mail(). Эксплоит можно найти на security.nnov.ru. Вообще, пятый аргумент функции mail() используют достаточно редко, и здесь я привожу эту ошибку только для того, чтобы оградить тебя от этой досадной ошибки и помочь сделать код более безопасным. Еще один путь обхода "safe mode". Ошибка содержалась в функции getpw() и ей подобных. Эта функция показывает имя пользователя по его UID, но она не проверяет, включен ли режим "safe mode" и ограничение на выход из домашней директории пользователя open_basedir. Вот простой кусок кода, который покажет всех пользователей в системе: |