This struck me as a problem: the ability to embed an iframe into an email is already a vulnerability. Even worse, as the iframe was not affected by the block external images setting that prevents tracking pixels and web beacons. But if an attacker could gain the ability to run JavaScript in an email, there could be a much more dangerous attack vector.

With this in mind I tried inserting a script tag instead of an iframe into an email. It failed, which is good. However, I was able to circumvent this by using a JavaScript URL in my iframe. Things were getting interesting.

Stored XSS Via Email

In a web browser, it’s possible to run JavaScript code by using a URL that starts javascript:. But in a web browser, JavaScript in an iframe on a separate domain shouldn’t have access to the data in the rest of the page. In Outlook on the Android, there is no such restriction. My iframe JavaScript had full access to cookies, tokens and even some emails. Not only that, I could send them back out to a remote attacker.

This kind of vulnerability could be exploited by an attacker sending an email with JavaScript in it. The server escapes that JavaScript and does not see it because it’s within an iframe. When delivered, the mail client automatically undoes the escaping and the JavaScript runs on the client device. Bingo – a stored XSS. This code can do whatever the attacker desires, up to and including stealing information and/or sending data back out. An attacker can send you an email and just by you reading it, they could steal the contents of your inbox. Weaponized, this can turn into a very nasty piece of malware.

Attempt at Disclosure

This was a big deal, so I needed to let Microsoft know. Before disclosing, I created a short Proof of Concept (POC) that demonstrated my vulnerability. It ran an arbitrary external script that stole and exfiltrated private data (although admittedly, with very limited access to email data). I sent this to the Microsoft Security Response Center (MSRC) on December 10, 2018.

At this point I did not know exactly which part of the code caused the bug. How could I? I don’t have access to Outlook source code. And really, I had no experience debugging mobile apps. Besides, I assumed that it would be pretty easy for the app developers to take my POC and find the problem.

Unfortunately, the vulnerability didn’t reproduce for the engineering team. I was stymied and worried. This was real and I needed them to address it. I sent them a video of the bug occurring. I later learned that another researcher reported it too, but neither POC reproduced the bug for the security engineers.

I tested different Outlook settings to see if that was the cause of the discrepancy, but had no success, and so the case went cold.

No Repro, No Bug

Every security engineer and developer will tell you that not being able to reproduce a reported bug is a real headache; and their time is a precious and limited resource to the business. An organization can only expend so much effort to try to reproduce a bug. If they can’t reproduce it, the reasoning goes, then surely an attacker can’t either. So the engineers and devs sit on it, and often put the responsibility back on the researcher to find a way to create a POC that security engineers can easily confirm, triage, and hopefully patch.

Breakthrough

I couldn’t let it go. A few months later, I was still thinking about this vulnerability, and the difficulty in creating a POC for the Microsoft Security Engineers. I remembered this bug and thought about how to extract the rendered HTML from the app. I realized that the key was the bug itself! The bug let me steal data from the app—I could use it to read and extract the HTML.

I constructed a new payload using this information, which can be seen in the screenshot below in Figure 3: