SAML Assertion Replay Testing for Bug Bounty Hunters
SAML login ends with the identity provider posting a signed SAMLResponse to an assertion consumer service. That response is meant for a particular service provider, recipient, and time window. If the service provider accepts the same assertion again after it has already created a session, anyone who captures one valid response may be able to replay it.
Use only your own identity and a dedicated test tenant where possible. Proxy one complete login, save the base64-encoded response and the ACS request, then let the first login finish normally. In a separate clean browser, resend the exact POST to the same ACS endpoint. Remove existing cookies so you can distinguish a new session from the old browser state.
If the second browser receives a fresh authenticated session, record the time and session identifier. Repeat once after a short delay to learn whether acceptance lasts for the assertion's full validity period or beyond it. Do not automate dozens of replays; two controlled requests establish the behavior.
What the timestamps really say
Decode the assertion locally without editing it. Inspect NotBefore, NotOnOrAfter, IssueInstant, Recipient, Audience, InResponseTo, and the assertion ID. A service provider should enforce these values with a small clock-skew allowance. For request-initiated SSO, InResponseTo should match an outstanding authentication request and that request should be consumed once.
An assertion replayed inside its valid window is not always equally severe. Some SAML deployments deliberately allow unsolicited identity-provider-initiated login, where no request ID exists. Even there, caching accepted assertion IDs until expiry prevents straightforward reuse. Describe the deployment rather than claiming every repeated POST violates the same rule.
Try replaying after logout. If an old assertion immediately recreates the session, logout cannot protect a user whose response was captured. Then wait until NotOnOrAfter passes and test once more. Acceptance after expiry points to a more serious timestamp-validation failure.
Boundaries you should not cross
Do not alter the subject to another employee; the signature should fail, and using a real identity creates needless risk. Do not disable signature checks in your tooling and mistake local decoding for server acceptance. Never forward an assertion to another application unless both services and cross-audience testing are explicitly in scope.
You can safely test audience binding with services you own if the program offers two test applications. An assertion minted for application A should not authenticate to application B. Recipient and destination values deserve the same exact comparison, especially when staging and production share an SSO integration.
Capture whether the replay creates an entirely new session or merely redirects to an already authenticated one. Cookie-free browser evidence and distinct server session values settle that question.
Reporting replay cleanly
Provide the two ACS requests, response timestamps, decoded condition fields, and proof that each browser obtained a session. Redact the assertion body, name identifier, and cookies. Explain the realistic capture route carefully—browser history is less likely for a POST, while proxy logs, malware, compromised extensions, verbose server logs, or a leaked support trace are plausible.
Recommend strict signature validation against configured IdP certificates, exact audience and recipient checks, enforcement of all time conditions, one-time consumption of InResponseTo, and an assertion-ID replay cache lasting at least through expiry. Keep SAML responses out of application logs and traces. Replay protection is cheap compared with explaining why a signed login artifact worked twice.