Injections, SQL and otherwise - Basic Security Part 4

NB: This is the fourth post in a series of posts on web application security.

SQL Injection

SQL injection is a vector that lets a user insert their own SQL into a statement sent to your database server. The typical example is:

1.
"SELECT * FROM users WHERE username = ‘" + username + "’ AND \
2.
password = ‘" + password ‘"
3.
Then someone submits `' OR 1=1; --` as their password. To avoid this, use parameterized queries or, better yet, use framework-level functions like ORMs that make it very difficult to do this wrong. In Django, use the [auth framework](https://docs.djangoproject.com/en/dev/topics/auth/), but even if you wanted to look up users for another reason, [use the ORM](https://docs.djangoproject.com/en/dev/topics/db/queries/):
1.
User.objects.get(username=username)
Sometimes ORMs don’t produce the fastest queries, or we want to do complicated joins. That’s fine, there are still tools. Django provides the [Queryset.raw()](https://docs.djangoproject.com/en/dev/topics/db/sql/#passing-parameters-into-raw) method. Use it correctly:
1.
User.objects.raw(‘SELECT username FROM auth_user WHERE username=%s’,
2.
                 [username])

Other types of Injections

SQL injection is only one type of injection. Much worse are injections that let users run code on your server. PHP’s backtick passthrough and Python’s subprocess.call are both dangerous places that need to be carefully audited. If possible, they should be avoided completely. If that’s not possible, don’t put user data in there. eval() is another risky thing to avoid if at all possible.

In Python, the ast.literal_eval method is both safe and more often than not does whatever it was you thought you needed eval() to do in the first place.

If you’re running code on the server under any user, even the web process user—which should have almost no permissions—don’t put user data in there. Just don’t do it. Find another way.