summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2017-11-07 13:07:12 -0500
committerGitHub <noreply@github.com>2017-11-07 13:07:12 -0500
commit327f0f37ce3c1e5ac3a19668add237ddd92266d6 (patch)
tree1d0cbcd3edff80caeb40315b0c4f005d75c86f38 /docs
parent998c9dd599cd907bb38f440fff13a808571589f8 (diff)
Fixed #28770 -- Warned that quoting a placeholder in a raw SQL string is unsafe.
Thanks Hynek Cernoch for the report and review.
Diffstat (limited to 'docs')
-rw-r--r--docs/ref/models/expressions.txt18
-rw-r--r--docs/ref/models/querysets.txt11
-rw-r--r--docs/topics/db/sql.txt23
3 files changed, 38 insertions, 14 deletions
diff --git a/docs/ref/models/expressions.txt b/docs/ref/models/expressions.txt
index affafa331b..764ec8a955 100644
--- a/docs/ref/models/expressions.txt
+++ b/docs/ref/models/expressions.txt
@@ -654,11 +654,19 @@ should avoid them if possible.
.. warning::
- You should be very careful to escape any parameters that the user can
- control by using ``params`` in order to protect against :ref:`SQL injection
- attacks <sql-injection-protection>`. ``params`` is a required argument to
- force you to acknowledge that you're not interpolating your SQL with user
- provided data.
+ To protect against `SQL injection attacks
+ <https://en.wikipedia.org/wiki/SQL_injection>`_, you must escape any
+ parameters that the user can control by using ``params``. ``params`` is a
+ required argument to force you to acknowledge that you're not interpolating
+ your SQL with user-provided data.
+
+ You also must not quote placeholders in the SQL string. This example is
+ vulnerable to SQL injection because of the quotes around ``%s``::
+
+ RawSQL("select col from sometable where othercol = '%s'") # unsafe!
+
+ You can read more about how Django's :ref:`SQL injection protection
+ <sql-injection-protection>` works.
Window functions
----------------
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
index 017cdcae29..4903d61132 100644
--- a/docs/ref/models/querysets.txt
+++ b/docs/ref/models/querysets.txt
@@ -1262,8 +1262,15 @@ generated by a ``QuerySet``.
You should be very careful whenever you use ``extra()``. Every time you use
it, you should escape any parameters that the user can control by using
- ``params`` in order to protect against SQL injection attacks . Please
- read more about :ref:`SQL injection protection <sql-injection-protection>`.
+ ``params`` in order to protect against SQL injection attacks.
+
+ You also must not quote placeholders in the SQL string. This example is
+ vulnerable to SQL injection because of the quotes around ``%s``::
+
+ "select col from sometable where othercol = '%s'" # unsafe!
+
+ You can read more about how Django's :ref:`SQL injection protection
+ <sql-injection-protection>` works.
By definition, these extra lookups may not be portable to different database
engines (because you're explicitly writing SQL code) and violate the DRY
diff --git a/docs/topics/db/sql.txt b/docs/topics/db/sql.txt
index 969026e56e..dc2bcc50b6 100644
--- a/docs/topics/db/sql.txt
+++ b/docs/topics/db/sql.txt
@@ -210,20 +210,26 @@ argument.
.. warning::
- **Do not use string formatting on raw queries!**
+ **Do not use string formatting on raw queries or quote placeholders in your
+ SQL strings!**
It's tempting to write the above query as::
>>> query = 'SELECT * FROM myapp_person WHERE last_name = %s' % lname
>>> Person.objects.raw(query)
- **Don't.**
+ You might also think you should write your query like this (with quotes
+ around ``%s``)::
- Using the ``params`` argument completely protects you from `SQL injection
- attacks`__, a common exploit where attackers inject arbitrary SQL into
- your database. If you use string interpolation, sooner or later you'll
- fall victim to SQL injection. As long as you remember to always use the
- ``params`` argument you'll be protected.
+ >>> query = "SELECT * FROM myapp_person WHERE last_name = '%s'"
+
+ **Don't make either of these mistakes.**
+
+ As discussed in :ref:`sql-injection-protection`, using the ``params``
+ argument and leaving the placeholders unquoted protects you from `SQL
+ injection attacks`__, a common exploit where attackers inject arbitrary
+ SQL into your database. If you use string interpolation or quote the
+ placeholder, you're at risk for SQL injection.
__ https://en.wikipedia.org/wiki/SQL_injection
@@ -257,6 +263,9 @@ For example::
return row
+To protect against SQL injection, you must not include quotes around the ``%s``
+placeholders in the SQL string.
+
Note that if you want to include literal percent signs in the query, you have to
double them in the case you are passing parameters::