LOGO

A smooth, flexible CMS to create the designs you like,
built on top of the powerful Django framework.

Tip: making SSL-only websites

When deploying websites, adding SSL should in my opinion be a standard practise. This for a few reasons:

  • Protecting the privacy of your users.
  • Protecting your visitors when they use Wifi-hotspots
  • Protecting your admin interface against session-cookie-theft.
  • Making life harder for government agencies to read traffic.

There are a few things to do to implement SSL (actually TLS) property

1. Django configuration

When a site is accessable over HTTPS only, the following settings give maximum security:

# For https only sites:
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True

# Improve cookie protection
SESSION_COOKIE_HTTPONLY = True  # can't read cookie from JavaScript, default in modern Django
SESSION_EXPIRE_AT_BROWSER_CLOSE = True

# Enable clickjacking protection 
# Can be overwritten per view using the @xframe_options_.. decorators
X_FRAME_OPTIONS = 'DENY'        # Prevent iframes, alt: SAMEORIGIN.

MIDDLEWARE_CLASSES = (
    # ...
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    # ...
)

The first two fields avoid exposing the cookie over HTTP, which could give attackers an opportunity to read the cookie. When a hacker is able to read the session-cookie, they can impersonate themselves as your account, and log into your site. This is obviously a security risk.

The remaining settings are optional, but give better security. A clickjacking site for instance, tries show your site in an iframe, and overlay an element to catch user input.

2. Nginx configuration

Just adding SSL settings to Nginx is not enough. To get an A+ score in the SSL test you need to configure the SSL ciphers properly. There are various combinations, this is an example:

    ssl_ciphers "ECDH+AESGCM ECDH+AES256 DH+AESGCM DH+AES256 ECDH+AES128 DH+AES ECDH+3DES DH+3DES RSA+AES RSA+3DES !RC4 !ADH !AECDH !MD5 !DSS";

    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # Diffie-Hellman parameter for DHE ciphersuites, recommended at least 2048 bits
    ssl_dhparam /etc/ssl/private/dhparam.pem;

    # Enforce strict policies in browsers, and be SSL-only
    add_header Strict-Transport-Security "max-age=31536000";  # optional: ; includeSubdomains
    add_header X-Content-Type-Options nosniff;

 This combination ensures that:

  • Browsers get the best possible encryption by default
  • ECDH ciphers are preferred, which give Perfect Forward Secrecy.
  • SSL v3 and RC4 are disabled, which is really insecure.

Please verify these cipher settings against the current SSL test suite, it's possible you may need other ciphers in the future. The dhparam file is needed to give a higher key exchange for the DH-ciphers. Generate this file using:

/usr/bin/openssl dhparam -out /etc/ssl/private/dhparam.pem 4096

It takes a few minutes to generate this file!

3. Updating content

When making sites SSL-only, modern browsers will no longer allow "mixed content". This can effect staff users that write content for the website. For example, when embedding a YouTube video, the URL should use the https:// protocol prefix. Browsers won't load the video otherwise. You can also use // as prefix, so browsers pick the current protocol automatically.

Bonus: you can add Content Security Policy headers to limit the domains for images, scripts, iframes that can be embedded.

Other resources

Other good resources about security:

Leave a reply

cancel reply
Fork me on GitHub