20 Point List For Preventing Cross-Site Scripting In PHP
Summarising knowledge has as much value as writing a 200 page treatise on a topic, so here is a list of 20 brief points you should bear in mind when battling Cross-Site Scripting (XSS) in PHP. Minus my usual book length brain fart ;). Chances are good that ignoring or acting contrary to any one of these will lead to a potential XSS vulnerability. It’s not necessarily a complete list – if you think something needs to be added, let everyone know in the comments.
- Never pass data from untrusted origins into output without either escaping or sanitising it.
- Never forget to validate data arriving from an untrusted origin using relevant rules for the context it’s used in.
- Remember that anything not explicitly defined in source code has an untrusted origin.
- Remember that htmlentities() is incompatible with XML, including HTML5’s XML serialisation – use htmlspecialchars().
- Always include ENT_QUOTES, ENT_SUBSTITUTE and a valid character encoding when calling htmlspecialchars().
- Use rawurlencode() to escape strings being inserted into URLs and then HTML escape the entire URL.
- Validate all complete URLs if constructed from untrusted data.
- Never include resources loaded over unsecured HTTP on a page loaded over HTTPS.
- Sanitise raw HTML from untrusted origins using HTMLPurifier before injecting it into ouput.
- Sanitise the output of Markdown, BBCode and other HTML replacements using HTMLPurifier before injecting it into output.
- Remember that HTMLPurifier is the only HTML sanitiser worth using.
- Always transmit, with content, a valid Content-Type header referencing a valid character encoding.
- Ensure that cookies for use solely by the server are marked HttpOnly.
- Ensure that cookies which must only be transmitted over HTTPS are marked Secure.
- Always review dependencies and other third party code for potential XSS vulnerabilities and vectors.
Cross-Site Scripting remains, by far, the most common vulnerability in web applications. Things that will sink your application, framework or library become very obvious from the list. There are more than enough naughty applications, frameworks and libraries around that you should have little trouble identifying offenders with grep and some mental acrobatics. Rumour has it that you can now locally search any project on Github without even cloning a repository.
Yes, some entries are reminders. It’s surprising how many people try to avoid HTMLPurifier in favour of the month’s Regular Expression Powered Miracle option which is riddled with holes or have formulated the belief that, contrary to its official syntax rules, Markdown magically prevents Cross-Site Scripting.