Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python: promote nosql query #14070

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft

Conversation

yoff
Copy link
Contributor

@yoff yoff commented Aug 28, 2023

No description provided.

Mostly move files, preserving authourship.
This will not compile.
- Move NoSQL concepts to the non-experimental concepts file
- fix references
Also use new DataFlow API
Also make inline query tests use the new dataflow API.
This bit could be a separate PR...
@github-actions
Copy link
Contributor

QHelp previews:

python/ql/src/Security/CWE-943/NoSQLInjection.qhelp

NoSQL Injection

Passing user-controlled sources into NoSQL queries can result in a NoSQL injection flaw. This tainted NoSQL query containing a user-controlled source can then execute a malicious query in a NoSQL database such as MongoDB. In order for the user-controlled source to taint the NoSQL query, the user-controller source must be converted into a Python object using something like json.loads or xmltodict.parse.

Because a user-controlled source is passed into the query, the malicious user can have complete control over the query itself. When the tainted query is executed, the malicious user can commit malicious actions such as bypassing role restrictions or accessing and modifying restricted data in the NoSQL database.

Recommendation

NoSQL injections can be prevented by escaping user-input's special characters that are passed into the NoSQL query from the user-supplied source. Alternatively, using a sanitize library such as MongoSanitizer will ensure that user-supplied sources can not act as a malicious query.

Example

In the example below, the user-supplied source is passed to a MongoDB function that queries the MongoDB database.

from flask import Flask, request
from flask_pymongo import PyMongo
import json

mongo = PyMongo(app)


@app.route("/")
def home_page():
    unsanitized_search = request.args['search']
    json_search = json.loads(unsanitized_search)

    result = mongo.db.user.find({'name': json_search})

This can be fixed by using a sanitizer library like MongoSanitizer as shown in this annotated code version below.

from flask import Flask, request
from flask_pymongo import PyMongo
from mongosanitizer.sanitizer import sanitize
import json

mongo = PyMongo(app)


@app.route("/")
def home_page():
    unsafe_search = request.args['search']
    json_search = json.loads(unsafe_search)
    safe_search = sanitize(unsanitized_search)

    result = client.db.collection.find_one({'data': safe_search})

References

currently we do not:
- recognize the pattern
   `{'author': {"$eq": author}}` as protected
- recognize arguements to `$where` (and friends)
   as vulnerable
This allows us to make more precise modelling
The query tests now pass.
I do wonder, if there is a cleaner approach, similar to
`TaintedObject` in JavaScript. I want the option to
get this query in the hands of the custumors before
such an investigation, though.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant