Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Безопасная эксплуатация Apache, часть 9: атаки на PHP-приложения

Оригинал: Securing Apache, Part 9: Attacks that Target PHP-based Instances
Автор: Arpit Bajpai
Дата публикации: 1 Мая 2011 г.
Перевод: А.Панин
Дата перевода: 4 Февраля 2013 г.

Начало статьи: "Безопасная эксплуатация Apache, часть 9: атаки на PHP-приложения"

Атаки локального включения файлов (LFI)

Это другая разновидность атак включения файлов, аналогичная атакам обхода директорий, которые мы рассматривали в части 7 данной серии статей. (Для лучшего понимания обратитесь к данной статье.)

Эта атака может быть проведена в том случае, если у взломщика есть возможность посматривать файловую систему сервера и получать доступ к определенным файлам (скажем, к файлам в директории базы данных MySQL или к файлам passwd или shadow из директории /etc), информация из которых может помочь в осуществлении проникновения в веб-приложение или даже во входе в систему с использованием SSH. В ходе атаки используются идеи, описанные выше за тем исключением, что в данном случае с помощью строки URL производится включение файла, находящегося (по умолчанию) на сервере. Для начала рассмотрим пример кода, уязвимого для атак локального включения файлов:
<?php
$page = $_GET[page];
include($page);
?>

Данный код уязвим, так как значение переменной page не проходит проверку, а напрямую включается (исполняется). Представьте, что существует директория /test с файлом test.php в ней; пример строки URL для доступа к нему будет выглядеть следующим образом: www.example.com/test/test.php. Теперь представим, что в директории /test находится файл index.php, доступный с помощью следующей строки URL: www.example.com/test/index.php. Если файл index.php содержит следующий уязвимый код PHP, у нас будет возможность использовать строку URL www.example.com/test/index.php?page=../test/test.php и, таким образом, выполнить сценарий test.php. (Последовательность символов ../ служит для перехода в директорию уровнем выше.)

Если веб-сайт работает на сервере под управлением *NIX, у нас должна быть возможность произвести обход директорий до файла passwd и других с помощью подобной строки URL (предполагается, что файл index.php находится в директории /var/www/test): www.example.com/test/index.php?page=../../../etc/passwd. (Если вы не знаете, в какой директории на сервере находится файл test.php, можете попытаться подставлять последовательность символов ../ до того момента, как окажитесь в нужной директории.) Кроме файла /etc/passwd, взломщики также могут попытаться получить содержимое файлов /etc/shadow, /etc/group, /etc/security/group, /etc/security/passwd, /etc/security/user, /etc/security/environ, /etc/security/limits и /usr/lib/security/mkuser.default.

Чаще всего в качестве меры дополнительной безопасности разработчики просто добавляют расширение .php в конец строки URL, поэтому при запросе взломщиками файла /etc/passwd, как показано выше, запрос примет вид /etc/passwd.php. Этого файла не существует. Однако, для обхода этой системы защиты взломщик может просто использовать нулевой байт - т.е. добавить %00 в конец строки URL перед отправкой: /etc/passwd%00. Нулевой байт позволяет игнорировать часть строки после него, таким образом запрос примет вид: /etc/passwd.

Журнал Apache и атаки локального включения файлов

Описанный выше пример атаки позволяет взломщикам читать файлы, располагающиеся на сервере. Но существуют также способы выполнения необходимого злоумышленникам кода - в большинстве случаев с использованием файлов журнала Apache. Обычно Apache использует два файла журнала: access_log, содержащий все корректные запросы к веб-серверу и error_log, содержащий сообщения об ошибках. Apache позволяет настроить подробность записи событий в эти файлы - администраторы могут устанавливать, нужно ли записывать в файл информацию о браузере, ОС, предыдущей строке URL для каждого запроса. Так как взломщики могут контролировать то, какая информация передается серверу, они могут просто изменить информацию о браузере или ОС на корректный код PHP и передать его.

Так как Apache поддерживает виртуальные узлы, он может работать с несколькими доменами, используя один и тот же IP-адрес, поэтому администратор может задать имя и расположение файла журнала, следовательно сложно установить директорию хранения журнала событий Apache. Однако, эта информация очень важна для успешного завершения атаки. Ниже приведены стандартные директории, используемые для хранения файлов журнала событий Apache (в качестве имен файлов должны использоваться access.log и error.log): /etc/httpd/logs/, /opt/lampp/logs/, /usr/local/apache/log, /usr/local/apache/logs/, /usr/local/etc/httpd/logs/, /usr/local/www/logs/thttpd_log, /var/apache/logs/, /var/log/apache/, /var/log/apache-ssl/, /var/log/httpd/, /var/log/httpsd/ssl.access_log (в *NIX-системах) и C:\apache\logs, C:\Program Files\Apache Group\Apache\logs, C:\program files\wamp\apache2\logs, C:\wamp\apache2\logs, C:\wamp\logs, C:\xampp\apache\logs в Windows-системах.

Теперь давайте рассмотрим случай использования файла error_log в ходе атаки. Взломщики используют запрос в отношении уязвимого к атакам локального включения файлов сервера со следующей строкой URL: http://www.example.com/<?php+$s=$_GET;@chdir($s['x']);echo@system($s['y'])?>.

После этого они пытаются получить доступ к вставленному в файл журнала событий коду PHP с помощью запроса: http://www.example.com/test/index.php?page=/var/log/apache/logs/error_log%00&x=/&y=uname.

В итоге взломщиками будет получена системная информация от сервера. В ходе атаки использовалась особенность работы сервера, заключающаяся в том, что так как файла <?PHP $s=$_GET;@chdir($s['x']);echo@system($s['y'])?> не существует на сервере, данный код PHP добавляется в файл журнала error_log, а затем исполняется при помощи запроса с использованием второй строки URL.

Теперь рассмотрим второй случай с использованием файла access_log в ходе атаки. В данном случае взломщики подменяют значение параметра User-Agent, отправляемое в заголовках их браузерами на PHP-код (как и в предыдущем примере) с помощью расширения Firefox с названием "User Agent Switcher". Для записи в журнал событий сервера измененной строки User Agent, они просто заходят на сайт http://www.example.com. После этого они включают файл access_log для выполнения кода (строка URL аналогична предыдущему случаю за исключением изменившегося имени файла).

Мероприятия по повышению безопасности

Большинство мероприятий для защиты от атак локального включения файлов идентичны мероприятиям, описанным в части 7 данной серии статей (атаки обхода директорий). Однако, кроме них должны быть приняты следующие меры предосторожности:
  1. В общем случае лучшим способом защиты от атак включения файлов является отказ от передачи данных, введенных пользователем, или производных данных для динамического исполнения или на вход функции include.
  2. Если это по какой-либо причине невозможно реализовать, то вводимые данные должны подвергаться строгой проверке для того, чтобы исключить любые варианты атак.
  3. Если это возможно, следует использовать списки известных корректных значений (такие, как списки всех языков или расположений файлов, поддерживаемых приложением) и отклонять любые вводимые данные, не находящиеся в списках. После этого следует проверять символы из введенных строк на безопасность и принимать только буквы и числа, исключив символ пробела.

Инструменты

  • lfimap является сценарием на языке Python для проверки веб-приложений на наличие уязвимостей локального включения файлов. Он использует список директорий и пытается перемещаться по нему с помощью вставки путей в определенные параметры.
  • Darkjumper будет пытаться найти все веб-сайты, расположенные на том же сервере, что и целевой веб-сайт, а также проверит веб-сайт на на уязвимость к атакам на основе SQL-инъекций, удаленного включения файлов, локального включения файлов, слепых SQL-инъекций, и.т.д.
  • Simple Local File Inclusion Exploiter также является сценарием на языке Python, позволяющим вам идентифицировать страницу с уязвимостью к атакам локального включения файлов.

Проверка на уязвимость к атакам включения файлов

Для проверки, уязвимо ли ваше приложение к атакам удаленного включения файлов, вы можете выполнить следующие действия:
  • Передайте в составе каждого параметра строку URL, указывающую на ресурс на веб-сервере, находящийся по вашим контролем, и установите, были ли произведены какие-либо запросы от сервера к целевому приложению.
  • Если описанная выше проверка не увенчалась успехом, попробуйте передать строку URL, содержащую несуществующий IP-адрес и установить, истекло ли время ожидания при попытке сервера соединиться с этим адресом.
Для проверки на уязвимость к атакам локального включения файлов, выполните следующие действия:
  • Введите известное имя сценария в поля ввода и установите, не было ли изменений в процессе работы приложения.
  • Введите известное имя статического файла в поля ввода и установите, выводится ли его содержимое вместе с ответом приложения.
  • Если приложение уязвимо к атакам локального включения файлов, попытайтесь получить доступ к важным функциям или ресурсам, которые недоступны напрямую с помощью веб-сервера.

Уязвимости загрузки файлов

Всегда, когда вы позволяете пользователям загружать файлы, такие, как изображения, принимаемые приложением гостевой книги, вы добавляете уязвимость в ваше приложение. Пользователи могут загрузить вирус, руткит или другой вредоносный сценарий так же просто как безобидную картинку. Механизм загрузки файлов может быть главной угрозой безопасности и без лишних сложностей использоваться для получения доступа к файловой системе сервера, поддерживающего работу веб-приложения. Для лучшего понимания методов проведения атак против механизма загрузки файлов, рассмотрим простой сценарий атаки.

Сценарий атаки 3

Предположим, что веб-приложение использует следующий код PHP для загрузки файлов (upload.php):
<?php
$target_path = "uploads/";
$target_path = $target_path . basename( $_FILES['uploadedfile']['name']);
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path))
{
    echo "The file ". basename( $_FILES['uploadedfile']['name']).
    " has been uploaded";
}
else
{
    echo "There was an error uploading the file, please try again!";
}
?>
Данный сценарий работает вместе со следующей HTML-формой:
<form enctype="multipart/form-data" action="uploader.php" method="POST">
    <input type="hidden" name="MAX_FILE_SIZE" value="100000" />
    Choose a file to upload: <input name="uploadedfile" type="file" /><br />
    <input type="submit" value="Upload File" />
</form>
Когда PHP принимает POST-запрос с типом кодировки "multipart/form-data", создается временный файл со случайным именем в директории для временных файлов (т.е. /var/tmp/php4vlktb). PHP также заполняет глобальный массив $_FILES информацией о загруженном файле:
  • $_FILES['uploadedfile']['name']: Оригинальное имя файла на компьютере клиента.
  • $_FILES['uploadedfile']['type']: MIME-тип файла.
  • $_FILES['uploadedfile']['size']: Размер файла в байтах.
  • $_FILES['uploadedfile']['tmp_name']: Временное имя загруженного файла, под которым он сохранен на сервере.

Функция PHP move_uploaded_file переместит временный файл по заданному пользователем пути. В данном случае путь для перемещения файла находится в пределах корневой директории веб-сервера. Следовательно, файл будет доступен при использовании строки URL, похожей на следующую: http://www.example.com/uploads/temp-uploads/uploadedfile.jpg.

В этом простом примере не накладывается ограничений на тип загружаемых файлов, поэтому взломщик может загрузить файл с вредоносным кодом PHP или .NET, что приведет к компрометации сервера. В таком случае взломщик может просто загрузить вредоносные сценарии c99 shell или r57 shell и получить контроль над сервером.

Однако, даже если в целях безопасности проверка расширения файла производится перед загрузкой, взломщик может также обойти ее, использовав нулевой символ %00. Все что требуется сделать, это выбрать файл PHP для загрузки, не нажимая на кнопку "Загрузить". Путь к выбранному для загрузки файлу будет отображен и для *NIX-систем будет выглядеть как /Users/username/exploit.php, а для Windows-систем как c:\exploit.php. На этом этапе нужно вручную добавить к строке нулевой символ с каким-либо последующим расширением изображения, например, /Users/username/exploit.php%00.jpg или c:\exploit.php%00.jpg.

После нажатия на кнопку "Загрузить" сервер проверит расширение, посчитает, что производится загрузка изображения и выведет сообщение, подобное следующему: "Спасибо за загрузку вашего изображения!". Как только файл будет загружен, появится возможность выполнения вредоносного кода на сервере.

Другим популярным способом защиты от исполнения загруженных файлов является запрет на исполнение сценариев в директории загрузок с помощью файла .htaccess. Стандартный файл .htaccess для этой цели должен содержать следующий код:
AddHandler cgi-script .php .php3 .php4 .phtml .pl .py .jsp .asp .htm .shtml .sh .cgi
Options -ExecCGI
Код, приведенный выше, использует список запрещенных расширений и не особенно безопасен сам по себе. Взломщик может просто обойти такие проверки, загрузив файл с названием .htaccess, содержащий код, подобный следующему:
AddType application/x-httpd-php .jpg

Эта строка указывает Apache, что необходимо исполнять файлы изображений с расширением .jpg так, как будто это сценарии PHP. Теперь взломщик может загрузить файл с расширением .jpg, содержащий код PHP. Так как загружаемые файлы могут перезаписывать и перезаписывают существующие, злоумышленники могут без лишних сложностей заменить файл .htaccess своей модифицированной версией, позволяющей исполнять определенные сценарии для последующей компрометации сервера.

Мероприятия по повышению безопасности

Механизм загрузки файлов является ключевой функцией многих веб-приложений, а с учетом следующих мер предосторожности он может быть реализован максимально безопасно:
  1. Не используйте заданных пользователями имен файлов в вашей системе. Наоборот, генерируйте свои непредсказуемые имена файлов. Подойдет имя в виде хэш-значения (md5/sha), так как его просто проверить (это просто строка шестнадцатеричных чисел). Возможно, к имени следует добавлять порядковый номер или время для предотвращения случайных коллизий.
  2. В том случае, если нет возможности просмотра загружаемых файлов модератором, важно сделать возможной загрузку файлов только после прохождения аутентификации. В этом случае, по крайней мере, возможно отследить того, кто загрузил интересующий файл.
  3. Следует фиксировать данные (такие, как время, IP-адрес клиента и имя пользователя) при загрузках файлов и наступлении других событий. Это поможет вам узнать, какие типы атак применялись против вашего сервера и были ли эти атаки успешными.
  4. Если это возможно, следует также проверять загружаемые файлы на наличие вредоносного программного обеспечения; следует загружать файлы в директорию вне корневой директории веб-сервера.
  5. Не стоит полагаться только на проверку загружаемых файлов на стороне клиента, так как этой проверки не достаточно. В идеальном случае следует реализовать проверку и на стороне клиента и на стороне сервера.
Примечание: Еще раз подчеркну, что ни я, ни журнал LFY не несем ответственности за недобросовестное использование представленной в статье информации. Напротив, техники атак описываются для того, чтобы предоставить вам знания, необходимые для защиты вашей инфраструктуры. Пожалуйста, используйте добросовестно описанные выше инструменты и техники.

Мы поговорим о других опасных атаках на веб-приложения и Apache в следующей статье.

Всегда помните: нужно знать все о взломе, но не заниматься им.

Дополнительные ресурсы

Я настоятельно рекомендую прочитать пост из блога с названием "Remote File Inclusion Attacks - pt1".

Следующая статья серии: "Безопасная эксплуатация Apache, часть 10: модуль mod_security"