GitHub Advisoryadvisory · Packagist

GHSA-xg76-5qj2-2hhv Admidio: CSRF in SSO client `enable` action toggles SAML/OIDC clients without token validation

MEDIUM Published 2026-05-29 Modified 2026-05-29 Official page ↗
Aliases
CVE-2026-47229
Ecosystem
Packagist
Packages
admidio/admidio
Severity
Moderate
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:L
Weaknesses
CWE-352
Reviewed
2026-05-29

Affected packages

• Packagist admidio/admidio: < 5.0.10 → fixed in 5.0.10

Description

Summary `modules/sso/clients.php` validates an `adm_csrf_token` on every state-changing branch except `enable`. The `enable` case loads the SAML or OIDC client by UUID, calls `$client->enable($enabled)`, and persists the new state with no token check. Because the action is reachable via plain GET parameters, a third-party page can trick an authenticated administrator into disabling (or silently re-enabling) any configured SAML or OIDC client. Disabling an SSO client breaks every downstream relying-party application that authenticates through it. Details Vulnerable Code `modules/sso/clients.php:84-115` — the file's other branches each begin with `SecurityUtils::validateCsrfToken($_POST['adm_csrf_token']);`, but `case 'enable':` does not: ```php case 'delete_oidc': // check the CSRF token of the form against the session token SecurityUtils::validateCsrfToken($_POST['adm_csrf_token']); $oidcService = new OIDCService($gDb, $gCurrentUser); $client = $oidcService->getClientFromUUID($getClientUUID); $client->delete(); echo json_encode(array('status' => 'success')); break; case 'enable': // readDataByUuid($getClientUUID); if ($client->isNewRecord()) { // Not a SAML record, so try OIDC: $client = new OIDCClient($gDb); $client->readDataByUuid($getClientUUID); } if ($client->isNewRecord()) { throw new Exception('SYS_SSO_INVALID_CLIENT'); } $client->enable($enabled); $client->save(); echo json_encode(['success' => true]); break; ``` The `enable($enabled)` call is documented to set a single boolean column on the SAML / OIDC client row — `smc_enabled` for SAML, `ocl_enabled` for OIDC — and `save()` persists the change immediately. The handler accepts plain GET (`admFuncVariableIsValid($_GET, 'enabled', 'boolean')`), so a `` or auto-submitting form is sufficient. Exploitation Flow 1. Attacker prepares a hostile page that loads (e.g.) `&enabled=0">`. The client UUID can be observed by anyone who has visited the SSO settings, by anyone who has crawled the SAML metadata endpoint, or by anyone with read access to the SSO clients table — but the value is also enumerable: an admin viewing the list of SSO clients in the UI exposes `data-uuid` attributes in the rendered HTML, and SSO metadata endpoints (e.g. `modules/sso/saml.php?metadata=1&uuid=...`) confirm valid UUIDs by returning XML. 2. An Admidio administrator visits the hostile page while logged in. The browser sends Admidio's session cookie (which does not set `SameSite=Strict`). 3. The server runs `case 'enable':` as the admin, sets `smc_enabled=0` (or `ocl_enabled=0`), and replies `{"success":true}`. 4. The configured SAML / OIDC client is now disabled. Every downstream application authenticating through it gets `SYS_SSO_INVALID_CLIENT` on its next AuthnRequest / token-endpoint call. The outage persists until an admin notices and toggles it back on. The attacker can also flip the bit the other way: silently *re-enabling* a client that an admin had previously deactivated (perhaps because of a security concern with that relying party). PoC Tested on HEAD `c5cde53`. To produce a deterministic test target, an SSO client is provisioned directly in the DB: ``` 0. seed a SAML client mariadb -h 127.0.0.1 -P 3399 -u admidio -p... admidio readDataByUuid($getClientUUID); if ($client->isNewRecord()) { $client = new OIDCClient($gDb); $client->readDataByUuid($getClientUUID); } if ($client->isNewRecord()) { throw new Exception('SYS_SSO_INVALID_CLIENT'); } $client->enable($enabled); $client->save(); echo json_encode(['success' => true]); break; ``` Update the JS call site that drives the enable/disable toggle to POST the form's CSRF token (the page already renders `adm_csrf_token`). A regression test should issue a `GET /modules/sso/clients.php?mode=enable&uuid=&enabled=0` with an admin cookie but no token, and assert the response rejects the request and the client's `_enabled` column is unchanged.

Related

Alias · CVE (1)

  • CVE-2026-47229 Admidio is an open-source user management solution. vulnerability

Weakness · CWE (1)

  • CWE-352 Cross-Site Request Forgery weakness

References