В PHPMailer выявлена еще одна критическая уязвимость, вызванная недоработкой в PHP
В библиотеке PHPMailer выявлена еще одна критическая уязвимость (CVE-2016-10045), позволяющая выполнить свой код на сервере. Проблема устранена в выпуске PHPMailer 5.2.20. Уязвимость позволяет обойти метод защиты, реализованный для блокирования прошлой уязвимости, и касается не столько самого PHPMailer, сколько внутренних проблем с функцией mail() и средствами экранирования символов в PHP.
Напомним, что уязвимость в PHPMailer позволяла через передачу специально оформленного адреса отправителя, корректного и полностью соответствующего RFC 3696, организовать передачу дополнительных аргументов утилите /usb/sbin/sendmail, запускаемой по умолчанию при вызове PHP-функции mail(). Для атаки используется опция "-X", позволяющая записать тело сообщения в переданный в качестве аргумента файл (игнорируется в реализациях утилиты sendmail от проектов Postfix и Exim). Так как формально атака осуществляется через корректный email-адрес, проходящий проверку на предмет соответствия требованиям RFC 3696, для блокирования уязвимости был добавлен дополнительный вызов escapeshellarg() для экранирования аргументов, передаваемых в функцию mail().
Из-за особенностей PHP данная защита оказалась неэффективной. В частности, для защиты от подстановки дополнительных shell-команд в функции mail() уже применяется экранирование итоговой команды через escapeshellcmd(). Добавленное разработчиками PHPMailer экранирование отдельных аргументов при помощи escapeshellarg() привело к некорректному двойному экранированию спецсимволов, в результате которого на выходе остается рабочая команда. Например, попытка отправки по адресу "&92;"Attacker&92;&92;' -Param2 -Param3&92;"@test.com" приводит к следующей расстановке аргументов при вызове функции mail():
Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [-f&92;"Attacker&92;&92;&92;] Arg no. 4 == [-Param2] Arg no. 5 == [-Param3"@test.com']
Так как выполнение escapeshellcmd(escapeshellarg($address)) ломает всю защиту и штатными средствами устранить уязвимость через экранирование символов оказалось невозможно, разработчики PHPMailer решились на нарушение совместимости с RFC 3696 и в версии PHPMailer 5.2.20 реализовали дополнительную фильтрацию, которая может привести к прекращению обработки некоторых сложных email-адресов.
В ходе разработки исправления был поднят пласт проблем с функциями escapeshellcmd() и scapeshellarg(), поведение которых отличается для разных платформ и локалей. По мнению разработчиков PHPMailer для полноценного устранения проблемы требуется внутренняя переработка функции mail() в PHP, в которой следует вместо строки $additional_parameters подставляемой в выполняемую команду использовать массив отдельных аргументов и обеспечить запуск sendmail напрямую, а не через shell.
Следует отметить, что проблема не ограничивается PHPMailer и, например, вчера обнаружена (CVE-2016-10074) в другой популярной PHP-библиотеке SwiftMailer, которая используется в таких проектах, как Yii2, Laravel и Symfony. Несмотря на то, что разработчики были уведомлены о проблеме еще 2 декабря, исправление до сих пор не выпущено и последний выпуск SwiftMailer 5.4.5-dev остается уязвимым. Метод эксплуатации полностью аналогичен уязвимости в PHPMailer.
$email_from = '"attacker&92;" -oQ/tmp/ -X/var/www/cache/phpcode.php "@email.com'; Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [-fattacker&92;] Arg no. 4 == [-oQ/tmp/] Arg no. 5 == [-X/var/www/cache/phpcode.php] Arg no. 6 == ["@email.com]