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

Merged
merged 45 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
60dc1af
Python: prepare to promote NoSqlInjection
yoff Aug 15, 2023
55707d3
Python: Make things compile in their new location
yoff Aug 15, 2023
db04597
Python: rename file
yoff Aug 23, 2023
087961d
Python: Refactor to allow customizations
yoff Aug 23, 2023
19046ea
Python: more renames
yoff Aug 23, 2023
bf8bfd9
Python: Add inline query test
yoff Sep 7, 2023
114984b
Python: Added tests based on security analysis
yoff Aug 29, 2023
c0b3245
Python: Enrich the NoSql concept
yoff Aug 31, 2023
7edebbe
Python: Add QLDocs
yoff Sep 6, 2023
f253f97
Python: update test expectations
yoff Sep 6, 2023
970e881
Python: Follow naming convention
yoff Sep 7, 2023
b07d085
Python: make test PoC a proper package
yoff Sep 7, 2023
d91cd21
Python: rename file
yoff Sep 8, 2023
154a369
Python: Add test for function
yoff Sep 11, 2023
d9f63e1
Python: Split modelling of query operators
yoff Sep 11, 2023
a063d7d
Python: sinks -> decodings
yoff Sep 11, 2023
4614b1a
Python: add change note
yoff Sep 18, 2023
5611bda
Python: add test for `$accumulator`
yoff Sep 19, 2023
30c37ca
Python: model `§accumulator`
yoff Sep 19, 2023
7c085ec
Python: Add test for `map_reduce`
yoff Sep 20, 2023
4ec8b3f
Python: Model `map_reduce`
yoff Sep 20, 2023
12dab88
Python: rename concept
yoff Sep 20, 2023
8156fa9
Apply naming suggestions from code review
yoff Sep 28, 2023
37a4f35
Python: further rename
yoff Sep 28, 2023
3fb579e
Python: add test for type tracking
yoff Sep 28, 2023
d90630a
Python: fix query file
yoff Sep 28, 2023
c2b6383
Apply suggestions from code review
yoff Sep 28, 2023
9682c82
Python: rename file
yoff Sep 28, 2023
2a739b3
Python: rename module
yoff Sep 28, 2023
eb1be08
Python: split modelling
yoff Sep 28, 2023
2a7b593
Python: Fix QL alerts
yoff Sep 28, 2023
a8e0023
Python: forgot to list framework
yoff Sep 28, 2023
d5b64c5
Python: update test expectations
yoff Sep 28, 2023
3043633
Python: Some renaming of flow states
yoff Sep 28, 2023
2e028a4
Apply suggestions from code review
yoff Sep 29, 2023
74d6f37
Python: update meta query `TaintSinks`
yoff Sep 29, 2023
2d845e3
Python: nicer paths
yoff Sep 29, 2023
e170805
Python: fix QL alert
yoff Sep 29, 2023
f3a0161
Python: rename flow states
yoff Sep 29, 2023
9769668
Python: require dict sinks be dangerous.
yoff Sep 29, 2023
16e1a00
Python: NoSQLInjection -> NoSqlInjection
RasmusWL Sep 29, 2023
d7ad5a0
Python: List NoSQL injection sinks
RasmusWL Sep 29, 2023
3676262
Python: Clean trailing whitespace
RasmusWL Sep 29, 2023
d6d13f8
Python: -> NoSQL in QLDocs
RasmusWL Sep 29, 2023
9b73bbf
Python: Add keyword argument support
RasmusWL Sep 29, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions python/ql/lib/semmle/python/Concepts.qll
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,68 @@ module SqlExecution {
}
}

/** Provides a class for modeling NoSQL execution APIs. */
module NoSqlExecution {
/**
* A data-flow node that executes NoSQL queries.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `NoSqlExecution` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets the argument that specifies the NoSql query to be executed. */
abstract DataFlow::Node getQuery();

/** Holds if this query will unpack/interpret a dictionary */
abstract predicate interpretsDict();

/** Holds if this query can be dangerous when run on a user-controlled string */
abstract predicate vulnerableToStrings();
}
}

/**
* A data-flow node that executes NoSQL queries.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `NoSqlExecution::Range` instead.
*/
class NoSqlExecution extends DataFlow::Node instanceof NoSqlExecution::Range {
/** Gets the argument that specifies the NoSql query to be executed. */
DataFlow::Node getQuery() { result = super.getQuery() }

/** Holds if this query will unpack/interpret a dictionary */
predicate interpretsDict() { super.interpretsDict() }

/** Holds if this query can be dangerous when run on a user-controlled string */
predicate vulnerableToStrings() { super.vulnerableToStrings() }
}

/** Provides classes for modeling NoSql sanitization-related APIs. */
module NoSqlSanitizer {
/**
* A data-flow node that collects functions sanitizing NoSQL queries.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `NoSQLSanitizer` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets the argument that specifies the NoSql query to be sanitized. */
abstract DataFlow::Node getAnInput();
}
}

/**
* A data-flow node that collects functions sanitizing NoSQL queries.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `NoSQLSanitizer::Range` instead.
*/
class NoSqlSanitizer extends DataFlow::Node instanceof NoSqlSanitizer::Range {
/** Gets the argument that specifies the NoSql query to be sanitized. */
DataFlow::Node getAnInput() { result = super.getAnInput() }
}

/**
* A data-flow node that executes a regular expression.
*
Expand Down
2 changes: 2 additions & 0 deletions python/ql/lib/semmle/python/Frameworks.qll
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ private import semmle.python.frameworks.Aiomysql
private import semmle.python.frameworks.Aiosqlite
private import semmle.python.frameworks.Aiopg
private import semmle.python.frameworks.Asyncpg
private import semmle.python.frameworks.BSon
private import semmle.python.frameworks.CassandraDriver
private import semmle.python.frameworks.ClickhouseDriver
private import semmle.python.frameworks.Cryptodome
Expand Down Expand Up @@ -42,6 +43,7 @@ private import semmle.python.frameworks.Phoenixdb
private import semmle.python.frameworks.Psycopg2
private import semmle.python.frameworks.Pycurl
private import semmle.python.frameworks.Pydantic
private import semmle.python.frameworks.PyMongo
private import semmle.python.frameworks.Pymssql
private import semmle.python.frameworks.PyMySQL
private import semmle.python.frameworks.Pyodbc
Expand Down
38 changes: 38 additions & 0 deletions python/ql/lib/semmle/python/frameworks/BSon.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Provides classes modeling security-relevant aspects of the `bson` PyPI package.
* See
* - https://pypi.org/project/bson/
* - https://github.com/py-bson/bson
*/

private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.Concepts
private import semmle.python.ApiGraphs

/**
* Provides models for the `bson` PyPI package.
* See
* - https://pypi.org/project/bson/
* - https://github.com/py-bson/bson
*/
private module BSon {
yoff marked this conversation as resolved.
Show resolved Hide resolved
/**
* ObjectId returns a string representing an id.
* If at any time ObjectId can't parse it's input (like when a tainted dict in passed in),
* then ObjectId will throw an error preventing the query from running.
*/
private class BsonObjectIdCall extends DataFlow::CallCfgNode, NoSqlSanitizer::Range {
BsonObjectIdCall() {
exists(API::Node mod |
mod = API::moduleImport("bson")
or
mod = API::moduleImport("bson").getMember(["objectid", "json_util"])
|
this = mod.getMember("ObjectId").getACall()
)
}

override DataFlow::Node getAnInput() { result = this.getArg(0) }
}
}
Loading