Local File Inclusion (LFI) — это возможность использования локальных файлов сервера. Уязвимость позволяет удаленному пользователю получить доступ с помощью специально сформированного запроса к произвольным файлам на сервере, в том числе потенциально содержащим конфиденциальную информацию.
Возникает подобная уязвимость в том случае, если при реализации веб-приложения используются небезопасные функции, например, include
, позволяющие включать контент на страницу из локального файла. В нашем случае это выглядит следующим образом:
<?php
$file = $_GET['file'];
if(isset($file))
{
include("$file");
}
?>
<b> <p align="center">Пример веб-приложения, доступный в Интеренте.</p></b>
Благодаря строчке include(“$file”)
****в содержимое страницы будет включаться значение GET-параметра file
. Теперь, используя эту уязвимость, нам будут возвращаться локальные файлы, которые мы укажем в параметре.
Статья носит информационный характер. Не нарушайте законодательство.
Как обнаружить уязвимость? Если указать в потенциально уязвимом параметре включение какого-то локального файла, например, index с любым расширением, и этот файл откроется, то однозначно можно утверждать, что параметр отвечает за подкачку файла. Сделать это можно как вручную, так и с помощью различных автоматизированных инструментов, например, сканером уязвимостей Wapiti, или специализированным инструментом LFISuite, который разработан именно под поиск и эксплуатацию LFI-уязвимостей.
Какие здесь могут быть подводные камни? Например, наличие фильтрации, которая будет подставлять в окончание строки расширение файла, например, .php. Таким образом, при попытке включения в страницу файла /etc/passwd мы получим в адресной строке file=/etc/passwd.php, а содержимое этого файла не будет отображаться на странице, так как файла не существует. Но такой фильтр можно обойти с помощью так называемого нулевого байта, который будет «отсекать» все, что будет идти после него. Дело в том, что вся адресная строка при передаче HTTP-запроса кодируется в URL-encode, и в этой кодировке нулевой байт выглядит как %00. Таким образом, строчка /etc/passwd%00.php будет преобразована в /etc/passwd. Однако стоит отметить, что данная проблема является довольно известной и исправлена в версии PHP 5.3+
Другой вариант обхода фильтрации — использование php filter. В параметре, отвечающем за включение файлов, пишем не просто путь до файла, который мы хотим включить, а путь до файла с использованием этой функции. Теперь запрос, который мы будем отправлять, имеет вид:
http://site.test.lan/index2.php?file=php://filter/convert.base64-encode/resource=/etc/passwd
И теперь на странице браузера мы увидим не содержимое файла, а его исходник в кодировке base64, который можно декодировать.
С основными моментами уязвимости LFI разобрались, и теперь понимаем, что при ее эксплуатации можно прочитать локальный файл на удаленном сервере. Но у LFI есть интересная особенность, позволяющая не просто прочитать локальные файлы, а скомпрометировать сервер.
Думаю, стоит сразу оговориться, что уязвимость не новая, но тем не менее она до сих встречается и может представлять серьезную угрозу для безопасности веб-сервера. При взаимодействии с веб-приложением любой наш запрос записывается в журналы веб-сервера, как правило, это файлы /var/log/nginx/access.log или /var/log/nginx/error.log если, например, используется веб-сервер Nginx, но названия конечных файлов, разумеется, могут отличаться.
Теперь, составив специальный запрос, мы создадим веб-шелл на сервере, записав его в access.log. Для отправки запроса будем использовать инструмент Burp Suite, позволяющий в режиме реального времени перехватывать и редактировать запросы.
Наш веб-шелл <?php system($_GET[cmd]); ?> записан в журнале веб-сервера и готов к использованию.
Почему использовался именно параметр User-Agent? Как уже говорилось ранее, адресная строка кодирует информацию с помощью URL-encode, поэтому для передачи php-кода нужно использовать заголовки, а так как в access.log точно пишется User-Agent, то и используем его. Обратившись к нашему веб-шеллу, получаем возможность выполнять различные команды через параметр cmd:
http://site.test.lan/index2.php?file=/var/log/nginx/access.log&cmd=ls /