mongodb-developer / mongodb-developer/GenAI-Showcase

[BUG] 🐍 MongoDB Playgrounds arbitrary code execution via mongostory

Open
#135 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Jupyter Notebook
Stars
4.3k
Forks
746
Avg merge
1d 7h
Merged PRs (30d)
2

Description

https://github.com/mongodb-developer/GenAI-Showcase/blob/50535ba52c872ed03a975bf180f01f84696e7cc9/apps/mongostory/app/api/mongodb-playground/route.ts#L18-L21

Directly evaluating user input (an HTTP request parameter) as code without properly sanitizing the input first allows an attacker arbitrary code execution. This can occur when user input is treated as JavaScript, or passed to a framework which interprets it as an expression to be evaluated. include AngularJS expressions or JQuery selectors.

Recommendation

Avoid including user input in any expression which may be dynamically evaluated. If user input must be included, use context-specific escaping before including it. It is important that the correct escaping is used for the type of evaluation that will occur.

The following shows part of the page URL being evaluated as JavaScript code. This allows an attacker to provide JavaScript within the URL. If an attacker can persuade a user to click on a link to such a URL, the attacker can evaluate arbitrary JavaScript in the browser of the user to, for example, steal cookies containing session information.

eval(document.location.href.substring(document.location.href.indexOf("default=")+8))

The following example shows a Pug template being constructed from user input, allowing attackers to run arbitrary code via a payload such as #{global.process.exit(1)}.

const express = require('express')
var pug = require('pug');
const app = express()

app.post('/', (req, res) => {
    var input = req.query.username;
    var template = `
doctype
html
head
    title= 'Hello world'
body
    form(action='/' method='post')
        input#name.form-control(type='text)
        button.btn.btn-primary(type='submit') Submit
    p Hello `+ input
    var fn = pug.compile(template);
    var html = fn();
    res.send(html);
})

Below is an example of how to use a template engine without any risk of template injection. The user input is included via an interpolation expression #{username} whose value is provided as an option to the template, instead of being part of the template string itself:

const express = require('express')
var pug = require('pug');
const app = express()

app.post('/', (req, res) => {
    var input = req.query.username;
    var template = `
doctype
html
head
    title= 'Hello world'
body
    form(action='/' method='post')
        input#name.form-control(type='text)
        button.btn.btn-primary(type='submit') Submit
    p Hello #{username}`
    var fn = pug.compile(template);
    var html = fn({username: input});
    res.send(html);
})
References

Code Injection
Code Injection
Server-Side Template Injection

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with apps/mongostory/app/api/mongodb-playground/route.ts at lines 18-21 and trace how the HTTP request parameter reaches evaluation. Verify the behavior with a request containing executable input, then confirm that the same input is handled as data and cannot execute code.

Written by the indexing model from the issue text.

Assessment

Tech stack
mongodb, typescript
Domain
api, backend, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
40/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.