Stored XSS Via Email
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.
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:
The payload I constructed looked like this:
This payload correctly escaped on the server side with HTML entities. But the escaping was undone on the client, and the payload was converted to:
The bug occurred in the client-side code, which made the phone number clickable. This bug was not reproducible at first because my Android localization settings were set to UK, which caused the number to be judged as a valid phone number. Other localizations didn’t detect a phone number, so there was no bug.
I rewrote the POC, using a full US phone number format, xxx-xxx-xxxx, and tested that this reproduced across localities. I then sent this back to Microsoft. On March 26, 2019, they confirmed the repro and committed to a fix within 90 days of that date.
Timeline of Disclosure
- 10 December 2018 – First disclosed to MSRC
- 16 January 2019 – Video screen capture of vulnerability sent. Microsoft cannot repro. Case went cold.
- 26 March 2019 – Universal POC sent to MSRC
- 26 March 2019 – Microsoft confirms repro
- 20 June 2019 – Fix released
CVE-2019-1105 has a fix is available as of June 20, 2019, available at https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2019-1105. It is always important for both individual and enterprise users to keep their applications up to date in order to lower the risk of exploitation of known vulnerabilities. It’s also important to seek and report security vulnerabilities, so we can all have safer products—and, obviously, keep our systems patched to avoid getting burned by these new holes when they are released.