Python: Don't quote %s in django example

This is vulnerable to SQL injection because of the quotes around %s -- added
some code that highlights this in test.py

Since our examples did this in the safe query, I ended up rewriting them
completely, causing a lot of trouble for myself :D
This commit is contained in:
Rasmus Wriedt Larsen
2019-10-14 16:51:50 +02:00
parent afe7a0536c
commit 471318369b
7 changed files with 128 additions and 90 deletions

View File

@@ -21,20 +21,29 @@ or prepared statements.
<example>
<p>
In the following snippet, from an example django app,
a name is stored in the database using two different queries.
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 attribute.
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.
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" />

View File

@@ -1,21 +1,19 @@
from django.conf.urls import patterns, url
from django.conf.urls import url
from django.db import connection
def save_name(request):
def show_user(request, username):
with connection.cursor() as cursor:
# BAD -- Using string formatting
cursor.execute("SELECT * FROM users WHERE username = '%s'" % username)
user = cursor.fetchone()
if request.method == 'POST':
name = request.POST.get('name')
curs = connection.cursor()
#BAD -- Using string formatting
curs.execute(
"insert into names_file ('name') values ('%s')" % name)
#GOOD -- Using parameters
curs.execute(
"insert into names_file ('name') values ('%s')", name)
# GOOD -- Using parameters
cursor.execute("SELECT * FROM users WHERE username = %s", username)
user = cursor.fetchone()
# BAD -- Manually quoting placeholder (%s)
cursor.execute("SELECT * FROM users WHERE username = '%s'", username)
user = cursor.fetchone()
urlpatterns = patterns(url(r'^save_name/$',
upload, name='save_name'))
urlpatterns = [url(r'^users/(?P<username>[^/]+)$', show_user)]