When creating web applications these days security must come first. Building the application without security and then attempting to retrofit it with security after the fact is a fruitless exercise. There will always be an excuse from upper management that it isn’t a high enough priority to secure it properly, “just fix the worst vulnerabilities and quickly return to that stuff marketing wanted, we have a deadline! We’ll just assume risks, note them, and move on.”
So you’re only real option is to bake security into every application while you’re building it the first time. Pay attention to details and do it right the first time. You won’t get around to it later, trust me. This is a short list of things I think about when designing a new application.
- Do not hard code database connection credentials or application server credentials anywhere in the code. If you can’t get around this, then you must lock that account down to the least amount of privileges it requires to do it’s job.
- You need a strong policy regarding password resets. Attackers just need the answers to a few personal questions about the victim. And a persistent attacker will have already acquired the answers from Facebook, LinkedIn, Twitter, etc. to establish their identity and in turn reset the password. The system needs to be based on questions that are both hard to guess and brute force. Password reseting should not tip off the attacker to whether the username is correct or not.
- Require strong passwords that are long in length and require uppercase, lowercase, numbers, and special characters. You will get push back from whiny users that they can’t remember them. Refer them to LastPass to manage the passwords, so they don’t have to remember them.
- Require that passwords be changed on a fairly regular basis. Again, refer the whiners to LastPass.
- Implement account lockouts after some number of failed attempts, this will reduce the effectiveness of brute force attacks.
- Session tokens must be randomly generated from a source of with a high degree of entropy in order to prevent the attacker from being able to predict and spoof them.
- Session tokens should be regenerated when the user authenticates.
- Session tokens should be regenerated when the user privilege level changes.
- Session tokens should be regenerated when the encryption status changes.
- When the user stops being active in the application after a timeout threshold has been reached, the user should then be logged out.
- Implement features to detect session spoofing and session hijacking attempts. If detected, the session should be destroyed, forcing the real user to re-authenticate to the application again.
- When the user logs out, the session and any left over goodies on the server should be torn down and removed from memory.
- The session cookie attributes need to set the HttpOnly flag and the Secure flag.
document.cookieobject. This session ID protection is mandatory to prevent the session ID from being stolen through Cross-sites Scripting (XSS) attacks.
- The “Secure” flag tells the web browsers to only send the cookie through an encrypted SSL/TLS connection (https only).
- Don’t use wildcard domain scoped cookies. Be very specific and don’t be lazy with a wildcard cookie.
- The Sec Ops team should continuously educate the software developers and QA teams on security and latest attack vectors in applications.
- The Sec Ops team must be part of the change management process, new vulnerability arrive at our door step daily now. Developers are more then likely not be aware of them.
- The Sec Ops team must continually perform penetration testing on the developed applications in order to find the vulnerabilities before and after they go into production.
- The Sec Ops team must define the security requirements of the application, preferably before the development has started, in the design phase. Take a security first approach. Product Owners won’t want to hear it, but it’s a battle worth fighting.
- The Sec Ops team must perform code reviews looking for potential coding vulnerabilities, like hard coding passwords, unvalidated inout controls, openings for SQL injection and XSS.
- The Sec Ops team will not catch every thing. It’s fantasy to believe otherwise. When something is missed and exploited by an attacker, bad things are going to happen. You need to have an Incident Response Team.
- The Incident Response Team must have a plan in place to handle the aftermath, determine whether the attackers gained a foothold into the compromised servers (dropping a rootkit), determine how the application was exploited in order to remediate the vulnerability so that it doesn’t happen again.
User Input Forms
- Do no build SQL queries dynamically using string concatenation from user input. Use parameterized SQL queries for better protection against SQL injection attacks.
- Embed a random value (a token) that is not known to third parties into each HTML form to help prevent Cross-Site Request Forgery (CSRF) attacks. This CSRF protection token must be unique to each request. This helps prevents a spoofed CSRF request from being submitted because the attacker does not know the value of the token.
- Use the
X-Frame-Optionsheader to help prevent content from being loaded by the attacker’s site in a frame (Clickjacking). This may not be an option for all browsers.
Content-Security-Policyheader to help prevent reflected Cross-Site Scripting (XSS) attacks.
X-XSS-Protectionheader help prevent against many common reflected Cross-Site Scripting (XSS) attacks.
- Do not trust the browser to select the correct character encoding, set it for every page using the http header or in meta tags. Setting a consistent encoding like UTF-8 for your application helps prevent Cross-Site Scripting (XSS) attacks.
- If you must accept file uploads from the client make you must validate the type of file, the size of the file, and the file contents if possible.
- Do no allow the client to override the destination path for a file uploaded by the client.
- If you are hosting user uploaded content, use the
X-Content-Type-Options: nosniffheader to ensure that text/plain files are not sniffed to a different file type.
- Validate the input source. If input is expected from a POST request, then it shouldn’t be coming from a GET request.
- Always use the principle of least privilege, the opposite of giving admin rights to everything. Permissions should be deny all by default, then explicitly grant access at a granular level.
- Do not trust the client to tell you what it has rights to, access decisions must be made on the server side.
- Do not use unvalidated forwards, which allows the attacker to access private content without authentication.
- Do not use unvalidated redirects, which allows the attacker to trick the victim into landing on a malicious site.
- Use SSL/TLS everywhere. It’s free now so there’s no excuse anymore, go to https://letsencrypt.org/ .
- Disable the weak SSL ciphers on the servers. This will help prevent encryption downgrade attacks.
- Disable HTTP access for every page, force HTTPS.
- Use the
Strict-Transport-Securityheader to make sure that the attacker’s browser does not talk to the server over non-SSL. This helps prevent SSL stripping attacks.
- Store user passwords using hashing techniques with a strong algorithm like SHA-256. Simply hashing the password a single time does not protect the password. Use iterative hashing with a random salt to make the hash stronger.
- If you are not salting your hashes, then 2 identical passwords will have the same resulting hash.
- Implement key management. Protect the private keys like the crown jewels because they are.
- Not all Certificate Authorities (CA) are equal, even though they should be. Some CA’s had been compromised and aren’t trust worthy. Pick a trusted one to partner with.
- Frequently evaluate that sensitive data is not being unnecessarily stored online. Air gap it or otherwise, move it offline.
- Do not leak intelligence from error messages. Create generic customized messages to hide the internal state of the application. Stack traces should not be handed over to the attacker.
- No unhandled exceptions should be allowed. Do not allow the attacker to crash the application and know it. The attacker will focus his efforts on exploiting it.
- Log all authentication attempts, successes and failures.
- Log all user privilege changes.
- Log all admin level activities, after all, they are high value targets by attackers. If a dormant admin level service account starts doing things outside of whats expected, then you’ll know it has been compromised.
- Log all access to sensitive data.
- Do not log passwords, keys, and other sensitive personal information.
- Protect the integrity of the logs. Logs are targets for attackers, first they are scanned for anything that will help them for an intrusion, then wiped clean to cover their tracks.