Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I always use strip_tags to prevent XSS attacks, but today I saw a post which was telling it's horribly unsafe. As the manual says, it doesn't check for malformed HTML!

Is it true?

What can I do to prevent XSS?

share|improve this question

2 Answers 2

up vote 16 down vote accepted

To prevent XSS you need to:

  1. Validate all user input that you'll process (for example - if id GET parameter should be a number, ensure it is with e.g. PHP's is_number() function or using Filter extension). This should not only include GET / POST parameters, but also cookie names, cookie values, HTTP headers, uploaded file names etc. Attackers can manipulate requests in many ways. If you need to accept & display HTML content from the user (e.g. in CMS application) use well-tested HTMLPurifier library to filter out Javascript & other XSS payload and leave only clean, sanitized HTML.

  2. When displaying the value use contextual output encoding (sometimes called 'escaping'). There are different rules on how to encode user-supplied value whether it occurs in:

    • HTML context e.g. <div>{$_GET['id']}</div>
    • HTML attribute context e.g. <div class='{$_GET['class']}'>
    • Javascript context e.g. <script> var a = '{$_GET['id']}'</script>
    • CSS context e.g. <div style='background:url({$_GET['image']})'>

It's best to refer to recommended rules described in OWASP XSS Prevention Cheat Sheet. Read it thoroughly and adher to it - XSS is #2 risk to web applications today so you really need to protect from it. See also OWASP tutorial video on XSS.

share|improve this answer
3  
You deserve kudos for distinguishing between validation and escaping. If only more than 10 people would do this... –  chris Dec 24 '11 at 10:18
1  
@Krzysztof, Did miss a close brace in <div>{$_GET['id']}</div> and <div style="background:url({$_GET['image']})">, or is that valid PHP? –  George Bailey Dec 26 '11 at 18:48
    
oops, corrected now, thanks for spotting this. –  Krzysztof Kotowicz Dec 26 '11 at 21:15
    
is_int will never work for POST/GET values, since they're always strings. ctype_digit or, yes, the Filter extension is what you're looking for. :) –  deceze Dec 28 '11 at 23:25
    
true, will fix now. –  Krzysztof Kotowicz Dec 29 '11 at 1:05

You should use contextual encoding. See the owasp xss prevention cheat sheet. You have to encode differently depending on where the output is. As an example the following input will be missed by strip_tags, yet cause xss if the output is in the value attribute of a html text input: " autofocus onfocus="alert(1)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.