XSS in Zagat, exploiting a XOR-based obfuscation algorithm

February 16, 2014

This is a very interesting vulnerability I internally reported, and is now fixed. I find it interesting because it is not the usual XSS, but it exploits a XOR-based obfuscation algorithm of a user-controlled input.

Steps to reproduce

Go to http://www.zagat.com/newsletters/process?email=A2d5QgFwUzZRclE%2BVXcAcQ8wV2JQbF02BnACIQ0gBTUOPgxuAiUDZAJiAGkAdlZ%2BATNQOVRpDmAEbF1sfAVwQgMoASUDZQwqDDoPflB2NQEDRlA2AS1TNlFvUTo=

alert(document.cookie) was executed directly.

Details of the vulnerability

Zagat uses a XOR and position-based obfuscation for passing the email address that is then output to a HTML page on the same domain as a confirmation.

I reverse-engineered the obfuscation function, by exploiting the fact that passing 128 NULL ( \0 ) characters base64 encoded (http://www.zagat.com/newsletters/process?email=AAAA ... A=) to the above URL outputs the repeating 20-chars long encryption key ;) - old trick - XOR with NULL reveals the key.

Knowing that, I found out that there was another step, likely dependent on the difference between chars in the string. Using a clever bruteforce script, also thanks to collisions (several chars in email collided to the same output char), it is possible to make it output arbitrary HTML (and thus JS) to the page, without any user interaction.

Screenshots

Finding the XOR repeating key providing NULL bytes to reveal it Using Burp Suite to reverse the obfuscation algorithm Testing the Javascript payload with Burp Boom!

This vulnerability was fixed in a matter of days, and now a proper protection is in place.

Abusing JSONP with Rosetta Flash

Mailbox.app Javascript execution