Django under the hood: Django security - Florian Apolloner

Tags: django, djangocon

(One of my summaries of a talk at the 2015 django under the hood conference).

Florian Apolloner talks about django security. Django security, so it won’t be about attacks against the SSL protocol as those are outside of django. (But do look at https://www.ssllabs.com/ssltest/).

In case you think you’ve found a security bug in django: look at https://djangoproject.com/security and only contact security@djangoproject.com. Don’t report such a bug publicly, as that makes it much harder to make and distribute a proper fix.

Regarding security: look at the owasp top 10 list of the most common found vulnerabilities in websites.

SQL/SMTP/OS injections

Basic rule: don’t ever trust user input. Everything the user can input into your web interface is to be treated as dangerous. select * from auth_user where username=%s is easy to exploit if you inject a username string inputted by the user directly.

If you use django, you don’t run much risk as django does the good thing internally regarding escaping.

Defense in layers is best. If you limit the parameter to an integer in your url patterns and select users by id instead of a string, you already prevent many problems.

The same goes for OS interaction. Use Django components instead of rolling your own storage or email. Django’s components are secure. If there’s no django component to do it, like ldap authentication: watch out as you’re on your own.

Generally: string interpolations are bad.

To repeat: do not ever trust user input. This includes everything the user sends, including http headers and filenames/content types in uploads.

Authentication and session management

Basic rule: use what django provides. Django does a lot to keep you safe. He showed some examples.

Passwords are stored encrypted. Multiple algorithms are available out of the box. Iterations are increased every release. Upgrading to new algorithms are always possible.

Since django 1.9 you can have password validators. Length checks, numeric characters, common words. And you can add your own. Please use them.

Django allows pasword reset links to be used. For this, nothing needs to be stored on the server. A link is mailed to the user. The link can be used once and only once to reset the password.

The link includes a user ID, a timestamp and an HMAC hash of your last login time and two other items. You can look at django.core.signing.* if you need to roll your own.

Cross site scripting (XSS)

A lot of XSS is prevented by django’s auto-escaping. But: it is HTML only. It replaces < > ' " with entities. Always use quotes around attributes.

Javascript requires different escaping! var mystr="{{ value|escapejs}}".

The canonical XSS attack results in something like data="</script><script>alert('xss')'//".

If you want to insert json inside a template:

var json = JSON.parse('{{ data|escapejs }}');

Or you can use django-argonauts:

var json = {{ data|json }};

Defense in depth: you can enable django’s XSS protection. It enables a http header that tells your browser to be extra picky about what it allows: no inline js, no event handlers.

The most important thing: check your libraries and your own code. Many people just do mark_safe(json.dumps(). Many many people.

Cross site request forgery (CSRF)

Basically: <img src="mybank.com/t/?amount=1000&to=apollo13">.

It is enabled by default. It protects your site against an attacker sending one of your users to your site with a hurtful request. Django protects against it by generating a random value in the form and setting one in your cookie. If you go directly to the form and submit it, everything compares. If you come from a different site, they don’t match.

Unvalidated redirects and forwards

This means requests to /auth/login/?next=http://evil.com. After login you are on evil.com. So use django.utils.http.is_safe_url(). It contains more comments than code, which means that it is code that is hard to get right :-)

Security checklist

Run manage.py check --deploy and try to get everything right. It checks for security settings that you might have missed.

TODOs

What more could we do in Django?

  • Rate limiting for login and so.

  • Two factor authentication. (TOTP and U2F as reference implementations).

  • CSRF improvmeents (#16859).

  • JSON filter for templates. This will be added to django core.

  • Enhance SecurityMiddleware. (Look at https://github.com/twitter/secureheaders)

  • Implement Content-Security-Policy.

  • Limit POST/GET data length.

Repairing a locomotive

Image: repairing a locomotive

water-gerelateerd Python en Django in het hartje van Utrecht!
 
vanrees.org logo

About me

My name is Reinout van Rees and I work a lot with Python (programming language) and Django (website framework). I live in The Netherlands and I'm happily married to Annie van Rees-Kooiman.

Weblog feeds

Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):