2

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?...

3
  • 3
    Django already protects you from SQL injection attacks. Yes, the data that looks like a SQL command is inserted into the database, that is the proper response to such data. A successful SQL injection attack would execute the SQL instead of inserting it as data. Commented Sep 26, 2017 at 7:27
  • 1
    Note, one of the points of using a model form is that you can just do form.save() to create your post object. In any case, you should always access form.cleaned_data rather than request.POST. Commented Sep 26, 2017 at 7:34
  • That's why we use frameworks like Django. There is no need to reinvent the wheel. The framework takes care not only of SQL injection, but also XSS, CSRF, form validation and much more. You should invest more time in reading the documentation and getting to know the tool. Commented Sep 26, 2017 at 7:43

1 Answer 1

16

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.

Sign up to request clarification or add additional context in comments.

5 Comments

tnx ...grate illustrating
Thanks for that explanation @Martijn Pieters. Currently I have injected SQL in my views because I don't understand how I can fetch the data otherwise from Django models. I need to pull out details based on joins between two database tables. Could you please give some headsup on how I can replace the SQL query with maybe some model based query?
@NSP: that's way, way too broad. Django's ORM protects you from injections, and supports joins just fine. See docs.djangoproject.com/en/1.11/topics/db/queries
I have this cur.execute('''select teacher.teacher_id,teacher_name,subject_name from teacher,subject,teaches where(teacher.teacher_id=teaches.teacher_id and subject.subject_id=teaches.subject_id)''') How can I change this with Django ORM? I am new to django, and this aspect is pretty complex to understand. Could you please suggest.
@NSP: sorry, no, I'm not going to do that. Please follow the Django tutorials, they are quite helpful there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.