The following list is targeted at developers and engineers looking to ensure they have taken satisfactory security measures when creating applications, services, and tools.
THE SECURITY MINDSET
- Question the architecture and design.
- Practice best case security by trying to exploit the tool or application you are building.
- Security is not a single fix; facilitate building layers of defenses.
- Understand current security trends and attack patterns.
- Intimately become familiar with the OWASP Top 10
- Change your password at a regular interval, and use a zero knowledge password manager.
- Become aware of your surroundings; especially when working remote at coffee shops or hotels.
- Always assume the worst when connecting to public services; use encryption, masking, and alerting.
AUTHENTICATION SYSTEMS
- Use HTTPS everywhere.
- Store password hashes using Bcrypt (no salt necessary – Bcrypt does it for you).
- Destroy the session identifier after logout.
- Destroy all active sessions on reset password (or offer to).
- Must have the state parameter in OAuth2.
- No open redirects after successful login or in any other intermediate redirects.Al
- When parsing Signup/Login input, sanitize for javascript://, data://, CRLF characters.
- Set secure, httpOnly cookies.
- In Mobile OTP based mobile verification, do not send the OTP back in the response when generate OTP or Resend OTP API is called.
- Limit attempts to Login, Verify OTP, Resend OTP and generate OTP APIs for a particular user. Have an exponential backoff set or/and something like a captcha based challenge.
- Check for randomness of reset password token in the emailed link or SMS.
- Set an expiration on the reset password token for a reasonable period.
- Expire the reset token after it has been successfully used.
USER DATA & AUTHORIZATION
- Any resource access like, my cart, my history should check the logged in user’s ownership of the resource using session id.
- Serially iterable resource id should be avoided. Use /me/orders instead of /user/37153/orders. This acts as a sanity check in case you forgot to check for authorization token.
- Edit email/phone number feature should be accompanied by a verification email to the owner of the account.
- Any upload feature should sanitize the filename provided by the user. Also, for generally reasons apart from security, upload to something like S3 (and post-process using lambda) and not your own server capable of executing code.
- Profile photo upload feature should sanitize all the EXIF tags also if not required.
- For user ids and other ids, use RFC compliant UUID instead of integers. You can find an implementation for this for your language on Github.
- JSON Web Tokens (JWT) are awesome. Use them if required for your single page app/APIs.
ANDROID / IOS
- salt from payment gateways should not be hardcoded.
- secret / auth token from 3rd party SDK’s should not be hardcoded.
- API calls intended to be done server to server should not be done from the app.
- In Android, all the granted permissions should be carefully evaluated.
- On iOS, store sensitive information (authentication tokens, API keys, etc.) in the system keychain. Do not store this kind of information in the user defaults.
- Certificate pinning is highly recommended.
SECURITY HEADERS & CONFIGURATIONS
- Add CSP header to mitigate XSS and data injection attacks. This is important.
- Add CSRF header to prevent cross site request forgery. Also add SameSite attributes on cookies.
- Add HSTS header to prevent SSL stripping attack.
- Add your domain to the HSTS Preload List
- Add X-Frame-Options to protect against Clickjacking.
- Add X-XSS-Protection header to mitigate XSS attacks.
- Update DNS records to add SPF record to mitigate spam and phishing attacks.
- Add subresource integrity checks if loading your JavaScript libraries from a third party CDN. For extra security, add the require-sri-for CSP-directive so you don’t load resources that don’t have an SRI sat.
- Use random CSRF tokens and expose business logic APIs as HTTP POST requests. Do not expose CSRF tokens over HTTP for example in an initial request upgrade phase.
- Do not use critical data or tokens in GET request parameters. Exposure of server logs or a machine/stack processing them would expose user data in turn.
SANITIZATION OF INPUT
- Sanitize all user inputs or any input parameters exposed to user to prevent XSS.
- Always use parameterized queries to prevent SQL Injection.
- Sanitize user input if using it directly for functionalities like CSV import.
- Sanitize user input for special cases like robots.txt as profile names in case you are using a url pattern like coolcorp.io/username.
- Do not hand code or build JSON by string concatenation ever, no matter how small the object is. Use your language defined libraries or framework.
- Sanitize inputs that take some sort of URLs to prevent SSRF.
- Sanitize Outputs before displaying to users.
OPERATIONS & MANAGEMENT
- Check for machines with unwanted publicly open ports.
- Check for no/default passwords for databases especially MongoDB & Redis.
- Always use SSH key authentication when connecting to servers.
- Install updates timely to act upon zero day vulnerabilities like Heartbleed, Shellshock.
- Modify server config to use TLS 1.2 for HTTPS and disable all other schemes.
- Do not leave the DEBUG mode on. In some frameworks, DEBUG mode can give access full-fledged REPL or shells or expose critical data in error messages stacktraces.
- Test and understand the hosting providers DDOS migration strategies.
- Ensure the New Relic agent is running on all production systems.
- Verify syslog is configured and working correctly.
- Always enable encyrption on cloud services such as Amazon S3.
PEOPLE
- Limit access to “need to have”.
- Be polite to bug reporters.
- Have your code review done by a fellow developer and a resource from the security team.
- If you suspect a breach or data or privacy report immediately to the security team.
- Set up Netflix’s Scumblr to source sensitive information surrounding your organization.