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

Iman Salehi
  • 908
  • 2
  • 14
  • 34
  • 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. – Martijn Pieters Sep 26 '17 at 07: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`. – Daniel Roseman Sep 26 '17 at 07: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. – cezar Sep 26 '17 at 07:43

1 Answers1

15

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.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • tnx ...grate illustrating – Iman Salehi Sep 26 '17 at 07:51
  • 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 Oct 26 '17 at 09:50
  • @NSP: that's way, way too broad. Django's ORM protects you from injections, and supports joins just fine. See https://docs.djangoproject.com/en/1.11/topics/db/queries/ – Martijn Pieters Oct 26 '17 at 09:58
  • 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 Oct 26 '17 at 10:38
  • @NSP: sorry, no, I'm not going to do that. Please follow the Django tutorials, they are quite helpful there. – Martijn Pieters Oct 26 '17 at 10:46
  • @MartijnPieters Sure Thanks for the link – NSP Oct 26 '17 at 10:47