RedCloth security thoughts

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.