Generic
Here resides some generic good security practices regarding web development
About
Needless to say, most websites suffer from various types of bugs which may eventually lead to vulnerabilities. Why would this happen so often? There can be many factors involved including misconfiguration, shortage of engineers' security skills, etc. [1] We are here to combat thisβ¦
Best practices
Here is a list of common attacks to cover ourselves from:
CSV Injection
Ensure that no cells begins with these characters: "=", "+", "-", "@", tab "0x09", carriage return "0x0D"
We need to ensure content will be read as text by the spreadsheet editor
Take care of field separators and quotes
Wrap each cell field in double quotes
Prepend each cell field with a single quote
Escape every double quote using an additional double quote
SQL Injection
If using an ORM, check about its SQLi defenses
Enforce Least privilege
NoSQL injection
Avoid unsanitized user inputs in application code
Some DBs has built-in features for secure query building... check them out
Apply the rule of Least Privilege
Know your language to avoid using vulnerable constructs
XXE - XML eXternal Entity
The safest way is to disable DTDs completely
For detailed XXE prevention guidance, check the OWASP Cheatsheet
CSRF - Cross-Site Request forgery
Check if your framework has built-in CSRF protection and use it
If not, add CSRF tokens to all state changing requests and validate them on the backend
For stateful software use the synchronizer token pattern
For stateless software use double submit cookies
For API-driven sites that don't use
<form>
tags, use custom request headersConsider using SameSite Cookie Attribute
Consider implementing user interaction based protection for highly sensitive operations
Do NOT use GET requests for state changing operations
If you need to do that, protect those resources against CSRF
Clickjacking (OWASP Clickjacking Defense Cheat Sheet)
Prevent the browser from loading the page in an iframe by using X-Frame-Options or CSP headers (specially "frame-ancestors")
Prevent sesion cookies from being included when the page is loaded in a frame using the SameSite cookie attribute
Implement JavaScript code in the page to attempt to prevent it being loaded in a frame ("frame-buster" technique)
SSRF - Server-Side Request forgery
Check where the application can send request only to identified and trusted applications
Use Input validation in all application layers
Disable the support for the following of redirections to prevent the bypass of the input validation
Apply the allow list approach
Check where the application can send request to ANY external IP address or domain name
Open Redirects
Never allow open redirects as a default (if possible)
Do not allow the URL as user input for destination (if possible)
If user input can't be avoided
Ensure it's valid
Sanitize the input
Ensure it's authorized
Force redirects to go through a page notifying users they are going to another site and make them confirm
Follow an allow-list approach, rather than a block list
Map the URL provided by the user to a short name (not enumerable) or hash to avoid tampering and reduce enumeration vulnerabilities
File Uploads
List allowed extensions, only allow safe and critical extensions for business functionallity
Use input validation before validation the extensions
Validate the file type, do NOT trust the Content-Type header (it can be spoofed)
Change the filename to something generated by the application
Set a filename length limit
Restrict allowed characters in the filename
Set a file size limit
Only allow authorized users to upload files
Store files on a different server or outside the webroot
If you have to provide public access to these files use a handler to map filenames inside the application
Run the file through an antivirus (such as VirusTotal) or in a sandbox, to validate it doesn't contain malicious data
Ensure that used libraries for this purpose are securely configured and up to date
Protect against CSRF attacks
CSP (Content Security Policies)
Ensure to have a strong/strict CSP headers. Only allow what needed for your web to load
Upgrade insecure requests (or only serve via HTTPS)
Enable a report directive to receive violations of prevented behaviours to specified locations
Use tools to evaluate your CSP policy (such as CSP evaluator)
Use HSTS (HTTP Strict Transport Security)
See related problems nevertheless
Cryptography
See Cryptography
JWT (JSON Web Tokens)
Do NOT include secrets in the payload
Do NOT allow 'none' algorithm for signing (more info)
Always verify the token (issuer, signature, retrieve actual public keys...)
Avoid sensitive data exposure by not inserting a whole object into the JWT (break into parts, has to be lightweight)
Use strong/recommended algorithms for signing
Authentication
UserIds
Make sure they are case-insensitive and unique
You can avoid username enumeration by mapping each username with an incremental ID internally and use a mapped hash (ex. using Hashids) to avoid enumeration
If using email as user id, perform input validation
Do NOT allow login with sensitive accounts (that can be used internally)
Do NOT use same authentication solution for internal resources and for public access
Implement proper password strength controls (see OWASP Password Storage Cheatsheet)
Implement a proper "forgot password" mechanism (see OWASP Forgot Password Cheat Sheet)
Store password securely (see OWASP Password Storage Cheatsheet)
Always compare password hashes using safe functions
Only allow authentication via HTTPs or other encrypted and strong transport
Require re-authentication or 2FA/MFA for sensitive features
Do NOT give hints in error messages to avoid enumeration attacks (be generic with error messages)
Protect against automated attacks (see also OWASP Credential Stuffing Cheatsheet)
Log and monitor your authentication mechanism
Set
spellcheck="false"
in the HTML password field to avoid filtering the password (Spell-jacking)Set
autocomplete="off"
if possible in the HTML password fieldLet know the users about the benefits of using a password manager
Cookies
Always limit their access as possible
Always set all Cookies with the "Secure" flag
Avoid access to the cookie via JS by setting "HttpOnly"
Set the expiration time ("Expires" & "Max-Age" directives) as soon as is necessary
Set the "Domain" directive as restrictive as possible
Set the "Path" directive as restrictive as possible
Set the "SameSite" directive accordingly to your needs and the more restrictive possible ("Strict" always recommended)
Consider enabling HTTP Public Key Pinning (HPKP)
Set a Referrer Policy and consider never redirect a user to an external page with the referrer header (to be secretive)
Create a restrictive "robots.txt" file to avoid robots crawl and disclose private information or portions of a website
Try to load external data from CDNs or others by specifying the "integrity" and "crossorigin" attributes to enable "Subresource Integrity"
Consider setting the header "X-Content-Type-Options" to avoid the client to guess the MIME type of the response (MIME type sniffing)
Add a "security.txt" file in the root of your page to tell security researchers how to disclose vulnerabilities
Another things to take care about
Here is another check list of things to know about and protect (this does not mean they are less important!):
Prototype Pollution
HTTP Parameter Pollution
Command Injection
Deserialization attacks
ORM Injection
FTP Injection
Web Cache Poisoning
Relative Path Overwrite
Remote Code Execution
Header injection
Browser Exploitation
ModSecurity (see OWASP ModSecurity Core Rule Set)
SSL/TLS
NFS
Fingerprint
DNS Rebinding
WAF (Web Application Firewalls)
Resources
Sources
[2]: Authentication - OWASP Cheat Sheet Series
Last updated