10 Ways to Secure Your Webapp

While there is no such thing as 100% secure, you can take specific measures to mitigate against a wide range of attacks and secure your webapp as much as possible.

In this post we discuss some of the steps we’ve taken as part of our efforts to secure our server monitoring tool.

1. Cover the Basics

Before considering any of the suggestions listed here, make sure you’ve covered the basics. Those include industry best practices like protecting against SQL injection, filtering, session handling, and XSRF attacks.

2. Use SSL only

When we launched Server Density in 2009, we offered HTTPS for monitoring agent postbacks but didn’t go as far as to block standard HTTP altogether.

Later on, when we made the switch to HTTPS-only, the change was nowhere near as onerous as we thought it would be.

SSL is often viewed as a performance bottleneck but that isn’t really true. In most situations, we see no reason not to force SSL for all connections right from the start.

Server Density v2 uses a new URL. As part of this, we can force SSL for new agent deployments and access to the web UI alike. We still support the old domain endpoint under non-SSL but will eventually be retiring it.

To get an excellent report on how good your implementation is, run your URL against the Qualys SSL server test. Here is ours:

3. Support SSL with Perfect Forward Secrecy

Every connection to an SSL URL is encrypted using a single private key. If someone obtains that key they can decrypt and access the traffic of that URL.

Perfect forward secrecy addresses this risk by negotiating a new key with every session. A compromise of one key would therefore only affect the data in that one session.

To do this, you need to allow certain cipher suites in your web server configuration.

ECDHE-RSA-AES128-SHA:AES128-SHA:RC4-SHA is compatible with most browsers (for more background and implementation details check out this post).

We terminate SSL at our nginx load balancers and implement SSL using these settings:

You can easily tell if you’re connected using perfect forward secrecy. In Chrome, just click on the lock icon preceding the URL and look for ECDHE_RSA under the Connection tab:

4. Use Strict Transport Security

Forcing SSL should be combined with HTTP Strict Transport Security. Otherwise you run a risk of users entering your domain without specifying a protocol.

For example, typing example.com rather than https://example.com and then being redirected to HTTPS. This redirect opens a security hole because there’s a short time when communication is still over HTTP.

You can address this by sending an STS header with your response. This forces the browser to do the HTTP to HTTPS conversion without issuing a request at all. Instead, it sends the header together with a time setting that the browser stores, before checking again:

strict-transport-security:max-age=315360000; includeSubdomains

Our header is set for 10 years and includes all subdomains because each account gets their own URL, for example: foo.serverdensity.io.

5. Submit STS Settings to Browser Vendors

Even with STS headers in place there’s still a potential hole, because those headers are only sent after the first request.

We have to specifically allow unsafe-eval here, as a number of third party libraries require this. You might not use any third party libraries—or the libraries you do use may not require unsafe eval—in which case you should not allow unsafe-eval.

Be careful with wildcarding on domains which can have any content hosted on them. For example wildcarding *.cloudfront.net would allow anyone to host any script. This is Amazon’s CDN which everyone can upload files to!

Password reset should use an out-of-band method to trigger resets, for example: requiring a username then emailing a one-time, expiring link to the on-record email address where the user can then choose a new password. Here is more guidance and a checklist.

“Remember me” functionality should use secure tokens to recognise the user, and not storing their credentials in cookies.

9. Offer Multi Factor Authentication

If your webapp is anything more than a trivial consumer product, you should implement—and encourage your users to use—multi factor authentication.

This requires them to authenticate using something they carry with them (token), before they can log in. An attacker would therefore need both this token (phone, RSA SecurID etc) and user credentials before they obtain access.

We use the Google Authenticator standard because it has authentication apps available for all platforms, and has libraries for pretty much every platform.

It is quite onerous to install a custom, proprietary MFA app so we don’t recommend you implement your own system.

Be sure to re-authenticate for things like adding/removing MFA tokens. We require re-authentication for all user profile changes.

We do however have a timeout in place during which users won’t have to re-authenticate. This timeout applies for simple actions like changing passwords (adding or removing tokens requires authentication even during the timeout).

To sum up, MFA is crucial for any serious application as it’s the only way to protect against account hijacking.