I think a lot of web designers and web masters have almost no idea what are the most important things to focus on beginning on day one. There is a lot of information out there, and most of it is well-intentioned and good advice. But some issues are harder to fix retroactively than others.
The following represents a list of website security items that should be implemented with each new website launch. Rather than waiting until the site has gone live, these things should be done up front because fixing them afterwards is often a lot more painful. Because these are way harder to shoe-horn and retrofit after deployment, we rarely see these done correctly in practice.
- Content-Security-Policy: We highly recommend you implement this with the alerting turned on so that you can see what’s breaking as your devs are working on it. It can be extremely difficult to build into your site retroactively, because it usually involves either adding so many whitelists that it’s practically worthless, or having to go painstakingly through your site to create a massive inventory, hoping that you don’t miss anything along the way. There is now a bookmarklet to help as well.
- X-Frame-Options: We highly recommend you put it into in block mode, which will help with clickjacking attacks and other framing attacks. This can be painful to implement after the fact because many sites over time start framing your site and using it in that manner. Getting each site to update their site that links to you can be hugely painful.
- anti-CSRF cryptographic nonces on all secure functions: We recommend building nonces (one time tokens tied to user sessions) into each form and validating that to ensure that your site can’t be forced to perform actions. This can be a huge pain to retrofit because it means touching a database or shared memory on every hit — not to mention the code that needs to be inserted into each page with a form and subsequent function to validate the nonce.
- DAL (data/database access layer): DALs help to prevent SQLinjection. Few companies know about them or use them correctly, but by front ending all databases with an abstraction layer many forms of SQL injection simply fail to work because they are not correctly formed. DALs can be expensive and extremely complex to retrofit because every single database call requires modification and interpolation at the DAL layer.
- Unwritable file system: Making the website code and webserver configs on the file system unwritable by the web user is a huge security advantage post-compromise. Almost no websites take this preventative action but it makes many forms of exploitation nearly impossible. Retrofitting this is difficult to do later because tons of things tend to rely on local file system writes as the site evolves over time, even though this type of design can be extremely sloppy.
- Forensically secure logging: Logs that are sent off-host or are made otherwise inaccessible by the web user help prevent overwriting the file system, local include attacks, removing the attacker’s tracks from the logs and so on. It’s difficult to explain how useful it is to have untampered logs until after it’s too late. It is difficult to retrofit because it usually requires setting up a different logging infrastructure and establishing some way to copy or automatically transport the logs.
- Secure credential/passwd/secret questions and answers storage: How many sites have we seen compromised and all of the information is taken? In most cases it is either plaintext or poorly hashed with an obsolete hashing algorithm, like MD5. Assuming that everything in the database is copied off, the attacker still shouldn’t have access to anything without spending huge amounts of resources to crack individual rows. This can be extremely complex to retrofit because many site functions rely on existing database designs and the associated structured data.
- Security frameworks: Libraries for handling and sanitizing or rejecting user input (XSS, SQLi, Command injection, etc…) greatly improves your ability to proactively protect yourself when used uniformly across the site. Libraries like this tend to require changing many site functions and these frameworks therefore touch almost every input, so it can be a nightmare to build after the fact.
- autocomplete=”off” and strong passwords: To protect your site from brute force and from the recent rash of security issues in autocomplete, it is a good idea to implement both of these. If your users think the browser will remember their passwords for them it’s going to be a nightmare when you turn autocomplete=”off” later. If you turn it off early, they’ll choose weak passwords. So you really need both at the same time. You don’t want the support costs of all of your users calling you trying to figure out how to get back into their account.
There are plenty of other great things you can and should do to protect your website, but for the most part they are far easier to implement after the fact than these would be if you do forget them.