Oct 20, 2011

Web App Security: Django and the OWASP Top 10


  1. Code Injection:  For most Django applications, the primary code injection risk is SQL injection.  Django protects against SQL injection through its ORM abstraction layer, which automatically escapes input.  Note that it's possible toperform raw sql queries with Django, any any such code should be manually audited for if it interacts with direct user input.  Though raw SQL is needed occasionally, especially for optimization, it's generally a code smell in a Django application.

    If your application interacts with any other backends, like LDAP, you'll want to investigate those third-party libraries separately.  Client-side javascript is also mitigated through its templating system; see #2 below.
  2. Cross-site scripting:  Generally, the most important way to mitigate XSS is to prevent unescaped user input from making it into your application's rendered HTML. Django’s templating system facilitates this by automatically excaping all variable values.  If you don't want to escape something on the front end, you have to explicitly tell Django not to escape it.  In your code reviews, you can concentrate more on the few areas of your app where you don't escape user input.
  3. Session hijacking:  With the default Django SessionMiddleware, the framework doesn't allow any session data in the url.  Session IDs are also stored as hashes, mitigating brute force attacks.

    While you'll still want to ensure your code doesn't expose direct session data to the user in any way, Django makes it difficult to expose that information.
  4. Insecure direct object references:  Django has several mechanisms in place to mitigate IDORs.  It provides a special "slug" field if you don't want to pass object IDs around as parameters.  Django 1.2 also lets you explicitly name read-only fields in the admin, so you can prevent users from hacking together forms that alter protected  data.

    Note that you'll still want to manually audit your code to expose areas where users can access arbitrary object data, especially outside of the admin.
  5. Cross-site request forgery:  Django has built-in CSRF protection middleware, so it would be extraordinarily difficult for an attacker to maliciously submit a form to your site using an authenticated user's credentials.
  6. Security misconfiguration:  This is one item that is largely outside the domain of the web framework itself; it's more about the application's deployment environment.  You need to keep up with Python security updates, Django security updates, and keep track of any third-party libraries you use for security updates.  You need to disable ports/services you don't use, and more.  With complex apps, this can be a huge job.

    Fortunately, there are great, frequently-updated blogs for both the Python andDjango core teams where you can keep track of security updates.  It's also easy to follow security announcement lists for your web server (e.g. apachenginx) or operating system to keep track of security updates.
  7. Insecure cryptographic storage:  If the only secure information you're encrypting is user password data, you're all set if you use Django's built-in user authentication.  Django encrypts password data using SHA1 by default, but also supports MD5 and crypt out-of-the-box.

    If your application directly stores or manipulates any sensitive user data, you'll need to audit that code manually.  Fortunately, OWASP maintains a great cryptographic storage cheat sheet to help you along the way.
  8. Failure to restrict URL access:  Django has great built-in support for restricting access to specific content.  Access is always controlled at the view level, before anything is rendered.  You're able to restrict access for specific actions or forentire views.  Note that you'll still want to audit each url/action in your app to ensure that you're restricting access the way you intended.  It's easy to miss a @login_required decorator or forget to lock down an AJAX action.
  9. Insufficient transport layer protection:  In many cases, strong transport layer protection means using SSL.  Though this falls outside the domain of Django itself, the framework does provide some help:  Django supports the secure cookie protocol (PDF link to research paper), and also allows developers to force the use of secure cookies over HTTPS.
  10. Unvalidated redirects and forwards:  Because of Django's robust, built-in URL access restriction (see #7), it would be very hard for an attacker to take advantage of unvalidated redirects.  Again, since access is handled at the view level, you can't [easily] redirect users to a different url on your site without access control.

    Additionally, Django's built-in user authentication system doesn't allow off-site redirect links as url parameters.  Note that you'll still want to audit your code for any manual use of redirect links in URL parameters.

No comments: