mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Merge pull request #10752 from RasmusWL/pymssql
Python: DB Modeling: Add `pymssql` and `executemany` in general
This commit is contained in:
@@ -226,6 +226,8 @@ and the CodeQL library pack ``codeql/python-all`` (`changelog <https://github.co
|
|||||||
MySQL-python, Database
|
MySQL-python, Database
|
||||||
mysqlclient, Database
|
mysqlclient, Database
|
||||||
psycopg2, Database
|
psycopg2, Database
|
||||||
|
pymssql, Database
|
||||||
|
PyMySQL, Database
|
||||||
sqlite3, Database
|
sqlite3, Database
|
||||||
Flask-SQLAlchemy, Database ORM
|
Flask-SQLAlchemy, Database ORM
|
||||||
peewee, Database ORM
|
peewee, Database ORM
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ private import semmle.python.frameworks.Peewee
|
|||||||
private import semmle.python.frameworks.Psycopg2
|
private import semmle.python.frameworks.Psycopg2
|
||||||
private import semmle.python.frameworks.Pycurl
|
private import semmle.python.frameworks.Pycurl
|
||||||
private import semmle.python.frameworks.Pydantic
|
private import semmle.python.frameworks.Pydantic
|
||||||
|
private import semmle.python.frameworks.Pymssql
|
||||||
private import semmle.python.frameworks.PyMySQL
|
private import semmle.python.frameworks.PyMySQL
|
||||||
private import semmle.python.frameworks.Requests
|
private import semmle.python.frameworks.Requests
|
||||||
private import semmle.python.frameworks.RestFramework
|
private import semmle.python.frameworks.RestFramework
|
||||||
@@ -51,6 +52,6 @@ private import semmle.python.frameworks.Tornado
|
|||||||
private import semmle.python.frameworks.Twisted
|
private import semmle.python.frameworks.Twisted
|
||||||
private import semmle.python.frameworks.Ujson
|
private import semmle.python.frameworks.Ujson
|
||||||
private import semmle.python.frameworks.Urllib3
|
private import semmle.python.frameworks.Urllib3
|
||||||
|
private import semmle.python.frameworks.Xmltodict
|
||||||
private import semmle.python.frameworks.Yaml
|
private import semmle.python.frameworks.Yaml
|
||||||
private import semmle.python.frameworks.Yarl
|
private import semmle.python.frameworks.Yarl
|
||||||
private import semmle.python.frameworks.Xmltodict
|
|
||||||
|
|||||||
@@ -21,17 +21,11 @@ private import semmle.python.frameworks.PEP249
|
|||||||
* - https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html
|
* - https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html
|
||||||
*/
|
*/
|
||||||
private module Mysql {
|
private module Mysql {
|
||||||
// ---------------------------------------------------------------------------
|
/**
|
||||||
// mysql
|
* The mysql.connector module
|
||||||
// ---------------------------------------------------------------------------
|
* See https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html
|
||||||
/** Provides models for the `mysql` module. */
|
*/
|
||||||
module MysqlMod {
|
class MysqlConnector extends PEP249::PEP249ModuleApiNode {
|
||||||
/**
|
MysqlConnector() { this = API::moduleImport("mysql").getMember("connector") }
|
||||||
* The mysql.connector module
|
|
||||||
* See https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html
|
|
||||||
*/
|
|
||||||
class MysqlConnector extends PEP249::PEP249ModuleApiNode {
|
|
||||||
MysqlConnector() { this = API::moduleImport("mysql").getMember("connector") }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
25
python/ql/lib/semmle/python/frameworks/Pymssql.qll
Normal file
25
python/ql/lib/semmle/python/frameworks/Pymssql.qll
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* Provides classes modeling security-relevant aspects of the `pymssql` PyPI package.
|
||||||
|
* See https://pypi.org/project/pymssql/
|
||||||
|
*/
|
||||||
|
|
||||||
|
private import python
|
||||||
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
|
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||||
|
private import semmle.python.Concepts
|
||||||
|
private import semmle.python.ApiGraphs
|
||||||
|
private import semmle.python.frameworks.PEP249
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides models for the `pymssql` PyPI package.
|
||||||
|
* See https://pypi.org/project/pymssql/
|
||||||
|
*/
|
||||||
|
private module Pymssql {
|
||||||
|
/**
|
||||||
|
* A model of `pymssql` as a module that implements PEP 249, providing ways to execute SQL statements
|
||||||
|
* against a database.
|
||||||
|
*/
|
||||||
|
class PymssqlPEP249 extends PEP249::PEP249ModuleApiNode {
|
||||||
|
PymssqlPEP249() { this = API::moduleImport("pymssql") }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -146,7 +146,7 @@ module PEP249 {
|
|||||||
* Note: while `execute` method on a connection is not part of PEP249, if it is used, we
|
* Note: while `execute` method on a connection is not part of PEP249, if it is used, we
|
||||||
* recognize it as an alias for constructing a cursor and calling `execute` on it.
|
* recognize it as an alias for constructing a cursor and calling `execute` on it.
|
||||||
*
|
*
|
||||||
* See https://www.python.org/dev/peps/pep-0249/#id15.
|
* See https://peps.python.org/pep-0249/#execute.
|
||||||
*/
|
*/
|
||||||
private DataFlow::TypeTrackingNode execute(DataFlow::TypeTracker t) {
|
private DataFlow::TypeTrackingNode execute(DataFlow::TypeTracker t) {
|
||||||
t.startInAttr("execute") and
|
t.startInAttr("execute") and
|
||||||
@@ -161,14 +161,44 @@ module PEP249 {
|
|||||||
* Note: while `execute` method on a connection is not part of PEP249, if it is used, we
|
* Note: while `execute` method on a connection is not part of PEP249, if it is used, we
|
||||||
* recognize it as an alias for constructing a cursor and calling `execute` on it.
|
* recognize it as an alias for constructing a cursor and calling `execute` on it.
|
||||||
*
|
*
|
||||||
* See https://www.python.org/dev/peps/pep-0249/#id15.
|
* See https://peps.python.org/pep-0249/#execute.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node execute() { execute(DataFlow::TypeTracker::end()).flowsTo(result) }
|
DataFlow::Node execute() { execute(DataFlow::TypeTracker::end()).flowsTo(result) }
|
||||||
|
|
||||||
/** A call to the `execute` method on a cursor (or on a connection). */
|
/**
|
||||||
|
* A call to the `execute` method on a cursor or a connection.
|
||||||
|
*
|
||||||
|
* See https://peps.python.org/pep-0249/#execute
|
||||||
|
*
|
||||||
|
* Note: While `execute` method on a connection is not part of PEP249, if it is used, we
|
||||||
|
* recognize it as an alias for constructing a cursor and calling `execute` on it.
|
||||||
|
*/
|
||||||
private class ExecuteCall extends SqlExecution::Range, DataFlow::CallCfgNode {
|
private class ExecuteCall extends SqlExecution::Range, DataFlow::CallCfgNode {
|
||||||
ExecuteCall() { this.getFunction() = execute() }
|
ExecuteCall() { this.getFunction() = execute() }
|
||||||
|
|
||||||
override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] }
|
override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DataFlow::TypeTrackingNode executemany(DataFlow::TypeTracker t) {
|
||||||
|
t.startInAttr("executemany") and
|
||||||
|
result in [Cursor::instance(), Connection::instance()]
|
||||||
|
or
|
||||||
|
exists(DataFlow::TypeTracker t2 | result = executemany(t2).track(t2, t))
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataFlow::Node executemany() { executemany(DataFlow::TypeTracker::end()).flowsTo(result) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A call to the `executemany` method on a cursor or a connection.
|
||||||
|
*
|
||||||
|
* See https://peps.python.org/pep-0249/#executemany
|
||||||
|
*
|
||||||
|
* Note: While `executemany` method on a connection is not part of PEP249, if it is used, we
|
||||||
|
* recognize it as an alias for constructing a cursor and calling `executemany` on it.
|
||||||
|
*/
|
||||||
|
private class ExecutemanyCall extends SqlExecution::Range, DataFlow::CallCfgNode {
|
||||||
|
ExecutemanyCall() { this.getFunction() = executemany() }
|
||||||
|
|
||||||
|
override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* Added model of `executemany` calls on PEP-249 compliant database APIs, resulting in additional sinks for `py/sql-injection`.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* Added model of `pymssql` PyPI package as a SQL interface following PEP249, resulting in additional sinks for `py/sql-injection`.
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import python
|
||||||
|
import experimental.meta.ConceptsTest
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import pymssql
|
||||||
|
connection = pymssql.connect(host="localhost", user="user", password="passwd")
|
||||||
|
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute("some sql", (42,)) # $ getSql="some sql"
|
||||||
|
cursor.executemany("some sql", [(42,)]) # $ getSql="some sql"
|
||||||
@@ -3,3 +3,4 @@ connection = pymysql.connect(host="localhost", user="user", password="passwd")
|
|||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute("some sql", (42,)) # $ getSql="some sql"
|
cursor.execute("some sql", (42,)) # $ getSql="some sql"
|
||||||
|
cursor.executemany("some sql", [(42,)]) # $ getSql="some sql"
|
||||||
|
|||||||
Reference in New Issue
Block a user