Skip to main content
A row of tall sealed concrete storage silos standing under a flat overcast sky.
Photo by Miguel Bernardo on Unsplash
  1. Research/

Google Cloud Console: dormant stored XSS

Patrik Grobshäuser
Author
Patrik Grobshäuser
Security researcher at Assetnote / Searchlight Cyber. Before that, seven years triaging other people’s reports at HackerOne and Shopify. Hunting bugs since 2012, published as Patrik Fehrenbach until 2025.
Table of Contents

Today I want to share a short write-up about a stored cross-site scripting (XSS) issue I found on the Google Cloud Console. I consider it a lucky find. Some of you may remember the tweet I sent to Frans Rosén after he discovered a vulnerability on Google Payments:

Screenshot of a tweet sent to Frans Rosén after his Google Payments vulnerability disclosure

As it turned out, among the unsuccessful XSS payloads I saved on my Google account, there was one that actually fired. But unexpectedly. When I was originally testing my payloads, I never managed to trigger the execution until recently and inadvertently. But let’s start from the beginning.

Finding the bug
#

As you may know, Google is offering a 60 day free trial with a budget of $300 and all that is required is entering (correct) payment information to prove you are not a robot. So, I did that a few weeks ago and started entering XSS payloads in every field I could find … and nothing fired, I failed. A situation I assume we’ve all been in, right? Well, after two months or so, I received an invoice from Google and a notification that my free trial was ending. Wanting to avoid the charges, I quickly logged into my account and deleted my project, which was titled “> <img src = x onerror = javascript: alert (1); … and boom, my payload got Executed!

JavaScript alert(1) dialog firing in the Google Cloud Console while deleting a project whose name contained an img onerror payload

The vulnerability
#

As it turned out, Google was not filtering the error message once a project was canceled. Astute readers may question why this was not classified as a low level self XSS. This issue was escalated because the Google Cloud Platform can be used by multiple users; if a user creates a project with a malicious XSS payload, that payload could be used against the project administrator to execute malicious JavaScript (if they delete the project, which seems likely).

Proof of concept
#

For those unfamiliar, and the knowledge hungry, here’s how the payload gets reflected in the content of the site: the first quote and angle bracket, “>” close the preceding HTML tag which allowed my injected tag to be rendered in the page source. For this POC, I simply used the img src = x payload. Since x is not a valid URL, this is designed to fail immediately with a 404 HTTP response, which will then invoke the onerror event to execute a JavaScript function. However, thanks to @Jobert from HackerOne for noting that it’s possible this could have returned a 2xx or 3xx redirecting to a 2xx in which case my payload would not have fired. In my testing, I just added the function alert to create a popup but malicious users could have used a cookie stealer or the Browser Exploitation Framework Project (BEEF) to escalate this issue (I did not have to demonstrate that to Google, though).

Page source view showing the injected img src=x onerror payload breaking out of the surrounding HTML tag

Here’s the video POC I sent in for the Google VRP:

That’s it 🙂

Disclosure
#

Google Vulnerability Reward Program notification confirming the $5,000 reward for the stored XSS report
Animated reaction GIF celebrating the payout

Thanks to Peter @yaworsk for editing :-)! Follow him and support him by buying his book !

Related