mirror of
https://github.com/github/codeql.git
synced 2026-05-05 21:55:19 +02:00
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:
@@ -1,17 +1,14 @@
|
||||
edges
|
||||
| sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:12:16:12:22 | django.request.HttpRequest |
|
||||
| sql_injection.py:12:16:12:22 | django.request.HttpRequest | sql_injection.py:12:16:12:27 | django.http.request.QueryDict |
|
||||
| sql_injection.py:12:16:12:27 | django.http.request.QueryDict | sql_injection.py:12:16:12:39 | externally controlled string |
|
||||
| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:19:63:19:66 | externally controlled string |
|
||||
| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:22:88:22:91 | externally controlled string |
|
||||
| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:23:76:23:79 | externally controlled string |
|
||||
| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:24:78:24:81 | externally controlled string |
|
||||
| sql_injection.py:19:63:19:66 | externally controlled string | sql_injection.py:19:13:19:66 | externally controlled string |
|
||||
| sql_injection.py:22:88:22:91 | externally controlled string | sql_injection.py:22:38:22:91 | externally controlled string |
|
||||
| sql_injection.py:23:76:23:79 | externally controlled string | sql_injection.py:23:26:23:79 | externally controlled string |
|
||||
| sql_injection.py:24:78:24:81 | externally controlled string | sql_injection.py:24:28:24:81 | externally controlled string |
|
||||
| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:19:70:19:77 | externally controlled string |
|
||||
| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:22:88:22:95 | externally controlled string |
|
||||
| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:23:76:23:83 | externally controlled string |
|
||||
| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:24:78:24:85 | externally controlled string |
|
||||
| sql_injection.py:19:70:19:77 | externally controlled string | sql_injection.py:19:24:19:77 | externally controlled string |
|
||||
| sql_injection.py:22:88:22:95 | externally controlled string | sql_injection.py:22:38:22:95 | externally controlled string |
|
||||
| sql_injection.py:23:76:23:83 | externally controlled string | sql_injection.py:23:26:23:83 | externally controlled string |
|
||||
| sql_injection.py:24:78:24:85 | externally controlled string | sql_injection.py:24:28:24:85 | externally controlled string |
|
||||
#select
|
||||
| sql_injection.py:19:13:19:66 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:19:13:19:66 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value |
|
||||
| sql_injection.py:22:38:22:91 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:22:38:22:91 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value |
|
||||
| sql_injection.py:23:26:23:79 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:23:26:23:79 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value |
|
||||
| sql_injection.py:24:28:24:81 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:24:28:24:81 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value |
|
||||
| sql_injection.py:19:24:19:77 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:19:24:19:77 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value |
|
||||
| sql_injection.py:22:38:22:95 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:22:38:22:95 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value |
|
||||
| sql_injection.py:23:26:23:83 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:23:26:23:83 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value |
|
||||
| sql_injection.py:24:28:24:85 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:24:28:24:85 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value |
|
||||
|
||||
@@ -1,28 +1,40 @@
|
||||
"""This is copied from ql/python/ql/test/library-tests/web/django/test.py
|
||||
and a only a slight extension of ql/python/ql/src/Security/CWE-089/examples/sql_injection.py
|
||||
"""
|
||||
|
||||
from django.conf.urls import patterns, url
|
||||
from django.conf.urls import url
|
||||
from django.db import connection, models
|
||||
from django.db.models.expressions import RawSQL
|
||||
|
||||
class Name(models.Model):
|
||||
class User(models.Model):
|
||||
pass
|
||||
|
||||
def save_name(request):
|
||||
def show_user(request, username):
|
||||
with connection.cursor() as cursor:
|
||||
# GOOD -- Using parameters
|
||||
cursor.execute("SELECT * FROM users WHERE username = %s", username)
|
||||
User.objects.raw("SELECT * FROM users WHERE username = %s", (username,))
|
||||
|
||||
if request.method == 'POST':
|
||||
name = request.POST.get('name')
|
||||
curs = connection.cursor()
|
||||
#GOOD -- Using parameters
|
||||
curs.execute(
|
||||
"insert into names_file ('name') values ('%s')", name)
|
||||
#BAD -- Using string formatting
|
||||
curs.execute(
|
||||
"insert into names_file ('name') values ('%s')" % name)
|
||||
# BAD -- Using string formatting
|
||||
cursor.execute("SELECT * FROM users WHERE username = '%s'" % username)
|
||||
|
||||
#BAD -- other ways of executing raw SQL code with string interpolation
|
||||
Name.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % name))
|
||||
Name.objects.raw("insert into names_file ('name') values ('%s')" % name)
|
||||
Name.objects.extra("insert into names_file ('name') values ('%s')" % name)
|
||||
# BAD -- other ways of executing raw SQL code with string interpolation
|
||||
User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username))
|
||||
User.objects.raw("insert into names_file ('name') values ('%s')" % username)
|
||||
User.objects.extra("insert into names_file ('name') values ('%s')" % username)
|
||||
|
||||
urlpatterns = patterns(url(r'^save_name/$',
|
||||
save_name, name='save_name'))
|
||||
# BAD (but currently no custom query to find this)
|
||||
#
|
||||
# It is exposed to SQL injection (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#extra)
|
||||
# For example, using name = "; DROP ALL TABLES -- "
|
||||
# will result in SQL: SELECT * FROM name WHERE name = ''; DROP ALL TABLES -- ''
|
||||
#
|
||||
# This shouldn't be very widespread, since using a normal string will result in invalid SQL
|
||||
# Using name = "example", will result in SQL: SELECT * FROM name WHERE name = ''example''
|
||||
# which in MySQL will give a syntax error
|
||||
#
|
||||
# When testing this out locally, none of the queries worked against SQLite3, but I could use
|
||||
# the SQL injection against MySQL.
|
||||
User.objects.raw("SELECT * FROM users WHERE username = '%s'", (username,))
|
||||
|
||||
urlpatterns = [url(r'^users/(?P<username>[^/]+)$', show_user)]
|
||||
|
||||
Reference in New Issue
Block a user