A sanitization filter bypass in plupload.php
in MicroweberCMS v1.3.1 allows remote authenticated attackers to upload files outside the restricted location.
The target $path
for the image is being sanitized here:
$path_restirct = userfiles_path();
if (isset($_REQUEST['path']) and trim($_REQUEST['path']) != '' and trim($_REQUEST['path']) != 'false') {
[...]
$path = str_replace('..', '', $path);
$path = str_replace($path_restirct, '', $path);
Since $path_restirct
can easily be guessed (/<base path of the web directory>/userfiles/
) the first str_replace
can easily be circumvented by adding $path_restirct
between two dots. After the second replace, directory traversal is possible. Though placing files outside of the intended location is possible, the impact has been deemed neither critical nor high due to the extension filter that is still in effect. However, the upload permits several potentially dangerous filetypes, including json
, and zip
for example.
A very good example for how easily this vulnerability could have turned into remote code execution is the loadPackagesComposerJson()
function here. This function reads Composer.json
files and uses the contents to include
any specified file. Luckily, this function is deprecated and not being used at the moment.
This PoC assumes a default install of Microweber in the standard web directory of a CentOS Webserver (/var/www/html/
).
1 ) Login as admin
2 ) Navigate to any file upload form (e.g. via editing a page or in the files menu)
3 ) Select a file to upload (e.g. schema.json
) and capture the request
4 ) Before passing on the POST request, add this parameter to the URL: ?path=/./var/www/html/userfiles/././var/www/html/userfiles/././var/www/html/userfiles/./
, where /var/www/html/
is the base web directory.
5 ) After successful upload, the file appears in the base web directory
Though I did not manage to escalate this attack further at the moment, I believe there are at least two vectors an attacker could investigate. Firstly, placing malicious Composer.json
files in arbitrary module directories (the file upload is kind enough to create any directory for us) and finding a way to trigger them. And secondly, creating malicious schema.json
files that are searched for and automatically parsed every time the modules are reloaded.
I did give the latter a shot and created a PoC to trigger an SQL error (though creating arbitrary tables is possible, modifying or accessing tables was not achieved during testing).