Do not rely on Web Application Firewalls for security (however, consider using them to improve security)
If external libraries (e.g. for database access, XML parsing) are used, always use current versions
If you need random numbers, obtain them from a secure/cryptographic random number generator
For every action or retrieval of data, always check access rights
Do not, under any circumstances, attempt to implement cryptographic algorithms yourself. Use high-level libraries for cryptography.
Ensure debug output and error messages do not leak sensitive information
Mark problematic debug output in your code (e.g. //TODO DEBUG REMOVE) even if you intend to remove it after just one test
Do not use “eval()” and similar functions
Avoid “system()” and similar functions if possible
Ensure database servers are not directly reachable from the outside
Consider to block old browsers from using your application
File inclusion and disclosure
Do not take file names for inclusions from user input, only from trusted lists or constants.
If user input is to be used, validate it against a whitelist. Checking if the file exists or if the input matches a certain format is not sufficient.
Avoid having scripts read and pass through files if possible.
If you read and deliver files using user-supplied file names, thoroughly validate the file names to avoid directory traversal and similar attacks and ensure the user is allowed to read the file.
Ensure the application runs with no more privileges than required.
File upload vulnerabilities
Avoid unnecessary file uploads
Ensure that files uploaded by the user cannot be interpreted as script files by the web server, e.g. by checking the file extension (or whatever means your web server uses to identify script files)
Ensure that files cannot be uploaded to unintended directories (directory traversal)
Try to disable script execution in the upload directory
Ensure that the file extension matches the actual type of the file content
If only images are to be uploaded, consider re-compressing them using a secure library to ensure they are valid
Ensure that uploaded files are specified with the correct Content-type when delivered to the user
Prevent users from uploading problematic file types like HTML, CSS, JavaScript, XML, SVG and executables using a whitelist of allowed file types
Prevent users from uploading special files (e.g. .htaccess, web.config, robots.txt, crossdomain.xml, clientaccesspolicy.xml)
Prevent users from overwriting application files
Consider delivering uploaded files with the “Content-disposition: attachment” header
SQL injection
use prepared statements to access the database – or –
use stored procedures, accessed using appropriate language/library methods or prepared statements
Always ensure the DB login used by the application has only the rights that are needed
Cross-site scripting (XSS)
Escape anything that is not a constant before including it in a response as close to the output as possible (i.e. right in the line containing the “echo” or “print” call)
If not possible (e.g. when building a larger HTML block), escape when building and indicate the fact that the variable content is pre-escaped and the expected context in the name
Consider the context when escaping: Escaping text inside HTML is different from escaping HTML attribute values, and very different from escaping values inside CSS or JavaScript, or inside HTTP headers.
This may mean that you need to escape for multiple contexts and/or multiple times. For example, when passing a HTML fragment as a JS constant for later includsion in the document, you need to escape for JS string inside HTML when writing the constant to the JavaScript source, then escape again for HTML when your script writes the fragment to the document. (See rationale for examples)
The attacker must not be able to put anything where it is not supposed to be, even if you think it is not exploitable (e.g. because attempts to exploit it result in broken JavaScript).
Explicitly set the correct character set at the beginning of the document (i.e. as early as possible) and/or in the header.
Ensure that URLs provided by the user start with an allowed scheme (whitelisting) to avoid dangerous schemes (e.g. javascript:-URLs )
don’t forget URLs in redirector scripts
A Content Security Policy may be used as an additional security measure, but is not sufficient by itself to prevent attacks.
XML and internal data escaping
Avoid XML if possible.
For XML, use well-tested, high-quality libraries, and pay close attention to the documentation. Know your library – some libraries have functions that allow you to bypass escaping without knowing it.
If you parse (read) XML, ensure your parser does not attempt to load external references (e.g. entities and DTDs).
For other internal representations of data, make sure correct escaping or filtering is applied. Try to use well-tested, high-quality libraries if available, even if it seems to be more difficult.
If escaping is done manually, ensure that it handles null bytes, unexpected charsets, invalid UTF-8 characters etc. in a secure manner.
Use standard data formats like JSON with proven libraries, and use them correctly. This will probably take care of all your escaping needs.
Make sure browsers do not misinterpret your document or allow cross-site loading
Ensure your document is well-formed
Send the correct content type
Use the X-Content-Type-Options: nosniff header
For XML, provide a charset and ensure attackers cannot insert arbitrary tags
For JSON, ensure the top-level data structure is an object and all characters with special meaning in HTML are escaped
(Un)trusted input
Thoroughly filter/escape any untrusted content
If the allowed character set for certain input fields is limited, check that the input is valid before using it
If in doubt about a certain kind of data (e.g. server variable), treat it as untrusted
If you are sure, but there is no real need to treat it as trusted, treat it as untrusted
The request URL (e.g. in environment variables) is untrusted
Data coming from HTTP headers is untrusted
Referer
X-Forwarded-For
Cookies
Server name (!)
All POST and GET data is untrusted
includes non-user-modifiable input fields like select
All content validation is to be done server side
Cross-site request forgery (CSRF)
Include a hidden form field with a random token bound to the user’s session (and preferably the action to be performed), and check this token in the response
Make sure the token is non-predictable and cannot be obtained by the attacker
do not include it in files the attacker could load into his site using <script> tags
Referer checks are not secure, but can be used as an additional measure
Clickjacking
Prevent (i)framing of your application in current browsers by including the HTTP response header “X-Frame-Options: deny”
Prevent (i)framing in outdated browsers by including a JavaScript frame breaker which checks for (i)framing and refuses to show the page if it is detected
For applications with high security requirements where you expect users to use outdated browsers with JavaScript disabled, consider requiring users of older browsers to enable JavaScript
Insecure data transfer
Use SSL/TLS (https) for any and all data transfer
Do not start communicating via http, only redirecting to https when “needed”
Mark cookies with the “secure” attribute
Use the Strict-Transport-Security header where possible
Educate users to visit the https:// URL directly
If your web application performs HTTPS requests, make sure it verifies the certificate and host name
Consider limiting trusted CAs if connecting to internal servers
Session fixation
Regenerate (change) the session ID as soon as the user logs in (destroying the old session)
Prevent the attacker from making the user use his session by accepting session IDs only from cookies, not from GET or POST parameters (PHP: php.ini setting “session.use_only_cookies”)
Session stealing
Set the “HttpOnly” attribute for session cookies
Generate random session IDs with secure randomness and sufficient length
Do not leak session IDs
Truncation attacks, trimming attacks
Avoid truncating input. Treat overlong input as an error instead.
If truncation is necessary, ensure to check the value after truncation and use only the truncated value
Make sure trimming does not occur or checks are done consistently
Introduce length checks
care about different lengths due to encoding
Make sure SQL treats truncated queries as errors by setting an appropriate SQL MODE
Password security
Do not store plain-text passwords, store only hashes
Use Argon2, scrypt, bcrypt, or some other secure hashing algorithm specifically designed for secure password "storage".[1][2]
Use per-user salts
Use strengthening (i.e. multi-iteration hashing to slow down brute force attempts)
Limit login attempts per IP (not per user account)
Enforce reasonable, but not too strict, password policies
If a password reset process is implemented, make sure it has adequate security. Questions like “mother’s maiden name” can often be guessed by attackers and are not sufficient.
Comparison issues
Know comparison types in your programming language and use the correct one
When in doubt (especially with PHP), use a strict comparison (PHP: "===")
When comparing strings for equality, make sure you actually check that the strings are equal and not that one string contains the other
PHP-specific issues
Do not use the short form “<?”, always use the full form “<?php”
When using the nginx web server, make sure to correctly follow the official installation instructions and pay attention to the "Pitfalls" page. Beware of tutorials that often contain working but insecure configuration examples.
preg_replace can act as eval() in certain cases. Avoid passing user input to it. If you must, correctly filter and escape it.
Use the Suhosin (including the patch, if possible) and configure it with strict rules
Enable suhosin.executor.disable_emodifier
Enable suhosin.executor.disable_eval if possible
Set suhosin.mail.protect to 2 if possible
When updating PHP to PHP 5.4 from an older version, ensure legacy applications do not rely on magic quotes for security.
Prefetching and Spiders
Use POST requests instead of GETs for anything that triggers an action
Special files
Know the meaning of these files
Ensure robots.txt does not disclose "secret" paths
Ensure crossdomain.xml and clientaccesspolicy.xml do not exist unless needed
If used, ensure crossdomain.xml and clientaccesspolicy.xml allow access from trusted domains only