On 13th May 2021, WordPress released WordPress 5.7.2, which was a security release fixing one vulnerability that affected versions 3.7 to 5.7. This vulnerability is a PHP Object Injection vulnerability in PHPMailer (CVE-2020-36326, CVE-2018-19296) that occurs via the addAttachment function with a UNC pathname. You may notice that there are two CVE’s in the security release addressing this vulnerability, this is because CVE-2018-19296 existed, but a bug fix by PHPMailer re-introduced the vulnerability (this post will focus on the primary CVE, CVE-2018-19296).
This post aims to cover a quick introduction on what PHP Object Injection is, how this vulnerability could be exploited, and then how to mitigate it.
What is PHP object injection and phar deserialization?
PHP object injection occurs when user-supplied input that is not sanitized is passed directly to the PHP unserialize() function. Here is what OWASP says about the requirements of exploiting a PHP object injection vulnerability:
The application must have a class which implements a PHP magic method (such as __wakeup or __destruct) that can be used to carry out malicious attacks, or to start a “POP chain”.
All of the classes used during the attack must be declared when the vulnerable unserialize() is being called, otherwise object autoloading must be supported for such classes.
The difference in this case is that this bug is a phar deserialization attack, which is a method of exploiting php object injection vulnerabilities. So what is phar deserialization and what is the difference between the two? (A great article on php phar deserialization can be found here: https://vickieli.dev/insecure%20deserialization/php-phar/)
In simple terms, phar deserialization occurs when a file operation is performed on a phar file with the phar:// wrapper. Phar files have 4 elements; a stub, a manifest, a source file and a signature. The metadata part is stored in a serialized format, so when a file operation is performed via the phar:// wrapper, then the serialized data is then unserialized. Phar deserialization does not need for the input to be passed to unserialize() (unlike a normal php object injection) as the data is unserialized already, that is the difference between the two (we still need to start a POP chain though!).
I could not really find much regarding this CVE other than the same security releases with no writeup, PoC or an analysis, so I fetched the source code for PHPMailer 5.2.26 (the version just before this CVE fix, found here: https://github.com/PHPMailer/PHPMailer/releases/tag/v5.2.26), and the PHPMailer 5.2.27 (found here: https://github.com/PHPMailer/PHPMailer/releases/tag/v5.2.27), and compared them.
From the CVE description, we can see that the vulnerability occurs by passing phar:// paths into the addAttachment() function, so the first step is to find that function and see what is going on.
*The left side is the vulnerable version, the right side is the patched version*
Not much is shown here at all, but what we can see is PHPMailer adding an isPermittedPath($path) check, and if it fails, then the phpmailerException is thrown. Lets check to see what isPermittedPath contains:
Here we can see the function isPermittedPath uses regex to check if the file path contains ://, effectively rejecting URLs and the ability to use the phar:// wrapper. If you look above the addAttachment function on the patched version, you can see a comment explaining that PHPMailer does not support passing URL’s, this looks like the direct result of the PHP Object Injection fix.
Basically all of the changes in the codebase for this update was to disable the ability to control the file path. As mentioned before, for a phar deserialization attack to work, we need to control the full file path to specify the phar:// wrapper, so these checks here fix the phar deserialisation vulnerability.
Creating phar files for exploitation
Actually exploiting phar deserialization bugs is pretty straightforward once you are familiar with php object injection. As noted from the “File Operation Induced Unserialization via the “phar://” Stream Wrapper” presentation by Sam Thomas, PHPGCC is a great tool to create the malicious phar files to exploit phar deserialization! For example, running phpggc -l allows us to list a bunch of gadgets like so:
And creating a malicious phar file can be as simple as:
phpggc -p phar -o /tmp/z.phar monolog/rce1 system id
phpggc -p zip -o /tmp/z.zip.phar monolog/rce1 system id # which creates a zip file instead
These bugs in the end can be used to achieve remote code execution, so in this case it is very much recommended to update your WordPress!
The mitigation here is relatively simple, and its to update your WordPress as advised by the WordPress security team to version 5.7.2. You can do this by visiting your Dashboard –> Updates –> and click update now!