How I Turned a Low-Risk XSS into a Tenant-Wide Lockout

How I Turned a Low-Risk XSS into a Tenant-Wide Lockout

Hey everyone! I’m Husnain, a Jr. Penetration Tester, and I love sharing my experiences from real-world pentests. Today, I want to talk about something cool that happened in one of my recent tests. I found a simple XSS bug, which is usually low-risk, but I escalated into High Severity. Let me walk you through how I did it!

The Starting Point: Finding the XSS Bug

In one of my recent pentests, I was testing a web app that’s like a tenant system, think shared spaces where different groups use the same setup but stay separate. I spotted a stored XSS vulnerability in a settings area. Stored XSS means the bad code gets saved in the database and runs for anyone who sees it.

The spot was in settings where you can add or rename columns. When I put in a simple payload like:

<script>alert(1)</script>

It popped up an alert box for me and others in the same tenant when someone logs in. Cool, but low-impact, right? Just a pop-up. The app had good security, like HTTP-only cookies, so I couldn’t steal sessions or call external sites easily.

But I didn’t stop there. I thought, “How can I chain this to show real damage?

Escalating to High Impact: The Forced Logout Trick

To make it serious, I needed the XSS to do something harmful inside the app. Since the payload runs when users load the dashboard, and it’s authenticated, it can access internal endpoints.

I crafted a payload that hits the logout endpoint automatically. Here’s what I used:

<img src="/auth/logout" onerror="location.reload();" style="display:none;">

Let me break it down:

  • The <img> tag tries to load an image from /auth/logout, but that’s not an image; it’s the logout URL. So, it logs out the user who sees it.
  • The onerror part runs if the image fails (which it will), and it reloads the page with location.reload();.
  • style=”display:none;” hides it so no one notices.

When this gets injected into the column name and saved, every time a user, normal or admin, opens the dashboard, it logs them out and reloads. They try to log in again? Boom, dashboard loads, logout happens, loop forever!

This affected the whole tenant. Even super admins couldn’t fix it without wiping the database. My senior tester had to reset everything just to log in. That’s how a low-risk XSS became a high-severity issue: mass logouts leading to total denial of access.

Lessons Learned

This shows why even “low-risk” bugs matter. Chain them with creativity, and they can cause big problems like this lockout. For devs: Always encode outputs, especially in shared areas. For testers: Think beyond alerts, look for internal abuse.

If you’re starting in pentesting, try this in CTFs. Practice XSS and see how to escalate. Got questions? Drop a comment!

Stay safe and keep hacking ethically!

Leave a Reply

Your email address will not be published. Required fields are marked *