- Common Node.js security best practices
- Use SSL/TLS to encrypt the client-server connection
- Comparing secret values and hashes securely
- Generating random strings using Node.js
- OWASP A2: Broken Authentication
- OWASP A5: Broken access control
- OWASP A6: Security Misconfiguration
- OWASP A3: Sensitive Data Exposure
- OWASP A9: Using Components With Known Security Vulneraibilities
- OWASP A10: Insufficient Logging & Monitoring
- OWASP A7: Cross-Site-Scripting (XSS)
- Protect Personally Identifyable Information (PII Data)
- Have a security.txt File [PRODUCTION]
- Have a SECURITY.md File [OPEN SOURCE]
Common Node.js security best practices
The common security guidelines section contains best practices that are standardized in many frameworks and conventions, running an application with SSL/TLS, for example, should be a common guideline and convention followed in every setup to achieve great security benefits.
Use SSL/TLS to encrypt the client-server connection
TL;DR: In the times of free SSL/TLS certificates and easy configuration of those, you do no longer have to weigh advantages and disadvantages of using a secure server because the advantages such as security, support of modern technology and trust clearly outweigh the disadvantages like minimal overhead compared to pure HTTP.
Otherwise: Attackers could perform man-in-the-middle attacks, spy on your users’ behaviour and perform even more malicious actions when the connection is unencrypted
Read More: Running a secure Node.js server
Comparing secret values and hashes securely
TL;DR: When comparing secret values or hashes like HMAC digests, you should use the crypto.timingSafeEqual(a, b)
function Node provides out of the box since Node.js v6.6.0. This method compares two given objects and keeps comparing even if data does not match. The default equality comparison methods would simply return after a character mismatch, allowing timing attacks based on the operation length.
Otherwise: Using default equality comparison operators you might expose critical information based on the time taken to compare two objects
Generating random strings using Node.js
TL;DR: Using a custom-built function generating pseudo-random strings for tokens and other security-sensitive use cases might actually not be as random as you think, rendering your application vulnerable to cryptographic attacks. When you have to generate secure random strings, use the crypto.randomBytes(size, [callback])
function using available entropy provided by the system.
Otherwise: When generating pseudo-random strings without cryptographically secure methods, attackers might predict and reproduce the generated results, rendering your application insecure
Going on, below we’ve listed some important bits of advice from the OWASP project.
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 ( 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
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
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 prevent client-side JavaScript code from accessing the cookies
- Protect each VPC with strict and restrictive access rules
- Prioritize threats using any standard security threat modeling like STRIDE or DREAD
- Protect against DDoS attacks using HTTP(S) and TCP load balancers
- Perform periodic penetration tests by specialized agencies
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 a 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
OWASP A9: Using Components With Known Security Vulneraibilities
- 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)
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 equivelant actions like forgot password)
- Include the time and username that initiated the update in each DB record
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 defense-in-depth mitigating control against XSS
Protect Personally Identifyable Information (PII Data)
Personally identifiable information (PII) is any data that can be used to identify a specific individual
Protect Personally Identifyable Information in the Applications by encrypting them
Follow the data privacy laws of the land
Reference laws:
European Union: GDPR - https://ec.europa.eu/info/law/law-topic/data-protection_en
India: https://meity.gov.in/writereaddata/files/Personal_Data_Protection_Bill,2018.pdf
Singapore: https://www.pdpc.gov.sg/Legislation-and-Guidelines/Personal-Data-Protection-Act-Overview
Have a security.txt File [PRODUCTION]
TL;DR: Have a text file called security.txt
under /.well-known
directory (/.well-known/security.txt) or in the root directory (/security.txt) of your website or your web application in production. security.txt
file should contain details using which security researchers can report vulnerabilities and also the contact details of the responsible person/group (email id and/or phone numbers) to whom the reports have to be sent.
Otherwise: You may not be notified about the vulnerabilities. You will miss the opportunity to act on the vulnerabilities in time.
Have a SECURITY.md File [OPEN SOURCE]
TL;DR: To give people instructions for responsibly reporting security vulnerabilities in your project, you can add a SECURITY.md file to your repository’s root, docs, or .github folder. SECURITY.md file should contain details using which security researchers can report vulnerabilities and also the contact details of the responsible person/group (email id and/or phone numbers) to whom the reports have to be sent.
Otherwise: You may not be notified about the vulnerabilities. You will miss the opportunity to act on the vulnerabilities in time.