Resources

From Stored XSS to Account Takeover: How Vulnerabilities Combine into Major Risks

Written by Maxwell Adams | Apr 9, 2025 7:00:00 AM

Recently, during a web application penetration test, we uncovered a situation where a combination of seemingly small vulnerabilities led to a major security breach. We found a stored Cross-Site Scripting (XSS) flaw in the comments section of a support ticketing system. This, paired with weak session security, allowed us to hijack a user’s account. 

While automated scanning tools typically miss these complex vulnerability chains, manual penetration testing like ours can reveal these hidden risks. In this article, we’ll break down how the attack worked and offer some practical advice on how to protect your application from similar threats.

The Vulnerabilities in Play

Let’s first understand the vulnerabilities involved:

1. Stored Cross-Site Scripting (XSS):

Stored XSS happens when a malicious script gets permanently stored on a web server, often through user-generated content like comments or messages. When other users view this content, the script runs in their browser, allowing attackers to execute unwanted actions or steal sensitive information remotely. 

2. Session Tokens Exposed in URLs: 

Session tokens help confirm user identity without forcing them to log in repeatedly. However, putting these tokens directly into URLs increases the risk of accidental exposure through browser history, logs, or even malicious interception. Attackers that capture these tokens can impersonate legitimate users, especially when they're obfuscated using simple methods like Base64 encoding. 

3. Session Hijacking: 

Session hijacking is when an attacker steals a user's login information (session token) to access their account without knowing their password.

Exploit Walkthrough:

Here’s how we combined these vulnerabilities to take over an account, along with the evidence we provided to the client: 

Step 1 – Stored XSS identification via Support Comments 

While testing the support ticket feature, I tried some basic XSS payloads to see if the system properly validated inputs. Initially, input validation mechanisms stripped certain special characters required for typical HTML-based XSS payloads. 

However, by using obfuscation and bypass techniques, specifically the JavaScript function String.fromCharCode(), I successfully bypassed the filters, confirming the presence of stored XSS. 

Step 2 – Base-64 Encoded Session Token in URL identification 

Next, I noticed URLs associated with viewing support tickets included an unusual base64-encoded parameter. After decoding, it became clear that this encoded string was actually the user's PHP session token —an important piece of information that could grant access to the user’s account. 

The image below displays the identified Base-64 encoded value being decoded to present the PHPSession cookie value utilised to identify the active session. 

Step 3 - Using Stored XSS to Capture the Token 

Knowing the session token was embedded in the URL, I crafted an XSS payload that sent the victim’s document location (the URL) to a server I controlled. When the victim clicked on the ticket containing the malicious code, it sent their session token straight to my server.

Step 4 – Decode Captured Token  

Once I had the session token, I simply decoded the Base64 string to retrieve the user's valid session cookie. This gave me full access to the victim's session without needing their password. 

Step 5 – Hijacking the Session 

Once I had the stolen session token, I simply replaced my session cookie with it, giving me full access to the victim's account. Since there was no re-authentication required, I could do things like disable Multi-Factor Authentication (MFA), change the registered phone number, update the email address, and reset the password. 

Ultimately, this permitted me to fully hijack the account, locking out the original user entirely, as demonstrated by the image below. 

Real-World Impact

You might be wondering what the real-world impact would be if this issue wasn’t identified and addressed within a controlled testing environment prior to public release. In short, this vulnerability could result in the complete compromise of any high-level or administrative account accessing support tickets. Attackers exploiting this could gain unrestricted access to sensitive customer data, perform unauthorised account modifications, escalate privileges, and potentially cause severe financial, regulatory, and reputational damage to the affected organisation. 

Mitigation Considerations 

To prevent attacks like this, here are a few key things to keep in mind:

1. Strict Input Validation, Sanitisation, and Output Encoding

  1. Validation ensures that inputs meet expected formats.
  2. Sanitisation removes harmful characters or code before storing them.
  3. Properly encode or escape special characters to avoid injection attacks during output rendering.
  4. Implement Content Security Policy (CSP) to mitigate XSS vulnerabilities.

2. Secure Session Handling

  1. Never expose session tokens in URLs—whether they are encoded or not.
  2. Use secure, randomly generated tokens and store them in HttpOnly cookies. 

3. Session Management Best Practices

  1. Regularly invalidate session tokens after logout or periods of inactivity.
  2. Use secure, industry-standard frameworks to manage authentication and session states. 

4. Regular Penetration Testing

  1. Automated tools are useful but can miss complex vulnerability chains. Regular, manual penetration testing can uncover these hidden risks.
  2. Educate your development team on how to recognise and prevent vulnerabilities during coding.
Final Thoughts 

Even vulnerabilities that might seem small—like stored XSS or insecure session token handling—can combine to create major security risks. Manual penetration testing is crucial for uncovering these hidden flaws and strengthening your overall security posture. It’s also important to remember that even reflected XSS can bypass protections such as anti-CSRF measures, allowing attackers to execute unintended actions through carefully crafted payloads. By staying ahead of these risks, your organisation can avoid costly breaches and protect sensitive data from falling into the wrong hands. 

At CybaVerse, our award-winning penetration testing services go beyond automated scans, proactively identifying risks before attackers can exploit them. If you’d like to keep your applications secure, don’t hesitate to get in touch and see how we can help.