PHP include уязвимость: от теории к практике. Создадаем страницу «Портфолио». Локальный инклуд файлов при добавлении расширения в скрипте

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

Проще говоря, это уязвимость открытия файлов с сервера + недостаточная фильтрация, что позволяет открывать произвольный файл.

Поиск file inclusion

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

Поиск параметров
Для поиска параметров есть два варианта: автоматический или ручной поиск.

Автоматический поиск
Автоматический поиск можно осуществить тем же spider"ом в burpsuite. Вы можете у нас в вики найти статью burpsuite.

Ручной поиск
Сейчас я поговорю о ручном поиске. Предположим, что мы нашли GET параметр:

Http://site.ru/folder/index.php?file=gallery

Подставим под параметр строку "index":

Http://site.ru/folder/index.php?file=index

Если у вас открылся какой то из файлов index.(любое расширение), находящихся на сайте, то тут мы уже однозначно можем утверждать, что файл отвечает за подкачку файла.

Именно такие параметры нам и нужны.

Определение фильтров
После того, как мы получили список параметров, нужно проверить, есть ли у них фильтрация.

Нулевая фильтрация
Попробуем подкачать файлы, которые не рассчитывали показывать=)

Аналогом такого файла в линкусе является файл /etc/passwd

данном случае за строку с параметром мы взяли http://site.ru/folder/index.php?file=index.html)

Попробуем его подкачать:

Http://site.ru/folder/index.php?file=/../../../../../../etc/passwd

Объясняю что происходит - переход в папку /../ означает поднятие по иерархии вверх (точнее это уязвимость path traversal). Т.к. папка etc лежит в корневой папке, то мы должны ее достичь угадыванием: то есть чем чаще мы поднимаемся вверх, тем выше шанс, что мы окажемся в корневой папке (то мы должны написать несколько раз /../).

Если файл показался. То считайте, что вы нашли LFI. В этом случае фильтр вообще отсутствует.

Нулевой байт
В данном случае за строку с параметром мы взяли http://site.ru/folder/index.php?file=index , то есть с отсутствующим окончанием.
Но даже при отсутствии фильтра могут быть проблемы. Например в конце параметра может приписываться окончание.

Например с запросом /../../../../../../etc/passwd может преобразоваться в

/../../../../../../etc/passwd.php

Но и на этот раз есть вариант исправить строку.В старых версиях PHP остался такой недостаток, как Null Byte Injection .
Один из них - это приписывание нулевого байта. Параметры, при передаче по http, зашифровываются в url шифрование. И в этой кодировке нулевой байт выглядит именно в %00.

А т.к. в PHP и многих других языках чтение строки идет именно до нулевого байта, то мы можем приписать его в середину строки, чтобы следующая часть строки отбрасывалась.

В данном случае если мы впишем в параметр /../../../../../../etc/passwd.php%00 , то получим следующую строку:

Http://site.ru/folder/index.php?file=/../../../../../../etc/passwd%00

И строка в памяти сервера будет выглядеть как:

/../../../../../../etc/passwd%00.php ==> /../../../../../../etc/passwd

И в итоге мы смогли отбросить окончание и получить нужный файл.

String limit
Еще один вариант отбрасывания окончания возможен при String Limit - укорачиванию строки.
И какая же от этого польза? А что если мы отбросим часть строки с окончанием, то получится нужная нам строка,но уже без окончания.

Уже на этот раз нам может помочь строка /./ . Объясняю, что происходит:

/./././././index === index

Если точнее, то в bash эти две строки идентичны. Приведу пример, как это может помочь

1) У нас есть параметр, строка которого укорачивается до 100 символов 2) Попробуем вывести файл index.txt, при условии, что приписывается окончание.php 3) Попробуем ввести index.txt - в итоге выводится index.txt.php 4) Чтобы обойти защиту, нужно ввести index.txt/././././../....../././ 5) В итоге получается, что к этой длинной строке приписывается.php, которое в последствии отбрасывается 6) Profit!

php filter
По мне самый интересный вариант lfi является lfi с php filter. Сразу привожу пример

Http://site.ru/folder/index.php?file=php://filter/convert.base64-encode/resource=index

В итоге у нас в браузере не запустится php файл, а выведется его base64 исходников.
Это в последнее время появляется на соревнованиях все чаще и чаще.

Эксплуатация уязвимости

Если вы читаете этот пункт,то вероятнее всего уже нашли LFI. Тогда разберем, чем она может нам быть полезна.

Получение важных файлов (не скриптов)
Ну самое типичное для lfi - скачивание файлов, которые мы, по задумке администратора, не должны были скачивать. Приведу пример задания:

Задание: Дан файлообменник, есть несколько аккаунтов - admin и user(и паролем test). Нужно скачать файл flag.txt, хранящийся у аккаунта admin. Решение: 1) Загрузим свой файл, и посмотрим на ссылку на его скачивание. Она будет вида http://site.ru/download.php?file=user/image.png 2) И в правду папка user существует. Но при скачивании по ссылке http://site.ru/user/image.png идет ошибка 403, что вполне логично. 3) На всякий случай составим ссылку с однозначно отсутствующим файлом в папке user, и если ответ будет 404, то понимаем, что ответ 403 == ответу 200. 4) Проверим, верно ли, что наш файл должен быть по пути admin/flag.txt: http://site.ru/admin/flag.txt возвращает 403 (вспоминаем предыдущий пункт). 5) А почему бы, раз скачать не можем, не направить скрипт download.php на нужный нам файл? Пробуем перейти по http://site.ru/download.php?file=admin/flag.txt и получаем файл. 6) Profit!

Получение исходников
В получении исходников могут быть некоторые проблемы. Например, при эксплуатации исходники не высвечиваются, а запускаются. В этом случае к нам на помощь приходит как раз php filter.
Примеры тут достаточно простые, так что не вижу смысла их приводить.

LFI -> RCE
Т.к. этот раздел уже переходит в более опасный раздел RCE, то вполне логично перенести дискуссию по этому поводу в нее. Ищите на сайте =)

Множество примеров

SharifCTF 2016 - technews

Решение

1. Смотрим путь до картинок, открываем напрямую папку /files/ и видим папку /flag/ 2. Проверяем существование файла /files/flag/flag.txt (403 ошибка) 3. Проверив burpsuit"ом замечаем, что некоторые картинки подкачиваются как images.php?id=files/images/heart.jpg 4. При images.php?id = php://filter/convert.base64-encode/resource=files/images/heart.jpg картинка возвращается в незашифрованом виде, что наводит на мысли регулярного выражения. 5. Изучаем форму и обходим регулярку с помощью запроса: images.php?id=php://abcdresource=files/flag/heart.jpg/resource=files/flag/flag.txt

В этом руководстве Вы узнаете, как построить простую систему по архитектуре MVC (Model-View-Controller, Модель-Отображение-Контроллер) на PHP 5.1 с использованием возможностей библиотеки SPL (Standard PHP Library, Стандартная Библиотека PHP).

Введение

Добро пожаловать в первое полноценное руководство для PHP 5. Вам понадобится PHP 5.1 с установленной библиотекой SPL, так как мы воспользуемся некоторыми из самых последних возможностей PHP 5.

В этом руководстве я собираюсь показать, как построить простую MVC-систему (архитектура MVC является наиболее распространённым шаблоном проектирования для больших web-приложений). Я проведу Вас через все шаги от начала и до конца создания полноценной MVC-системы.

Одна точка входа

Одной из важных вещей в MVC является одна точка входа в приложение вместо кучи PHP-файлов, делающих примерно следующее:

У нас будет один файл, обрабатывающий все запросы. Это значит, что нам не придётся мучиться с подключением global.php каждый раз, когда нам нужно создать новую страницу. Эта «одна точка входа» будет называться index.php и на данный момент будет такой:

Как Вы можете заметить, этот скрипт пока ещё ничего не делает, но погодите минутку.

Чтобы направить все запросы на главную страницу, мы воспользуемся mod_rewrite и установим в.htaccess директиву RewriteRule. Вставим следующий код в файл.htaccess и сохраним его в той же директории, что и index.php:

RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?route=$1

Сперва мы проверяем, существует ли запрашиваемый файл, используя директиву RewriteCond, и, если нет, то перенаправляем запрос на index.php. Такая проверка на существование файла необходима, так как иначе index.php будет пытаться обрабатывать все запросы к сайту, включая запросы на изображения. А это нам как раз и не надо.

Если у Вас нет возможности использовать.htaccess или mod_rewrite, то Вам придётся вручную адресовать все запросы к index.php. Другими словами, все ссылки должны будут иметь вид «index.php?route=[здесь-идёт-запрос]». Например, «index.php?route=chat/index».

Теперь, когда все запросы идут через одну точку входа, мы можем начать написание скрипта index.php. Первая вещь, которую мы должны сделать, это инициализация системы. Создадим директорию includes, а в ней файл startup.php (он будет у нас файлом инициализации). Вставим следующий код в index.php: