10

I currently have a simple <div contenteditable="true"> working, but, here's my problem.

Currently, the user can create a persistent XSS by inserting a <script> into the div, which I definitely do not want.

However, my current ideas to fix this are:

  • Allow only a and img tags
  • Use a textarea (not a good idea, because then have users copy and paste images)

What do you guys suggest?

Dhaivat Pandya
  • 6,499
  • 4
  • 29
  • 43
  • There's a method that does exactly what you want: it's `window.toStaticHTML()`. Unfortunately, it's not widely supported. However, you could use it at least as a part of a solution. – duri Nov 10 '11 at 22:15
  • I need it to be widely supported, but, I guess I could use that, but, I also hate browser sniffing. – Dhaivat Pandya Nov 10 '11 at 22:16
  • What are you using server side? – Dave Nov 10 '11 at 22:34
  • 1
    @DhaivatPandya Inserting a ` – Šime Vidas Nov 11 '11 at 03:36

2 Answers2

11

You have to keep in mind that to prevent xss, you've GOT TO DO IT ON THE SERVER SIDE. If your rich text editor (ex YUI or tinyMCE) has some javascript to prevent a script tag from being inputted, that doesn't stop me from inspecting your http post requests, looking at the variable names you're using, and then using firefox poster to send whatever string I like to your server to bypass all client side validation. If you aren't validating user input SERVER SIDE then you're doing almost nothing productive to protect from XSS.

Any client side xss protection would have to do with how you render user input; not how you receive it. So, for example, if you encoded all input so it does not render as html. This goes away from what you want to accomplish though (just anchor and img tags). Just keep in mind the more you allow to be rendered the more possible vulnerabilities you expose.

That being said the bulk of your protection should come from the server side and there are a lot of XSS filters out there depending on what you're writing with (ex, asp.net or tomcat/derby/jboss) that you can look into.

I think you're on the right path by allowing ONLY a and img tags. The one thing you have to keep in mind is that you can put javascript commands into the src attributes of a tags, so take care to validate the href attributes. But the basic idea of "allow nothing and then change the filters to only allow certain things" (AKA whitelist filtering) is better than "allow everything and then filter out what I don't want" (AKA blacklist filtering).

In the comments below, Brian Nickel also said this which illustrates the point:

Everything but the elements and attributes you want to keep. I know you mentioned it in your answer but that bears repeating since it is so scary. <img onerror="stealMoney()">

The other thing you're going to want to do is define a XSSFilterRequest object (or something along those lines) and in a filter, override your requests so that any call to whatever your "getUrlParameter" and "getRequestParameter" objects run the request values through your xss filter. This provides a clean way to filter everything without rewriting existing code.

EDIT: A python example of xss filtering:

Python HTML sanitizer / scrubber / filter

Python library for XSS filtering?

Community
  • 1
  • 1
Dave
  • 6,141
  • 2
  • 38
  • 65
  • The first answer mentioned is incorrect, as stated in the other answers/comments. And, same with the other answer. – Dhaivat Pandya Nov 10 '11 at 23:10
  • Are you talking about the answers I posted in the links? – Dave Nov 10 '11 at 23:13
  • Yes, I am. I hate this character limit. – Dhaivat Pandya Nov 10 '11 at 23:16
  • Alright, just making sure. But ya, I don't think there is a "best" solution out there, which is why I'm recommending the "strip everything, and then write code to allow what you want and ONLY what you want" approach. – Dave Nov 10 '11 at 23:18
  • You have to keep in mind some of the biggest players out there have been hit with xss attacks. Here is an article about youtube getting one: http://www.technewsworld.com/story/70357.html This was only last year and they've probably got a lot of people capable of preventing xss working for them. – Dave Nov 10 '11 at 23:21
  • I see. I don't quite understand how I'm supposed to strip everything, firstly, and secondly, how to keep the things I want. – Dhaivat Pandya Nov 11 '11 at 00:09
  • I don't think that my wording there was clear but the general idea of what I was talking about is "whitelist" filtering as opposed to "blacklist". In other words, I don't mean strip everything and then keep what you want. I mean strip everything but . – Dave Nov 11 '11 at 01:41
  • 2
    Everything but the elements **and** attributes you want to keep. I know you mentioned it in your answer but that bears repeating since it is so scary. `` fall under "elements you want to keep" after all. You almost want an SGML parser that parses the document, filters it, and then rebuilds it with only the desired subset. This Q confirmed why I love Markdown. – Brian Nickel Nov 11 '11 at 03:18
0

What about using google caja (a source-to-source translator for securing Javascript-based web content)?

Unless you have xss validation on server side you could apply html_sanitize both to data sent from the user and data received from the server that is to be displayed. In worst case scenario you'll get XSSed content in database that will never be displayed to the user.

Li0liQ
  • 11,158
  • 35
  • 52
  • XSSed database content will be displayed over and over to the user since I'll be reading from my database. – Dhaivat Pandya Nov 11 '11 at 22:09
  • If you apply `html_sanitize` both to user input and to data from database, as I've mentioned, it won't. Though, keeping xss in database isn't a good idea if you have any mean to prevent it on server side. – Li0liQ Nov 12 '11 at 08:49