mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Python: Added tests based on security analysis
currently we do not:
- recognize the pattern
`{'author': {"$eq": author}}` as protected
- recognize arguements to `$where` (and friends)
as vulnerable
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
from pymongo import MongoClient
|
||||
client = MongoClient()
|
||||
|
||||
db = client.test_database
|
||||
|
||||
import datetime
|
||||
post = {
|
||||
"author": "Mike",
|
||||
"text": "My first blog post!",
|
||||
"tags": ["mongodb", "python", "pymongo"],
|
||||
"date": datetime.datetime.now(tz=datetime.timezone.utc),
|
||||
}
|
||||
|
||||
posts = db.posts
|
||||
post_id = posts.insert_one(post).inserted_id
|
||||
post_id
|
||||
@@ -0,0 +1,19 @@
|
||||
Tutorials:
|
||||
- [pymongo](https://pymongo.readthedocs.io/en/stable/tutorial.html)
|
||||
- [install mongodb](https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-os-x/#std-label-install-mdb-community-macos)
|
||||
|
||||
I recommend creating a virtual environment with venv and then installing dependencies via
|
||||
```
|
||||
python -m pip --install -r requirements.txt
|
||||
```
|
||||
|
||||
Start mongodb:
|
||||
```
|
||||
mongod --config /usr/local/etc/mongod.conf --fork
|
||||
```
|
||||
run flask app:
|
||||
```
|
||||
flask --app server run
|
||||
```
|
||||
|
||||
Navigate to the root to see routes. For each route try to get the system to reveal the person in the database. If you know the name, you can just input it, but in some cases you can get to the person without knowing the name!
|
||||
@@ -0,0 +1,2 @@
|
||||
flask
|
||||
pymongo
|
||||
@@ -0,0 +1,55 @@
|
||||
from flask import Flask, request
|
||||
from pymongo import MongoClient
|
||||
import json
|
||||
|
||||
client = MongoClient()
|
||||
db = client.test_database
|
||||
posts = db.posts
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
def show_post(post, query):
|
||||
if post:
|
||||
return "You found " + post['author'] + "!"
|
||||
else:
|
||||
return "You did not find " + query
|
||||
|
||||
@app.route('/plain', methods=['GET'])
|
||||
def plain():
|
||||
author = request.args['author']
|
||||
post = posts.find_one({'author': author}) # $ result=OK
|
||||
return show_post(post, author)
|
||||
|
||||
@app.route('/dict', methods=['GET'])
|
||||
def as_dict():
|
||||
author_string = request.args['author']
|
||||
author = json.loads(author_string)
|
||||
# Use {"$ne": 1} as author
|
||||
# Found by http://127.0.0.1:5000/dict?author={%22$ne%22:1}
|
||||
post = posts.find_one({'author': author}) # $ result=BAD
|
||||
return show_post(post, author)
|
||||
|
||||
@app.route('/dictHardened', methods=['GET'])
|
||||
def as_dict_hardened():
|
||||
author_string = request.args['author']
|
||||
author = json.loads(author_string)
|
||||
post = posts.find_one({'author': {"$eq": author}}) # $ SPURIOUS: result=BAD
|
||||
return show_post(post, author)
|
||||
|
||||
@app.route('/byWhere', methods=['GET'])
|
||||
def by_where():
|
||||
author = request.args['author']
|
||||
# Use `" | "a" === "a` as author
|
||||
# making the query `this.author === "" | "a" === "a"`
|
||||
# Found by http://127.0.0.1:5000/byWhere?author=%22%20|%20%22a%22%20===%20%22a
|
||||
post = posts.find_one({'$where': 'this.author === "'+author+'"'}) # $ MISSING: result=BAD
|
||||
return show_post(post, author)
|
||||
|
||||
@app.route('/', methods=['GET'])
|
||||
def show_routes():
|
||||
links = []
|
||||
for rule in app.url_map.iter_rules():
|
||||
if "GET" in rule.methods:
|
||||
links.append((rule.rule, rule.endpoint))
|
||||
return links
|
||||
@@ -0,0 +1 @@
|
||||
semmle-extractor-options: --max-import-depth=1 -r PoC
|
||||
Reference in New Issue
Block a user