When it comes to security it is an unfortunate reality that technologies are rarely straight forward to use or easy to deploy. So it is quite refreshing to find something that breaks that mould. There is a fantastic project called django-secure which I believe does just this.
The idea is to provide a way to enforce secure defaults for django projects. It achieves this in two key ways. The first being a deployment check that you can run as a part of typical django-admin manage.py workflow, the other is a security middleware that enables security features that django doesn't do by default. To demonstrate the usage of django-secure I will walk through how to apply it to the OpenStack Horizon dashboard and discuss the features which it enables.
For those that are unfamiliar with the OpenStack project it has many facets, most of which can be administrated and controlled by a project called Horizon. It is conceivable that this dashboard could be deployed and exposed over the network so it is worth examining how to make it a little more secure. Horizon is essentially a typical django project so the steps here will be pretty universal for other projects.
The first thing that you need to do is install the django-secure package. This can be done using the Python pip package manager:
$ pip install django-secure
Next, we add django-secure into the list of INSTALLED_APPS within the django settings. I'm assuming you are doing this within a devstack envrionment (you probably shouldn't be testing things like this in production!) so the file we are looking for is /opt/stack/horizon/openstack_dashboard/settings.py (or as local_settings.py) overrides.
INSTALLED_APPS = (
With this change alone you will be able to see the benefit of django-secure. You should now be able to issue:
python manage.py checksecure
And have django-secure complain about all the things Horizon isn't doing by default (you can see the complaining part here -http://fpaste.org/61388/. This is a good start for figuring out what hardening options you can enable to make your site more secure. The remainder of this post will be devoted to deving into what those options are and what they actually do. But first lets add one more option to Horizons settings.
The django-secure project is more than just deployment check, it is actually middleware too so we need to enable the middleware before we continue. To do this add the following line (towards the top) of your MIDDLEWARE_CLASSES.
MIDDLEWARE_CLASSES = (
Ok so what does this do? This gives us the ability to enable some options that do some cool things that can help prevent a number of attacks. I'm going to break these down individually but I'm going to begin by discussing the options that are a part of django and how they are configured in devstack. The correct guideance for these options is available within the OpenStack security guide (http://docs.openstack.org/sec/).
SESSION_COOKIE_SECURE = True
This option will only allow the session cookie to be sent over a secure connection. Horizon does not enable this by default in devstack as it isn't configured to use HTTPS in devstack.
SESSION_COOKIE_HTTPONLY = True
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
This option is probably debatable. Essentially when set to true the user will have to reauthenticate everytime they open a new browser window. The alternative will use persistent sessions that have a lifetime as long as the expiry set in the session cookie. Horizon sets this to true by default.
The django-secure framework will also check for the correct usage of CSRF, and strength of the secret key. It also introduces some useful middleware that ensures some of the best security features available within the browser are being utilized. This options are discussed below.
SECURE_SSL_REDIRECT = True
Setting this option to true will ensure that all non HTTPS requests are sent permnant redirects to a HTTPS URL. As the Horizon dashboard is an administrative console it is essential that all traffic travels over a secure channel.
SECURE_HSTS_INCLUDE_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
These two options enable HTTP Strict Transport Security. It tells compliant browsers to only access this website (and subdomains) via HTTPS for the specified time period. This helps to prevent SSL stripping attacks and ensures traffic will only travel over a secure connection.
SECURE_FRAME_DENY = True
This enables the X-Frame-Options header which tells browsers not allow the site to be accessed via frames. A common technique employed by clickjackers.
SECURE_CONTENT_TYPE_NOSNIFF = True
This prevents the browser from guessing asset content types leading to assumptions about the content that could be exploited.
SECURE_BROWSER_XSS_FILTER = True
Enables dormant XSS filter capabilities in older browsers.
With these settings enabled almost all of the security features that most modern browsers employ will be enabled. To complete the configuration we need to enable SSL in the Apache web server. This will involve generating or obtaining SSL certificates to use with the dashboard and modifying the web servers configuration.
Example SSL configuration for http.conf
SetEnvIf User-Agent ".MSIE.*" nokeepalive ssl-unclean-shutdown
. (WSGI configuraiton here)
python manage.py checksec again should no longer report any failures and you should have a much more secure administrative interface to your OpenStack deployment.