Yasin Soliman

Yasin Soliman

I'm Yasin, a security analyst from the UK, interested in web application testing and red team operations.

Yasin Soliman



App Maker and Colaboratory: a stored Google XSS double-bill

Yasin SolimanYasin Soliman

It's been a few months since my last personal blogpost, which chronicled two reflected cross-site scripting vulnerabilities in Google Play. This time, we'll explore two stored cross-site scripting bugs since remediated by Google: the first in App Maker for G Suite organisations, and the second in the brand new Colaboratory platform.     

1. XSS by request manipulation: App Maker

App Maker is a low-code application development tool that lets [organisations] build and deploy custom apps easily and securely, on the same platform that powers G Suite.

To (briefly) set the scene, early August saw me travelling light with just a Chromebook. I'd recently applied for access to the App Maker Early Access Program (EAP) using my G Suite Business account, and shortly after touching down in the UK, had received an acceptance notification.

Google App Maker, from the developer documentation

Having eschewed my full research environment, I opted to approach App Maker with the mindset of an end user. This meant using Google's documentation to augment my review of potentially interesting features for review at a later date.

In a business-focused product like App Maker, extensibility features pique my interest — these often involve APIs and external resources. Within the "Advanced Services" section of App Settings was I able to store a persistent payload, after manually adjusting requests intercepted with Burp Suite.

The convincing nature of this vulnerability, coupled with persistent client-side JavaScript execution, meant that whitelisted App Maker users could deploy payloads completely accessible through the front-end interface. So, here's how it works.

Reproduction process

To begin, sign in to App Maker with a whitelisted G Suite account, and create a new App with the "Blank" template. Navigate to the App Settings tab by selecting the top-rightmost "cog" icon.

After arriving on App Settings, scroll downwards to Advanced Services, and select the "Add Service" option.

App Settings view within App Maker

Enable traffic interception using your web proxy of choice, then select one API checkbox (in this case, "Drive API"), followed by the "Add" button.

Adding the Drive API to an App Maker project

Two encoded POST requests are made to /editApplication/executeCommand in quick succession. Within the protobuf-like format of both, filter for the relevant developers.google.com documentation URL and replace this with a JavaScript URL payload:

Before: https://developers.google.com/apps-script/advanced/drive
After: javascript://www.google.com/test%0aalert(document.domain)

After doing so, finish POSTing the requests and refresh the client browser, returning to the Advanced Services section.

Advanced Services, now with the added API resource

Finally, any user with access to the application can mouseover the "Drive API" entry and select the "External Link" arrow to trigger the persistent JavaScript payload.

The final App Maker stored XSS proof of concept

2. XSS by Markdown parser injection: Colaboratory

Colaboratory is a research project created to help disseminate machine learning education and research. It's a Jupyter notebook environment that requires no setup to use.

Moments before stepping into an elevator in central London, I caught the following Tweet from Iwona Bialynicka-Birul of Google, announcing the external release of the Colaboratory tool.

Needless to say, within a few seconds of reading I signed in to Colaboratory — inspired by Frans Rosen's mobile screen approach — and started getting to know the platform.

A quick bit of background: notebooks on Colaboratory use the Jupyter framework, and comprise two "cell" types: static "Text" cells and dynamic "Code" cells. The actual Jupyter notebook processing (for instance, when running TensorFlow machine learning code) takes place within a Python-based runtime in Code cells. I soon realised that this required specific whitelist approval, but undeterred, continued experimenting with accessible features.1

Each applicable payload from @EdOverflow's Bug Bounty Cheatsheet and the DOMPurify test suite was subsequently neutralised by the parser, but led to the detection of some unusual behaviour whilst testing hyperlink functionality.

It appeared that unsafe protocol schemes (such as javascript:) could be rendered without sanitisation if specified twice, with the first colon in HTML entity form. This didn't immediately lead to XSS, but a suitable vector was found after some refinement.

In the end, the initial report was quite brief, but here's the interesting part: by this point I was travelling through Westminster in a taxicab, complete with Chromebook and mobile 4G link.

Reproduction process

  1. First, sign in to Colaboratory with your Google account and create a new blank Notebook.
  2. Add a new Text cell (Insert → Text Cell) with the below proof of concept payload.
  3. After a few seconds, the cell contents will be processed by the parser
  4. Select the hyperlink to execute our stored JavaScript.
[Click me](javascript:javascript:window.onerror=alert;throw 'XSS on domain: ' + document.domain)

Here's how the Colaboratory interface appeared:

The Colaboratory interface, pre-execution

Successful injection was confirmed by a JavaScript alert dialog upon selecting the link. Instead of a sandboxed googleusercontent.com domain, this JavaScript fired in the colab.research.google.com context.

Colaboratory, complete with stored XSS


I would like to once again commend the Google Security Team for their excellent handling of submitted reports to the Vulnerability Reward Program.

Research timeline

The following timestamps are provided in Greenwich Mean Time (GMT).

1. XSS by request manipulation: App Maker

  • 2017-08-04 18:45 – bug reported
  • 2017-08-04 19:04 – triaged
  • 2017-08-04 22:50 – "nice catch!" (validated)

2. XSS by Markdown parser injection: Colaboratory

  • 2017-10-24 16:25 – bug reported
  • 2017-10-24 19:46 – triaged
  • 2017-10-25 11:48 – "nice catch!" (validated)

Disclosure approval took place simultaneously at 2017-11-01 13:37.

1 After being approved for runtime usage, I soon discovered that all operations take place in a specially sandboxed Google endpoint, and would not be eligible in the event of XSS discovery.

Yasin Soliman

Yasin Soliman