Writing applications for mobile platforms in HTML has gained much popularity lately, both due to being able to quickly develop a working application but also because you can run one application on many platforms, or at least reuse much of the code you have written.
I decided to take a quick look at Zoho:s android-application. Zoho is a mail-service and has around 13 million users worldwide. They have a reputation of taking security seriously and was one of the providers that NSA said they had “major problems” with decrypting messages on.
Finding the HTML and JavaScript
The first thing I did was simply to download the application from Google Play, export the APK to a computer and open it in an archive manager.
I decided to take a look in the assets folder and it quickly became clear that a big part of the application is written in HTML, which is good as I read and understand JavaScript much faster and better than Java.
After a bit of looking around I figured out that mailDetail.html is the page responsible for showing the content of a mail, and a vulnerability there could be very interesting.
When reading the code and understanding the structure of it I came to the conclusion that the application itself calls setContent:
function setContent(contentToSet,margin) { document.body.style.marginTop = margin + "px"; document.body.style.marginBottom = "10px"; setBaseURL(); document.getElementById('mailcontentid').innerHTML = ""; handleContentForMailThread($('mailcontentid'), contentToSet); androidResponse(); } function handleContentForMailThread(contentEl,value) { var ind = value.indexOf("<blockquote");// NO I18N if(ind < 0) { addContentToElement(contentEl,value); return; } else { // removed 54 lines here for readability } } function addContentToElement(contentEl,value) { contentEl.innerHTML = value; addListener(); }
If you follow contentToSet (which seems to be the email content) you see that there is no kind of escaping done in this JavaScript, so if any escaping/security check is done it must be before this on the server side or in the Java code.
Figure out if and how content is secured
An easy way to tell if any escaping is done is to add a line with the code alert(contentToSet) in the first line of setContent and save the changed and signed APK.
I installed my modified APK and tried it out by sending an email to myself with three different payloads:
test<jukk http://test<jukk http://test%3Cjukk
The result I got was this:
It handled the two first ones just fine but the third payload (the one I sent URL-encoded) showed a less-than-character(<) in plain text.
They seemed to have a blacklist filter so I wasn’t able to easily exploit it. Given enough time these blacklist filters are almost always bypassed, but I got tired of manual fuzzing so I tried another approach.
Reversing the application
I’ve never coded for Android so I decided to catch up some reading about it and found out about webView (which is used to handle HTML-parts of an application). After checking out ways to send data from the Java-code to the HTML-part of the application I stumbled upon webView.loadUrl which seemed to be commonly used to run JavaScript, for example:
webView.loadUrl("javascript:initialize(" + myNumber + ");");
It would make sense that Zoho used the same approach and that would explain the weird behavior of the URL-encoded payload.
After reversing the .apk to a .jar using dex2jar and then JD-GUI to read the content of the .jar, I searched for setContent (the JavaScript function I had previously looked at) and voilá:
this.webView.loadUrl("javascript:setContent(" + JSONObject.quote(this.content) + "," + i + ")");
As you can see, they used the same method (webView.loadUrl) for sending data to the HTML-part of the application as I suspected.
Putting it all together
They use webView.loadUrl to call setContent, what did that tell me? As the JavaScript snippet was executed by opening it as an URI, anything pct-encoded was executed as normal code.
This example might make it easier to understand:
// this line of code: location.href = 'javascript:setContent("%22-alert%281%29-%22")'; // is the same as this: location.href = 'javascript:setContent(""-alert(1)-"")';
The issue became very clear, by just including a payload, as the one shown below, anywhere in the mail I was able to execute JavaScript in the targets mail-client:
%22-alert%281%29-%22
Reporting to Zoho
A few days after I sent a report to Zoho they uploaded a new patched version on Google Play and a few days after that I got a mail saying that the issue was already reported by some other fellow. Duplicate, but I thought the vulnerability was interesting and I believe there are a lot of similar vulnerabilities out there.
As shown above it’s not any harder to play around with a HTML-based Android-application than a normal webpage so get yourself together and make the world a better place!