Skip to content

Instantly share code, notes, and snippets.

Last active June 29, 2020 11:55
Show Gist options
  • Save mariuszpoplawski/703586aa068bdad21f2c098f396ce04f to your computer and use it in GitHub Desktop.
Save mariuszpoplawski/703586aa068bdad21f2c098f396ce04f to your computer and use it in GitHub Desktop.
[Suggested description]
ExpressionEngine before 5.3.2 allows remote attackers to upload and execute arbitrary code in a .php%20 file via Compose Msg, Add attachment, and Save As Draft actions.
A user with low privileges (member) is able to upload such a file on a server.
It is possible to bypass the checks of MIME type and file-extension while uploading new files.
Short aliases are not used for an attachment; instead, uploaded files can be accessed directly. It is possible to upload PHP only if one has member access, or registration/forum is enabled and one can create a member with the default group id of 5. To exploit this, one must be able to (at least) send and compose messages.
[Additional Information]
To trigger the vulnerability we can use messages composer:
Affected function
Compose Msg -> Add Attachment -> Save As Draft
Files attached to message are saved as draft are stored in /var/www/html/images/pm_attachments/$FILE_NAME which is accessible from web app root folder.$UPLOADED_FILE_NAME.EXT
We were able to send file with name "POC.php%20". It was a valid PNG file with PHP code inside. Below we present the PoC.
Quick overview of code
Global variable in CMS by default $this-blacklisted_extensions =
[0] = php
[1] = php3
[2] = php4
[3] = php5
[4] = php7
[5] = phps
[6] = phtml
/system/ee/legacy/libraries/Upload.php code at line 532
If extension of uploaded file is not in blacklisted_extensions array, for example ".php%20", upload will be successful.
if (in_array($ext, $this-blacklisted_extensions))
return FALSE;
To upload the file, MIME type has to be present in white list, so we uploaded PNG file with PHP code in comment TAG.
Line 237: public function isSafeForUpload($mime)
return in_array($mime, $this-whitelist, TRUE);
Line 95: public function ofFile($path){
Line 105: $finfo = finfo_open(FILEINFO_MIME_TYPE);
/system/ee/legacy/libraries/Upload.php code at
Function clean_file_name is called after check ...
[VulnerabilityType Other]
Low privileged user could upload PHP file which led to Remote Command Execution
[Vendor of Product]
[Affected Product Code Base] - before 5.3.2
[Affected Component]
[Attack Type]
[Impact Code execution]
[Attack Vectors]
User with low privileges has to upload file in Message composer. File extension check can be bypassed using %20 at the end of file ext. name.
Mariusz Popławski (
Mariusz Popławski / team
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment