-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathSqlInjection.qhelp
More file actions
64 lines (55 loc) · 2.19 KB
/
SqlInjection.qhelp
File metadata and controls
64 lines (55 loc) · 2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
If a database query (such as a SQL or NoSQL query) is built from
user-provided data without sufficient sanitization, a user
may be able to run malicious database queries.
</p>
<p>
This also includes using the <code>TextClause</code> class in the
<code><a href="https://pypi.org/project/SQLAlchemy/">SQLAlchemy</a></code> PyPI package,
which is used to represent a literal SQL fragment and is inserted directly into the
final SQL when used in a query built using the ORM.
</p>
</overview>
<recommendation>
<p>
Most database connector libraries offer a way of safely
embedding untrusted data into a query by means of query parameters
or prepared statements.
</p>
</recommendation>
<example>
<p>
In the following snippet, a user is fetched from the database using three
different queries.
</p>
<p>
In the first case, the query string is built by
directly using string formatting from a user-supplied request parameter.
The parameter may include quote characters, so this
code is vulnerable to a SQL injection attack.
</p>
<p>
In the second case, the user-supplied request attribute is passed
to the database using query parameters. The database connector library will
take care of escaping and inserting quotes as needed.
</p>
<p>
In the third case, the placeholder in the SQL string has been manually quoted. Since most
databaseconnector libraries will insert their own quotes, doing so yourself will make the code
vulnerable to SQL injection attacks. In this example, if <code>username</code> was
<code>; DROP ALL TABLES -- </code>, the final SQL query would be
<code>SELECT * FROM users WHERE username = ''; DROP ALL TABLES -- ''</code>
</p>
<sample src="examples/sql_injection.py" />
</example>
<references>
<li>Wikipedia: <a href="https://en.wikipedia.org/wiki/SQL_injection">SQL injection</a>.</li>
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html">SQL Injection Prevention Cheat Sheet</a>.</li>
<li><a href="https://docs.sqlalchemy.org/en/14/core/sqlelement.html#sqlalchemy.sql.expression.text.params.text">SQLAlchemy documentation for TextClause</a>.</li>
</references>
</qhelp>