How do I prevent XSS (cross-site scripting) using just HTML and PHP?
I've seen numerous other posts on this topic but I have not found an article that clear and concisely states how to actually prevent XSS.
How do I prevent XSS (cross-site scripting) using just HTML and PHP?
I've seen numerous other posts on this topic but I have not found an article that clear and concisely states how to actually prevent XSS.
In order of preference:
{{ var|e('html_attr') }}
htmlentities($var, ENT_QUOTES | ENT_HTML5, $charset)
and make sure the rest of your document uses the same character set as$charset
. In most cases,'UTF-8'
is the desired character set.Also, make sure you escape on output, not on input.
Use
htmlspecialchars
onPHP
. On HTML try to avoid using:element.innerHTML = “…”; element.outerHTML = “…”; document.write(…); document.writeln(…);
where
var
is controlled by the user.Also obviously try avoiding
eval(var)
, if you have to use any of them then try JS escaping them, HTML escape them and you might have to do some more but for the basics this should be enough.One of my favorite OWASP references is the Cross-Site Scripting explanation because while there are a large number of XSS attack vectors, the following of a few rules can defend against the majority of them greatly!
This is PHP Security Cheat Sheet
Cross-posting this as a consolidated reference from the SO Documentation beta which is going offline.
Problem
Cross-site scripting is the unintended execution of remote code by a web client. Any web application might expose itself to XSS if it takes input from a user and outputs it directly on a web page. If input includes HTML or JavaScript, remote code can be executed when this content is rendered by the web client.
For example, if a 3rd party side contains a JavaScript file:
And a PHP application directly outputs a string passed into it:
If an unchecked GET parameter contains
<script src="http://example.com/runme.js"></script>
then the output of the PHP script will be:The 3rd party JavaScript will run and the user will see "I'm running" on the web page.
Solution
As a general rule, never trust input coming from a client. Every GET, POST, and cookie value could be anything at all, and should therefore be validated. When outputting any of these values, escape them so they will not be evaluated in an unexpected way.
Keep in mind that even in the simplest applications data can be moved around and it will be hard to keep track of all sources. Therefore it is a best practice to always escape output.
PHP provides a few ways to escape output depending on the context.
Filter Functions
PHPs Filter Functions allow the input data to the php script to be sanitized or validated in many ways. They are useful when saving or outputting client input.
HTML Encoding
htmlspecialchars
will convert any "HTML special characters" into their HTML encodings, meaning they will then not be processed as standard HTML. To fix our previous example using this method:Would output:
Everything inside the
<div>
tag will not be interpreted as a JavaScript tag by the browser, but instead as a simple text node. The user will safely see:URL Encoding
When outputting a dynamically generated URL, PHP provides the
urlencode
function to safely output valid URLs. So, for example, if a user is able to input data that becomes part of another GET parameter:Any malicious input will be converted to an encoded URL parameter.
Using specialised external libraries or OWASP AntiSamy lists
Sometimes you will want to send HTML or other kind of code inputs. You will need to maintain a list of authorised words (white list) and un-authorized (blacklist).
You can download standard lists available at the OWASP AntiSamy website. Each list is fit for a specific kind of interaction (ebay api, tinyMCE, etc...). And it is open source.
There are libraries existing to filter HTML and prevent XSS attacks for the general case and performing at least as well as AntiSamy lists with very easy use. For example you have HTML Purifier
One of the most important steps is to sanitize any user input before it is processed and/or rendered back to the browser. PHP has some "filter" functions that can be used.
The form that XSS attacks usually have is to insert a link to some off-site javascript that contains malicious intent for the user. Read more about it here.
You'll also want to test your site - I can recommend the Firefox add-on XSS Me.