# Blast from the past: Cross Site Scripting on the AWS Console

Persistent DOM XSS in AWS Console via EC2 tag values rendered unencoded, letting a low-privileged user run JS in an admin's session.

- Payout: Research
- Severity: high
- Program: Amazon
- Write-up by: Johann Rehberger
- Disclosed: 2020-07-01
- Write-up quality: 6/10
- Original: https://embracethered.com/blog/posts/2020/aws-xss-cross-site-scripting-vulnerability/
- Library page: https://bugbountylibrary.com/r/blog%3Aembracethered-com-blog-posts-2020-aws-xss-cross-site-scripting-vulnerability
- Tags: area:cloud domain:cloud domain:web impact:integrity impact:privesc kind:research platform:research sev:high tech:aws technique:source-review vuln:privilege-escalation vuln:xss

**Target:** AWS Console EC2 instance tag rendering (AJAX JSON response into DOM)
**Root cause:** Console front-end injected tag key/value strings from the JSON API response directly into the DOM without HTML encoding, so a crafted tag value broke out of an attribute and injected elements.
**Steps:**
1. Create an EC2 instance and add a tag with value `Apache"/><h1>Web Server</h1>`
2. Reload the console page / open tag dropdowns where tags render
3. Observe the injected `<h1>` rendering, confirming HTML element injection
4. Inspect AJAX response: `{"tags":[{"key":"Name","resourceId":"i-0fc94007","value":"\"/><h1>Web Server</h1>"}]}`
5. Replace payload with `<img src=: onerror=alert(document.domain)>` to get JS execution in the console origin
**How found:** Habit of probing new objects with parsing test strings like `wuzzi"/><h1>hello</h1>` to check for HTML element injection; applied it to EC2 tag values and saw the h1 render, then confirmed via Fiddler that the JSON API echoed the raw value into the DOM.
**Exploitation:** A low-privileged AWS account user sets a malicious EC2 tag value; when an admin views the instance or tag metadata in the console, the stored payload executes in the AWS Console origin, enabling privilege escalation to account admin.
**Escalation:** Stored payload persists and fires for any admin who views the resource, converting low-priv user into code execution in admin's console session.
**Insight:** Tag/metadata fields echoed back through JSON APIs into console UIs are prime stored-DOM-XSS spots; test every user-controlled label with an attribute-breakout payload and watch for it rendering on other users' views.
