Application Security Best Practices / Defensive Programming
Tags: defensiveprogramming, applicationsecurity, bestpractices, securitybestpractices
Published: 2020-09-05 19:09:34

---
title: Application Security Best Practices / Defensive Programming
published: true
description: Defensive Programming / Application Security best practices
tags: defensiveprogramming, applicationsecurity, bestpractices, securitybestpractices
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/l3tzg8knya0dxrbtk8u4.jpg
---
#### My Other lists
- [JavaScript/Node Best Practices](https://dev.to/nirajkvinit/javascript-node-best-practices-2i4d)
- [Software Development General Best Practices](https://dev.to/nirajkvinit/software-development-general-best-practices-1747)
- [PR Code Review Practices](https://dev.to/nirajkvinit/pr-code-review-best-practices-5363)

---------------------------

Application security is a critical topic. Being a good engineer requires being aware of Application security best practices. You should practice defensive programming to ensure a robust, secure application. I have collected points and created this list for my reference. Hope, you too get benefitted out of this. This is a big list, but worth reading to the end.

1. Always Handle Exceptions
2. Validate user input to avoid common vulnerabilities (e.g. XSS, SQL-Injection, Remote Code Execution, etc.)
3. Escape HTML, JS and CSS output
4. HTML Encode Before Inserting Untrusted Data into HTML Element Content
5. JavaScript Encode Before Inserting Untrusted Data into JavaScript Data Values
6. URL Encode Before Inserting Untrusted Data into HTML URL Parameter Values
7. Implement type conversion with strict exception handling
8. Apply minimum and maximum value range check for numerical parameters and dates, minimum, and maximum length check for strings.
9. Use an array of allowed values for small sets of string parameters (e.g. days of week).
10. Implement CAPTCHA
11. Don't use Basic Auth. Use standard authentication instead (e.g. JWT, OAuth)
12. Check if all the endpoints are protected behind authentication to avoid broken authentication process
13. User own resource ID should be avoided. Use /me/orders instead of /user/654321/orders
14. Don't reinvent the wheel in Authentication, token generation, password storage. Use the standards.
15. Tokens must be transmitted using the Authorization header on every request
16. Authorization Code should be short-lived / Make token expiration (TTL, RTTL) as short as possible
17. Don't store sensitive data in the JWT payload, it can be decoded easily
18. Use Max Retry and jail features in Login
19. Consider using rate-limiting (throttling) to protect your resources from DDoS or brute force attacks
20. Code reviewer should always consider security guidelines during code reviews
21. Do not forget to turn the DEBUG mode OFF
22. Hide error details from clients, wherever applicable respond with generic error messages avoid revealing details of the failure unnecessarily
23. Do not pass technical details (e.g. call stacks or other internal hints) to the client
24. Never return sensitive data like credentials, Passwords, or security tokens
25. Avoid publishing secrets to the npm registry or Code repository
26. Inspect for outdated packages
27. Use a random complicated key (JWT Secret) to make brute-forcing the token very hard.
28. Support blacklisting JWTs or other authentication tokens
29. Do not use GET requests for state-changing operations
30. Run Node.js as a non-root user
31. Limit request payload size using a reverse-proxy or a middleware
32. The application must be programmed to defend against attacks from the OWASP TOP 10 (More details below)
33. Implement proper and regular security auditing of the application
34. Don't auto-increment IDs. Use UUID instead
35. Use a CDN for file uploads
36. Write audit logs before and after every security-related events
37. Consider logging token validation errors in order to detect attacks.
38. Take care of log injection attacks by sanitising log data beforehand.
39. Use HTTPOnly cookie flag
40. OAuth security
 - While using oAuth, Always validate redirect_uri server-side to allow only whitelisted URLs
 - Always try to exchange for code and not tokens (don't allow response_type=token)
 - Define the default scope, and validate scope parameters for each application
41. Reject any non-TLS requests by not responding to any HTTP request to avoid any insecure data exchange. Respond to HTTP requests by 403 Forbidden
42. Use HTTPS on server side to avoid MITM (Man in the Middle Attack)
43. Setting HTTP headers appropriately can help to lock down and secure your web application. Consider using Helmet library if you are building API on node
44. Your API should convert the received data to their canonical form or reject them. Return 400 Bad Request with details about any errors from bad or missing data.
45. Use the proper HTTP method according to the operation: GET (read), POST (create), PUT/PATCH (replace/update), and DELETE (to delete a record), and respond with 405 Method Not Allowed if the requested method isn't appropriate for the requested resource
46. Don't use any sensitive data (credentials, Passwords, security tokens, or API keys) in the URL, but use standard Authorization header
47. All the data exchanged with the REST API must be validated by the API.
48. Serialize your JSON (to avoid arbitrary JavaScript remote code execution)
49. Validate content-type on request Accept header (Content Negotiation) to allow only your supported format (e.g. application/xml, application/json, etc.) and respond with 406 Not Acceptable response if not matched
50. Validate content-type of posted data as you accept (e.g. application/x-www-form-urlencoded, multipart/form-data, application/json, etc.)
51. Use an API Gateway service to enable caching, Rate Limit policies (e.g. Quota, Spike Arrest, or Concurrent Rate Limit) and deploy APIs resources dynamically
52. If you are dealing with huge amount of data, use Workers and Queues to process as much as possible in background and return response fast to avoid HTTP Blocking
53. Audit your application's design, implementation and security with unit/integration tests coverage frequently
54. Implement proper access control for resources and its access
55. Do not store sensitive information to localStorage
56. Measure and guard the memory usage
57. Discover errors and downtime using APM products
58. Use tools that automatically detect vulnerabilities
59. Embrace linter security rules
60. Prevent query injection vulnerabilities with ORM/ODM libraries
61. Prevent unsafe redirects
62. Avoid DOS attacks by explicitly setting when a process should crash
63. Protect the input values from being cached by the browser.
64. Text areas and input fields for PII (name, email, address, phone number) and login credentials (username, password) should be prevented from being stored in the browser. e.g.  <input type="text" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off"></input>
65. Do NOT allow login with sensitive accounts (i.e. accounts that can be used internally within the solution such as to a back-end / middle-ware / DB) to any front-end user-interface
66. Implement Proper Password Strength Controls, Include password strength meter to help users create a more complex password and block common and previously breached passwords 
67. Implement Secure Password Recovery Mechanism
68. Store Passwords in a Secure Fashion
69. Compare Password Hashes Using Safe Function and in a timely manner
70. Transmit Passwords Only Over TLS or Other Strong Transport
71. Require Re-authentication for Sensitive Features
72. Consider Strong Transaction Authentication and Authorization
73. Require JavaScript and Block Headless Browsers
74. Notify users about unusual security events
75. Regular review of user accounts and their permissions
76. Secure File uploads
 - Whitelist allowed extensions. Only allow safe and critical extensions for business functionality
 - Ensure that input validation is applied before validating the extensions.
 - Validate the file type, don't trust the Content-Type header as it can be spoofed
 - Change the filename to something generated by the application
 - Set a filename length limit. Restrict the allowed characters if possible
 - Set a file size limit
 - Only allow authorised users to upload files
 - Store the files on a different server. If that's not possible, store them outside of the webroot
 - In the case of public access to the files, use a handler that gets mapped to filenames inside the application (someid -> file.ext)
 - Run the file through antivirus or a sandbox if available to validate that it doesn't contain malicious data
 - Ensure that any libraries used are securely configured and kept up to date
 - Protect the file upload from CSRF attacks
77. In the event of authentication exception, Using any of the authentication mechanisms (login, password reset or password recovery), an application must respond with a generic error message regardless of whether:
 - The user ID or password was incorrect.
 - The account does not exist.
 - The account is locked or disabled.
78. Implement a mechanism to protect the application against Automated Attacks
79. Implement Multi-Factor Authentication for optional but better security where advanced security is required
80. Enable logging and monitoring of authentication functions to detect attacks/failures on a real-time basis
 - Ensure that all failures are logged and reviewed
 - Ensure that all password failures are logged and reviewed
 - Ensure that all account lockouts are logged and reviewed
81. Don't rely on client logic for security
82. Don't rely on client business logic
83. Don't perform encryption in client side code. Use TLS/SSL and encrypt on the server!
84. Use CSRF Protection
85. Be vigilant about the following:
 - **Injection:** Almost any source of data can be an injection vector, environment variables, parameters, external and internal web services, and all types of users. Injection flaws occur when an attacker can send hostile data to an interpreter.
 - **Broken Authentication:** Attackers have access to hundreds of millions of valid username and password combinations for credential stuffing, default administrative account lists, automated brute force, and dictionary attack tools. Session management attacks are well understood, particularly in relation to unexpired session tokens
 - **Sensitive Data Exposure:** Rather than directly attacking crypto, attackers steal keys, execute man-in-the-middle attacks, or steal clear text data off the server, while in transit, or from the user's client, e.g. browser. A manual attack is generally required. Previously retrieved password databases could be brute-forced by Graphics Processing Units (GPUs). Secure Search Serves, do not log sensitive data
 - **Broken Access Control:** Exploitation of access control is a core skill of attackers. Access control is detectable using manual means, or possibly through automation for the absence of access controls in certain frameworks.
 - **Security Misconfiguration:** Attackers will often attempt to exploit unpatched flaws or access default accounts, unused pages, unprotected files and directories, etc to gain unauthorized access or knowledge of the system
 - **Cross-Site Scripting (XSS):** XSS is the second most prevalent issue in the OWASP Top 10, and is found in around two-thirds of all applications
 - **Insecure Deserialization:** Exploitation of deserialization is somewhat difficult, as off-the-shelf exploits rarely work without changes or tweaks to the underlying exploit code.
Using Components with Known Vulnerabilities: While it is easy to find already-written exploits for many known vulnerabilities, other vulnerabilities require concentrated effort to develop a custom exploit.
 - **Insufficient Logging & Monitoring:** Exploitation of insufficient logging and monitoring is the bedrock of nearly every major incident. Attackers rely on the lack of monitoring and timely response to achieve their goals without being detected
86. Forgot Password Service Guidelines
 - Return a consistent message for both existent and non-existent accounts.
 - Ensure that the time taken for the user response message is uniform.
 - Use a side-channel to communicate the method to reset their password.
 - Use URL tokens for the simplest and fastest implementation.
 - Ensure that generated tokens or codes are:
        - Randomly generated using a cryptographically safe algorithm.
        - Sufficiently long to protect against brute-force attacks.
Stored securely.
        - Single-use and expire after an appropriate period
87. Secure Management endpoints	
 - Avoid exposing management endpoints via the Internet.
 - If management endpoints must be accessible via the Internet, make sure that users must use a strong authentication mechanism, e.g. multi-factor.
 - Expose management endpoints via different HTTP ports or hosts preferably on a different NIC and restricted subnet.
 - Restrict access to these endpoints by firewall rules or use of access control lists.
88. Where possible, always log:
 - Input validation failures e.g. protocol violations, unacceptable encodings, invalid parameter names and values
 - Output validation failures e.g. database recordset mismatch, invalid data encoding
 - Authentication successes and failures
 - Authorization (access control) failures
 - Session management failures e.g. cookie session identification value modification
 - Application errors and system events e.g. syntax and runtime errors, connectivity problems, performance issues, third party service error messages, file system errors, file upload virus detection, configuration changes
 - Application and related systems start-ups and shut-downs, and logging initialization (starting, stopping or pausing)
 - Use of higher-risk functionality e.g. network connections, addition or deletion of users, changes to privileges, assigning users to tokens, adding or deleting tokens, use of systems administrative privileges, access by application administrators,all actions by users with administrative privileges, access to payment cardholder data, use of data encrypting keys, key changes, creation and deletion of system-level objects, data import and export including screen-based reports, submission of user-generated content especially file uploads
 - Legal and other opt-ins e.g. permissions for mobile phone capabilities, terms of use, terms & conditions, personal data usage consent, permission to receive marketing communications
89. In order to secure authorization-based transaction in such a system:
 - Authorization should be performed and enforced server-side
 - Transaction verification data should be generated server-side
 - Application should prevent authorization credentials brute-forcing
 - Transaction data should be protected against modification
 - Confidentiality of the transaction data should be protected during any client / server communications
 - When a transaction is executed, the system should check whether it was authorized
 - Authorization credentials should be valid only by a limited period of time
 - Authorization credentials should be unique for every operation
90. Protect Personally Identifiable Information (PII Data)
 - Personally identifiable information (PII) is any data that can be used to identify a specific individual
 - Protect Personally Identifiable Information in the Applications by encrypting them
 - Follow the data privacy laws of the land

#### Some Important OWASP Guidelines
1. **OWASP A2: Broken Authentication**
 - Require MFA/2FA for important services and accounts
 - Rotate passwords and access keys frequently, including SSH keys
 - Apply strong password policies, both for ops and in-application user management (link OWASP password recommendation)
 - Do not ship or deploy your application with any default credentials, particularly for admin users or external services you depend on
 - Use only standard authentication methods like OAuth, OpenID, etc.  avoid basic authentication
 - Auth rate-limiting: Disallow more than X login attempts (including password recovery, etc.) in a period of Y
 - On login failure, don't let the user know whether the username or password verification failed, just return a common-auth error
 - Consider using a centralized user management system to avoid managing multiple accounts per employee (e.g. GitHub, AWS, Jenkins, etc) and to benefit from a battle-tested user management system
2. **OWASP A3: Sensitive Data Exposure**
 - Only accept SSL/TLS connections, enforce Strict-Transport-Security using headers
 - Separate the network into segments (i.e. subnets) and ensure each node has the least necessary networking access permissions
 - Group all services/instances that need no internet access and explicitly disallow any outgoing connection (a.k.a private subnet)
 - Store all secrets in vault products like AWS KMS, HashiCorp Vault or Google Cloud KMS
 - Lockdown sensitive instance metadata using metadata
 - Encrypt data in transit when it leaves a physical boundary
 - Don't include secrets in log statements
 - Avoid showing plain passwords in the frontend, take necessary measures in the backend and never store sensitive information in plaintext
3. **OWASP A5:  Broken access control**
 - Respect the principle of least privilege  -  every component and DevOps person should only have access to the necessary information and resources
 - Never work with the console/root (full-privilege) account except for account management
 - Run all instances/containers on behalf of a role/service account
 - Assign permissions to groups and not to users. This should make permission management easier and more transparent for most cases
4. **OWASP A6: Security Misconfiguration**
 - Access to production environment internals is done through the internal network only, use SSH or other ways, but never expose internal services
 - Restrict internal network access  - explicitly set which resource can access other resources (e.g. network policy or subnets)
 - If using cookies, configure it to "secured" mode where it's being sent over SSL only
 - If using cookies, configure it for "same-site" only so only requests from same domain will get back the designated cookies
 - If using cookies, prefer "HttpOnly" configuration that prevents client-side JavaScript code from accessing the cookies
 - Protect each VPC with strict and restrictive access rules
 - Prioritize threats using any standard security threat modelling like STRIDE or DREAD
 - Protect against DDoS attacks using HTTP(S) and TCP load balancers
 - Perform periodic penetration tests by specialized agencies
5. **OWASP A7: Cross-Site-Scripting (XSS)**
 - Use templating engines or frameworks that automatically escape XSS by design, such as EJS, Pug, React, or Angular.  -  - Learn the limitations of each mechanisms XSS protection and appropriately handle the use cases which are not covered
 - Escaping untrusted HTTP request data based on the context in the HTML output (body, attribute, JavaScript, CSS, or URL) will resolve Reflected and Stored XSS vulnerabilities
 - Applying context-sensitive encoding when modifying the browser document on the client-side acts against DOM XSS
 - Enabling a Content-Security Policy (CSP) as a defence-in-depth mitigating control against XSS
6. **OWASP A9: Using Components With Known Security Vulnerabilities**
 - Scan docker images for known vulnerabilities (using Docker's and other vendors' scanning services)
 - Enable automatic instance (machine) patching and upgrades to avoid running old OS versions that lack security patches
 - Provide the user with both 'id', 'access' and 'refresh' token so the access token is short-lived and renewed with the refresh token
 - Log and audit each API call to cloud and management services (e.g who deleted the S3 bucket?) using services like AWS CloudTrail
 - Run the security checker of your cloud provider (e.g. AWS security trust advisor)
7. **OWASP A10: Insufficient Logging & Monitoring**
 - Alert on remarkable or suspicious auditing events like user login, new user creation, permission change, etc
 - Alert on irregular amount of login failures (or equivalent actions like forgot password)
 - Include the time and username that initiated the update in each DB record





**NOTE:** If you want to update this list, please comment, I'll incorporate your changes.

**Ref.**
https://github.com/shieldfy/API-Security-Checklist
https://owasp.org/www-project-automated-threats-to-web-applications/
https://github.com/OWASP/CheatSheetSeries
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Authentication_Cheat_Sheet.md
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Abuse_Case_Cheat_Sheet.md
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.md
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Input_Validation_Cheat_Sheet.md
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/REST_Security_Cheat_Sheet.md
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Logging_Cheat_Sheet.md
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Transaction_Authorization_Cheat_Sheet.md
https://github.com/goldbergyoni/nodebestpractices/blob/master/sections/security/commonsecuritybestpractices.md
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Nodejs_Security_Cheat_Sheet.md