vuln-writeup
Amazon XSS
2017-06-20 reflected xssCWE-79
amazon.co.uk · responsibly disclosed · patched in 2 weeks

Reflected cross-site scripting (XSS) across the Amazon storefront, present on all locales. Hats off to their security team for their response and for permission to publish.

Most of my recent findings were still unpatched at the time of writing — I tend not to publish until vendors confirm a fix, to avoid putting customers at risk.

Overview

Initially found on amazon.co.uk, then confirmed across amazon.com, amazon.de, amazon.ie, and all other locales via the same vulnerable component.

Discovery

While using Amazon Prime's pickup location feature, I noticed the ZIP code input was reflecting user input back onto the search results page without sanitisation. A ZIP should be 5-6 alphanumeric characters — the field accepted -/+ 5 and arbitrary special characters without complaint.

HTML injection

Injecting a simple <h1> confirmed the output was unsanitised. Spaces were filtered, as were standard quotes and colons — but protocol-relative URLs worked fine, so <img+src=//yoxall.me.uk> successfully loaded an external resource.

HTML injection in Amazon pickup location search results

Filters & bypass

Escalating to full script execution meant working around what appeared to be a web application firewall (WAF). The filter matrix:

BlockedAllowed
Element/attribute divider/ space %2f+
Quotes"'
Functionsalert confirm prompteval atob

The bypass: apostrophes as attribute delimiters, onerror as the event handler, and eval(atob()) with a base64-encoded payload to sidestep the function blocklist. Final payload:

<img+
src='x'onerror=eval(atob('cHJvbXB0KGRvY3VtZW50LmRvbWFpbiwieW94YWxsIik='))>
// decodes to: prompt(document.domain, "yoxall")

document.cookie was accessible and held session-* cookies — HttpOnly was not enforced. Combined with the external resource inclusion, an attacker could have hijacked customer accounts or accessed sensitive account data.

XSS prompt dialog firing on amazon.co.uk
takeaway

Never trust user input. Validate before processing — and don't treat a WAF as a substitute for proper input sanitisation.