Iman Salehi Iman Salehi - 25 days ago 7
MySQL Question

prevent SQL injection in django forms

I use this for validation:

class MyValidationForm(forms.Form):
title = forms.CharField()
body = forms.Textarea()
taxonomy = forms.IntegerField()


and this is my class-based view:

class blog_createpost(dashboardBaseViews):

template_name = "dashboardtems/blog_createpost.html"

model = {}

def post(self, request, *args, **kwargs):

form = MyValidationForm(request.POST)

if not form.is_valid():
return HttpResponse("not valid")


new_data = post(title=request.POST['title'],
body=request.POST['body'],
description=request.POST['description'],
taxonomy=get_object_or_404(taxonomy,
pk=request.POST['taxonomy']),
writer=request.user)
new_data.save()
return HttpResponse("done")


like you see i check my received request validation in this line:
if not form.is_valid():
and its working on but when i add some
SQL-command
inside my form inputs. it does not preventing to insert the value inside database!..
means i have a field in database which contains some value like
select * from user where 1=1
!.
doesn't it cause sql-injection danger from user inputs?...

Answer Source

You have misunderstood what SQL injection means. Django has successfully protected you from such an attack, the string "select * from user where 1=1" is being treated as data, not as a command, and ended up as a value in the database.

A SQL injection attack alters the SQL that is being executed by the database. A successful attack tricks the database into executing data as commands instead. You'd not end up with select * from user where 1=1 as a value, but instead you end up with the attacker getting access to all results from the user table.

A classic error is to not properly escape data, by constructing the SQL command as a string. Lets say the server uses the following query to look up data for the current user:

SELECT * FROM user WHERE username='$user_id'

where $user_id comes from the request. Normally that'd be a login name, say

user_id = "zopatista"

so the query becomes

SELECT * FROM user WHERE username='zopatista'

If the server does not protect against SQL injection attacks, an attacker can replace user_id and inject more SQL commands:

user_id = "zopatista' OR 1=1 -- "

so after simply interpolating that string into the query, now the server will send the following SQL to the database:

SELECT * FROM user WHERE username='zopatista' OR 1=1 -- '

and suddenly the meaning of the query command has changed and the database will return all rows rather than just one row matching the login name.

The classic XKCD joke on SQL injection goes a step further and injects SQL code that deletes the whole table, rather than try to get access to more information.

A server protecting against SQL injection will make sure that user-provided data is always parameterised, sending the data to the database driver separately from the query to make sure it can never be seen as part of the query.

As long as you use Django's models and querysets, you'll be protected from SQL injection attacks. You would only be at risk if you mixed extra() or RawSQL() with user data without using their parameter features.