Often times RedCloth is used to prevent Cross Site Scripting, because it uses a markup other than HTML to format text. "RedCloth is a module for using Textile in Ruby. Textile is a text format. A very simple text format. Another stab at making readable text that can be converted to HTML." For example *a phrase* becomes a phrase in RedCloth. However, there are a few things you have to know:
Note: the original attributes href and src were replaced by the blog software with xhref and xsrc in the following.
Using RedCloth without any options is still vulnerable to XSS:
>> RedCloth.new('<script>alert(1)</script>').to_html
=> "<script>alert(1)</script>"
Use the :filter_html option to remove or escape HTML which wasn’t created by the Textile processor:
>> RedCloth.new('<script>alert(1)</script>', [:filter_html]).to_html
=> "alert(1)"
However, this does not filter all HTML, a few tags will be left, for example <a>:
>> RedCloth.new("<a xhref='javascript:alert(1)'>hello</a>", [:filter_html]).to_html=> "<p><a _href=\"javascript:alert(1)\">hello</a></p>"
According to the source code, the image tag (<img xsrc="">) is allowed, as well, which should allow attacks like these:
<IMG xsrc=javascript:alert('XSS')>
However, my setup (version 3.0.4) gives me errors when passing image tags. I recommend to use a combination of RedCloth and the good old white_list filter, as in:
>> RedCloth.new('"ha":javascript:alert(1);').to_html
=> "<p><a xhref=\"javascript:alert(1);\">ha</a></p>">> white_list(RedCloth.new('"ha":javascript:alert(1);').to_html)
=> "<p><a>ha</a></p>"
As you can see, the Textile syntax allows you to create JavaScript links, as well. And if you think a JavaScript link looks suspicious to the users you can hide links in the data: protocol, as in Thou art so tolerant.
Another attack vector could be built with the Textile ability to include CSS. As described earlier, an attacker may deface your site and display his own elements (links, buttons, maybe login forms) on top of your original ones and lure the victim on one of his pages:
>> RedCloth.new('p{position:absolute; top:50px; left:10px; width:150px; height:150px}. Spacey blue').to_html
=> "<p style=\"position:absolute; top:50px; left:10px; width:150px; height:150px;\">Spacey blue</p>">> RedCloth.new('p{position:absolute; top:50px; left:10px; width:150px; height:150px}. No spacey blue', [:filter_styles]).to_html
=> "<p>No spacey blue</p>"
So a good combination of RedCloth and the WhiteListHelper should be a secure solution.







4 responses so far ↓
1 evan // Aug 20, 2007 at 10:34
Implemented this exact same solution the other day (except with SuperRedCloth). I tried Sam Ruby’s port of the html5lib sanitizer first but it seemed quite slow. That is perhaps a more rigorous solution though.
2 Mike // Aug 23, 2007 at 17:59
Uh, I just use textilize … ?
3 Heiko // Aug 23, 2007 at 23:35
textilize() is nearly the same as RedCloth.new(…).to_html, it calls RedCloth in the back-end. So RedCloth needs to installed.
4 graste // Aug 24, 2007 at 12:33
I want to add, that it is possible to use javascript in css. Internet Explorer allows for something like:
#someDiv {
width: expression(document.body.clientWidth > 1024? "960px": "auto" );
}
I didn’t play around with it any more than this, but it could be perfectly possible to call functions that are defined within the page (just think about all the XHR stuff and the javascript libraries all over the place in every HTML file nowadays) with some parameters. I think there are some uses, you better don’t want your page to do unexpectedly.
Another thing is, that IE5+ (but also (older?) Opera) lets you use javascript in css like this:

#someDiv {
background-image: url(javascript:document.write('foobar'));
}
The above works in IE and results in blanking out your HTML page and writing ‘foobar’ on it. Opera9 doesn’t do it. I don’t have an older version to test atm.
The following code does the obvious:
#someDiv {
background-image: url(javascript:alert('boo'));
}
Displaying an alert to the user in IE. I think, that there are some (somewhat limited) possibilities in this. Especially as you can use every javascript class/method and variables etc that are defined in the page. Pretty scary imho if you let users write HTML that is redisplayed to them and others users of your application.
Leave a Comment