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

Improve detecting SQL injections in f-strings #917

Merged
merged 2 commits into from Feb 24, 2023

Conversation

kfrydel
Copy link
Contributor

@kfrydel kfrydel commented Jun 28, 2022

This commit fixes detecting SQL injection
in statements like:

f"SELECT {column_name} FROM foo WHERE id = 1"
f"INSERT INTO {table_name} VALUES (1)"
f"UPDATE {table_name} SET id = 1"

Before this change, the bandit was analyzing statements
by parts, especially, in the case of:
"SELECT {column_name} FROM foo WHERE id = 1"
it was firstly checking "SELECT " for being
an SQL statement and then " FROM foo WHERE id = 1".
Neither of these parts match to defined
regular expressions:

    r"(select\s.*from\s|"
    r"delete\s+from\s|"
    r"insert\s+into\s.*values\s|"
    r"update\s.*set\s)",

Thus SQL injection was not detected.

This commit makes bandit checking the whole SQL
statement for matching the above regexps.
However, since it uses ast.unparse it works
only for python >= 3.9.

Resolves: #916

@@ -92,8 +92,25 @@ def _evaluate_ast(node):
elif hasattr(ast, "JoinedStr") and isinstance(
node._bandit_parent, ast.JoinedStr
):
statement = node.s
wrapper = node._bandit_parent._bandit_parent
if hasattr(ast, 'unparse'):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pyflakes seems to be able to handle JoinedStr https://github.com/PyCQA/pyflakes/blob/e19886e583637a7e2eec428cc036094b9630f2d0/pyflakes/checker.py#L1740-L1753 why can't we do something similar here without unparse?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking at my pull request!
Do you mean something like this? Now it works for all versions of python.

This commit fixes detecting SQL injection
in statements like:

f"SELECT {column_name} FROM foo WHERE id = 1"
f"INSERT INTO {table_name} VALUES (1)"
f"UPDATE {table_name} SET id = 1"

Before this change, the bandit was analyzing statements
by parts, especially, in the case of:
"SELECT {column_name} FROM foo WHERE id = 1"
it was firstly checking "SELECT " for being
an SQL statement and then " FROM foo WHERE id = 1".
Neither of these parts match to defined
regular expressions:

    r"(select\s.*from\s|"
    r"delete\s+from\s|"
    r"insert\s+into\s.*values\s|"
    r"update\s.*set\s)",

Thus SQL injection was not detected.

This commit makes bandit checking the whole SQL
statement for matching the above regexps.

Resolves: PyCQA#916
Copy link
Member

@sigmavirus24 sigmavirus24 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on my phone so it's hard to check, but are there test cases for multiline f strings (using python's implicit concatenation) mixed with regular strings?

@kfrydel
Copy link
Contributor Author

kfrydel commented Feb 24, 2023

We do not have tests for multiline SQL strings at all in the current code as far as I can see. I added some in my second PR: #915. I can move them here (assuming that you will merge this PR as the first one) and add tests for multiline f-strings. I will get back to you when done.

@sigmavirus24
Copy link
Member

No i mean implicit concatenation. Think something like

s = (
 'a'
'b'
'c'
)

Note no commas. This turns into 'abc'

@kfrydel
Copy link
Contributor Author

kfrydel commented Feb 24, 2023

Yes, I didn't know that name but I googled it. I added tests for multiline strings (as in the second PR but without nosec cases) and some for implicit concatenation: https://github.com/PyCQA/bandit/pull/917/files#diff-a691abc0c51d7e1432ef4486311a653dc950d5f440f71f7093f6f4f0892fe077R89

@sigmavirus24 sigmavirus24 merged commit 7e6f580 into PyCQA:main Feb 24, 2023
@kfrydel
Copy link
Contributor Author

kfrydel commented Feb 27, 2023

@sigmavirus24 Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

bandit does not detect SQL injection (B608) if FormattedValue is between "select" and "from" clauses
2 participants