Analysis of PHPMailer Remote Code Execution Vulnerability (CVE-2016-10033)
PHP is an open source, general-purpose scripting language used for web development that can also be embedded into HTML. It has over 9 million users, and is used by many popular tools, such as WordPress, Drupal, Joomla!, and so on. This week, a high-level security update was released to fix a remote code execution vulnerability (CVE-2016-10033) in PHPMailer, which is an open source PHP library for sending emails from PHP websites.
This critical vulnerability is caused by class.phpmailer.php incorrectly processing user requests. As a result, remote attackers are able to execute code on vulnerable servers.
This vulnerability affects PHPMailer versions before 5.2.18.
Analysis
When sending an email with PHPMailer, the normal process is, 1) PHPMailer gets user requests, 2) PHPMailer validates the user supplied data, 3) PHPMailer sends the data to the PHP mail() function to send the email.
In the validation stage, PHPMailer validates the user supplied data, as shown in the code below.
This validator uses standard validation methods, like PHP’s built-in FILTER_VALIDATE_EMAIL, pcres from squiloople.com, and html5 default patterns for email type.
For example, the $address with value “attacker -InjectedParam @example.com” will be rejected. But these methods follow RFC3696, which means the email address can contain spaces when quoted with “"”, so an $address with value “"attacker -InjectedParam"@example.com” will pass through the filter.
After the validation stage, PHPMailer will send the email elements, such as receiver address, subject, body, header, and sender address to the PHP mail() function to send the email. The code is shown below.
The issue here is that PHPMailer doesn’t sterilize these email values before sending them to the mail() function. It just returns the and then sends the $result to the mail() function with the same set of parameters. This issue enables the subsequent attacks.
For example, when sending the request with email address:
The mail() function will execute /usr/bin/sendmail with 4 arguments, “/usr/bin/sendmail”, “-t”, “-i” and “-fattacker -InjectedParam@example.com”.
However, an attacker could break the fourth argument by injecting a parameter with “"”. For example, using the email address:
This email address will let the sendmail function execute 6 arguments, “/usr/bin/sendmail”, “-t”, “-i”, “-fattacker”, “-InjectedParam1” and “-InjectedParam2"@example.com”.
How to Reproduce
In order to reproduce the attack, I have built a web server, as shown in Figure 1.
Figure 1. Testing the PHPMailer server
The source code is:
This is a form similar to the “send feedback” function on some online websites. An attacker could send an email with a malicious email address to execute sendmail arguments, such as:
The PHP code can then be added to the Name or Message part of the string. For example, . This is shown in Figure 2, below.
Figure 2. Sending the attack email
Before sending this email, the files in the web root directory are shown in Figure 3. The index.php is the code of the webpage shown in Figure 1 ,and the directory “vulnerable” contains the PHPMailer files.
Figure 3. Web root directory before sending the attack email
The payload for sending this email is shown in Figure 4, below.
Figure 4. Attack payload
After sending this attack email, a new file “test.php” is created. It contains the RAW data for sending this email, which contains our PHP code “”. It’s shown in Figure 5.
Figure 5. Web root directory after sending the attack email
Then we can access our shell PHP file test.php and run commands. For example, we could execute the command “cat /etc/passwd”, as shown in Figure 6.
Figure 6. Execute the command “cat /etc/passwd” on a test web server
In conclusion, the actual attack could be an arbitrary file upload that exploits the vulnerability in the PHPMailer filter for the sender email address. This means that an attacker could send an email with malicious code to the server, use the sendmail arguments to move the log file with the malicious code to the web root directory, and then execute the code remotely.
Solution
All users of PHPMailer should upgrade to the latest version immediately. Additionally, organizations that have deployed Fortinet IPS solutions are already protected from this vulnerability with the signature PHPMailer.Remote.Code.Execution.