Тестирование веб-приложений на присутствие LFI-уязвимостей

Введение 

Цель данного документа – помочь пентестерам и студентам в поиске LFI-уязвимостей, которые обычно обнаруживаются во время тестирования веб-приложений при помощи техник, описанных в этой статье. Кроме того, описанные методы обычно используются участниками различных хакерских конкурсов в формате CTF (Capture the Flag; Захват флага).

Что такое LFI-уязвимость?

LFI-уязвимости (Local File Inclusion; Включение локальных файлов) позволяют злоумышленникам через браузер подключать файлы на сервере. Эта брешь присутствует там, где отсутствует корректная обработка входящих данных, и злоумышленник может манипулировать входящей информацией, инжектировать символы типа path traversal и включать другие файлы с веб-сервера.

Пример уязвимого кода

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

<?php
$file = $_GET['file'];
if(isset($file))
{
include("pages/$file");
}
else
{
include("index.php");
}
?>

Нахождение LFI-уязвимостей внутри веб-приложений

Проблемы, связанные с включением локальных файлов, легко найти и эксплуатировать. Любой скрипт, который подключает файл с веб-сервера, является хорошим кандидатом для поиска LFI-уязвимостей. Например:
/script.php?page=index.html

Пентестер может попробовать поэксплуатировать эту брешь при помощи манипуляции параметром, связанным с местонахождением файла. Например, так:

/script.php?page=../../../../../../../../etc/passwd

Трюк, показанный выше, позволяет посмотреть содержимое файла /etc/passwd в системах на базе UNIX / Linux.

На рисунке ниже показан пример успешной эксплуатации LFI-уязвимости в веб-приложении:

 
Рисунок 1: Вывод содержимого файла /etc/passwd в системе, содержащей LFI-уязвимость

PHP-обертки

В интерпретаторе PHP есть несколько оберток, которые можно использовать для обхода фильтров входящих данных.

Обертка expect://

Обертка expect:// позволяет выполнять системные команды. К сожалению, этот модуль по-умолчанию не разрешен.

Пример:

php?page=expect://ls

Обертка file://

В примере ниже полезная нагрузка отправляется на сервер через POST-запрос (при помощи конструкции php://input выполняем команду ls).

/fi/?page=php://input&cmd=ls

Запрос:

 
Рисунок 2: POST-запрос, содержащий конструкцию php://input

Ответ веб-приложения:

 
Рисунок 3: Результат выполнения команды ls

Обертка php://filter

Обертка php://filter позволяет пентестеру подключать локальные файлы и кодировать выходной поток в base64. Таким образом, чтобы получить читабельное содержимое, нужна дешифровка.

Пример:

vuln.php?page=php://filter/convert.base64-encode/resource=/etc/passwd

 
Рисунок 4: Отображение файла /etc/passwd, закодированного в base64

Декодируем файл /etc/passwd при помощи следующей команды:

 
Рисунок 5: Раскодированный файл /etc/passwd

Обертку php://filter можно использовать и без кодирования выходного потока:

Пример:

?page=php://filter/resource=/etc/passwd

 
Рисунок 6: Отображение незакодированного файла /etc/passwd при помощи обертки php://filter

Обертка zip://

Обертка zip:// обрабатывает загруженные .zip файлы на стороне сервера. При помощи данной функции пентестер может загрузить .zip файл, используя уязвимую функцию, предназначенную для загрузки, а затем осуществить выполнение через распаковщик zip и локальное включение. Типичная атака выглядит следующим образом:

  1. Создаем обратный PHP-шелл.
  2. Упаковываем файл в .zip архив.     
  3. Загружаем сжатую полезную нагрузку на сервер.
  4. Используем обертку zip:// для распаковки полезной нагрузки при помощи следующей команды: php?page=zip://path/to/file.zip%23shell
  5. После выполнения команды из пункта 4 появится файл shell. Если сервер не принимает файл shell, поменяйте имя на shell.php.

Если сервер не принимает .zip архивы, можно попробовать обойти функцию загрузки файлов.

Включение локальных файлов через /proc/self/environ

Если получается подключение /proc/self/environ при помощи бреши, связанной с включением локальных файлов, возможна атака через заголовок User Agent. Как только код инжектирован в заголовок User Agent, в дальнейшем используется LFI-уязвимость для выполнения /proc/self/environ и перезапуска переменных окружения, что, в свою очередь, позволяет запустить обратный шелл.

Полезные трюки

Далее будут приведены методы, которые полезны в сочетании с техниками, указанными выше:

Пример:

<? system('uname -a');?>

Добавление пустого байта

Инжектирование пустого байта помогает обойти фильтры при помощи добавления к URL закодированного пустого байта (например, %00). Обычно этот трюк позволяет обойти базовые фильтры путем добавления пустых символов, которые допустимы и не обрабатываются серверной частью веб-приложения.

Практические примеры, связанные с инжектирование пустого байта, с целью включения локального файла:

vuln.php?page=/etc/passwd%00
vuln.php?page=/etc/passwd%2500

Техники, связанные с укорачиванием

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

Примеры трюков, связанных с укорачиванием:

vuln.php?page=/etc/passwd…………………………………………………………………………….
vuln.php?page=../../../../../../../../../../../../../../../../../../../../../../../../etc/passwd
vuln.php?page=/etc/passwd/../../../../../../../../../../../../../../../../../..

Инжектирование в лог-файл

Метод основан на внедрении исходного кода через другие внешний службы в лог-файл целевой системы. Например, инжектирование PHP-кода обратного шелла в URL сподвигнет службу syslog на создание записи в логе доступа веб-сервера Apache записи с ошибкой 404 (страница не найдена). Затем лог апача можно распарсить при помощи ранее обнаруженной LFI-уязвимости и запустить инжектированной PHP-код.

После добавления исходного кода в лог(и) целевой системы следующий шаг – поиск местонахождения этих файлов. После обнаружения типа целевой системы и веб-сервера следует поискать логи по стандартным путям, используемым в данной конкретной системе и веб-сервере. Полезные нагрузки, заточенные под LFI-уязвимость в сочетании с приложением Burp Intruder можно использовать для нахождения путей, где лежат логи в целевой системе.

Некоторые популярные внешние службы в системах Linux / UNIX перечислены ниже:

Apache / Nginx

Инжектируем код в журнал доступа или журнал ошибок веб-сервера при помощи netcat. После успешного внедрения парсим файл серверного лога, используя ранее обнаруженную LFI-уязвимость. Если журнал доступа / ошибок слишком длинный, на запуск инжектированного кода может уйти некоторое время.

Отправка обратного шелла по электронной почте

Если целевая машина перенаправляет почту напрямую или через другую машину в сети, а также хранит почту пользователя www-data (apache) в системе, становится возможной атака через отправку обратного шелла при помощи электронной почты. Если для текущего домена отсутствуют MX-записи, но есть внешняя служба SMTP, можно подключиться к целевому почтовому серверу и отослать почту пользователю www-data / apache. Почта отсылается пользователю, от имени которого запускается apache (например, www-data), с целью проверки, что права файловой системы позволяют получить доступ на чтение к файлу /var/spool/mail/www-data, который содержит инжектированный обратный шелл код, написанный на PHP.

Вначале проверяем присутствие пользователя www-data при помощи скрипта smtp-user-enum:

 
Рисунок 7: Проверка присутствия пользователя www-data

На рисунке ниже показан процесс отправки почты пользователю www-data через telnet:

 
Рисунок 8: Процесс пересылки обратного PHP-шелла через SMTP при помощи telnet

 
Рисунок 9: Включение файла www-data, который содержит код отосланного обратногоPHP-шелла

В результате обратный шелл подключается к netcat-слушателю:

 
Рисунок 10: Подсоединение обратного PHP-шелла к netcat

Ссылки

Информационные источники, используемые в этой статье:

https://highon.coffee/blog/lfi-cheat-sheet/
https://www.owasp.org/index.php/PHP_File_Inclusion

Уязвимое приложение DVWA (использовалось в примерах с демонстрацией LFI-уязвимостей): http://www.dvwa.co.uk/