diff --git a/rules/python/shared/common/sql_user_input.yml b/rules/python/shared/common/sql_user_input.yml index 50f05516..8ce25869 100644 --- a/rules/python/shared/common/sql_user_input.yml +++ b/rules/python/shared/common/sql_user_input.yml @@ -17,6 +17,22 @@ patterns: auxiliary: - id: python_shared_common_sql_user_input_sanitizer patterns: + - pattern: $($<_>) + filters: + - variable: CONVERTER_CLASS + detection: python_shared_lang_import4 + scope: cursor + filters: + - variable: MODULE1 + values: [mysql] + - variable: MODULE2 + values: [connector] + - variable: MODULE3 + values: [conversion] + - variable: MODULE4 + values: [MySQLConverter] + - variable: NAME + values: [escape] - pattern: $.escape($<_>) filters: - variable: CONVERTER diff --git a/tests/python/lang/sql_injection/testdata/main.py b/tests/python/lang/sql_injection/testdata/main.py index 888b79b9..f9e48123 100644 --- a/tests/python/lang/sql_injection/testdata/main.py +++ b/tests/python/lang/sql_injection/testdata/main.py @@ -20,9 +20,9 @@ def asyncpg(): conn = await asyncpg.connect(user='mish', password='password') query = "SELECT * FROM bar WHERE foo=" + user_input # bearer:expected python_lang_sql_injection - values = await conn.fetch(query) + values = await conn.fetch(query) await conn.close() - + def pg8000(): import pg8000.native as pg import pg8000.dbapi @@ -60,6 +60,19 @@ def mysql_connector_sanitizer(): cursor.execute(user_input) cursor.execute(converter.escape(user_input)) +def mysql_connector_sanitizer_2(): + import mysql.connector + from mysql.connector.conversion import MySQLConverter + + cursor = self.con.cursor() + # bearer:expected python_lang_sql_injection + cursor.callproc(user_input, user_input) + + sanitized_input = MySQLConverter.escape(str(user_input)) + sanitized_values = [MySQLConverter.escape(str(value)) for value in user_input] + # ok + cursor.callproc(sanitized_input, sanitized_values) + def pymysql_sanitizer(): import pymysql