CVE-2026-34384: Admidio/admidio Admidio Has Missing CSRF Protection Vulnerability
MODERATECVE-2026-34384 is a MODERATE (CVSS 4.5) admidio has missing csrf protection vulnerability (CWE-352: Cross-Site Request Forgery (CSRF)) affecting Admidio/admidio libraries in the Packagist ecosystem. The issue involves admidio has missing csrf protection on registration approval actions. Remediation is available by upgrading affected packages to version 5.0.8.
CVE-2026-34384 at a Glance
Security Impact
CVSS: 4.5
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:U/C:N/I:H/A:N).
How to Fix CVE-2026-34384
To remediate this vulnerability, upgrade all affected Admidio/admidio dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade admidio/admidio to 5.0.8
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for admidio/admidio
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-34384, inspect your project dependencies for Admidio/admidio:
inspect dependencies for admidio/admidio
Analyze the terminal output to locate any version of Admidio/admidio in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 5.0.8), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-352: Cross-Site Request Forgery (CSRF), where the web application does not, or cannot, sufficiently verify whether a request was intentionally provided by the user who sent the request, which could have originated from an unauthorized actor. In Admidio/admidio, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-34384 Affected Admidio/admidio Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
admidio/admidio
|
Packagist |
< 5.0.8
|
5.0.8
|
References
Frequently Asked Questions
What is CVE-2026-34384?
Which Admidio/admidio versions are affected?
What version fixes CVE-2026-34384?
Is admidio/admidio affected?
What is the CVSS score of CVE-2026-34384?
What CWE is associated with CVE-2026-34384?
How can I check Packagist dependencies for CVE-2026-34384?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-ph84-r98x-2j22",
"modified" : "2026-03-31T23:11:24Z",
"published" : "2026-03-31T23:11:24Z",
"aliases" : [ "CVE-2026-34384" ],
"summary" : "Admidio has Missing CSRF Protection on Registration Approval Actions",
"details" : "## Summary\n\nThe create_user, assign_member, and assign_user action modes in modules/registration.php approve pending user registrations via GET request without validating a CSRF token. Unlike the delete_user mode in the same file (which correctly validates the token), these three approval actions read their parameters from $_GET and perform irreversible state changes without any protection. An attacker who has submitted a pending registration can extract their own user UUID from the registration confirmation email URL, then trick any user with the rol_approve_users right into visiting a crafted URL that automatically approves the registration. This bypasses the manual registration approval workflow entirely.\n\n## Details\n\n### CSRF Protection Is Present for delete_user but Absent for Approval Modes\n\nFile: modules/registration.php, lines 90-128\n\nThe delete_user mode validates the CSRF token (line 99), but the three approval modes do not:\n\n```php\n// assign_member and assign_user: no CSRF check\n} elseif (in_array($getMode, array('assign_member', 'assign_user'))) {\n $registrationService = new RegistrationService($gDb, $getUserUUID);\n $message = $registrationService->assignRegistration($getUserUUIDAssigned, $getMode === 'assign_member');\n $gMessage->setForwardUrl($message['forwardUrl']);\n $gMessage->show($message['message']);\n\n// create_user: no CSRF check\n} elseif ($getMode === 'create_user') {\n $registrationUser->acceptRegistration();\n if ($gCurrentUser->isAdministratorRoles()) {\n admRedirect(SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES.'/profile/roles.php',\n array('accept_registration' => true, 'user_uuid' => $getUserUUID)));\n }\n\n// delete_user: CSRF IS validated\n} elseif ($getMode === 'delete_user') {\n SecurityUtils::validateCsrfToken($_POST['adm_csrf_token']); // <-- protected\n $registrationUser->delete();\n}\n```\n\nThe three approval modes read both UUIDs exclusively from $_GET (lines 41-43):\n\nThe approve action modes accept $_GET parameters `user_uuid` and `user_uuid_assigned` without any POST body or CSRF token. Both parameters pass through `admFuncVariableIsValid()` with `uuid` type validation, which prevents SQL injection but provides no CSRF protection.\n\n### User UUID Is Known to the Attacker from Registration Email\n\nFile: `D:/bugcrowd/admidio/repo/src/Infrastructure/Service/RegistrationService.php`, lines 154-157\n\nWhen a user submits a registration, Admidio sends a confirmation email containing a URL of the form:\n\n```\nhttps://TARGET/adm_program/modules/registration.php?id=VALIDATION_ID&user_uuid=REGISTRANT_UUID\n```\n\nThe `user_uuid` in this URL is the registrant's own UUID. The attacker has this UUID because they received the confirmation email for their own registration.\n\n### isAdministratorRegistration() Is a Delegated Right\n\nFile: `D:/bugcrowd/admidio/repo/src/Users/Entity/User.php`, lines 1603-1606\n\n```php\npublic function isAdministratorRegistration(): bool\n{\n return $this->checkRolesRight('rol_approve_users');\n}\n```\n\nThe `rol_approve_users` right is a delegated organizational privilege, not full system administrator access. Any member designated to review registrations -- for example, a membership secretary or club administrator -- is a valid CSRF victim.\n\n## PoC\n\n**Scenario: Attacker bypasses manual registration approval**\n\nPrerequisites: (1) Manual registration approval is enabled. (2) The attacker submits a registration form and receives a confirmation email with their `user_uuid`. (3) After clicking the confirmation link, their registration enters the pending queue.\n\n**Step 1: Attacker extracts their own user_uuid from the registration email**\n\nThe confirmation email contains a link of the form:\n\n```\nhttps://TARGET/adm_program/modules/registration.php?id=VALIDATION_ID&user_uuid=ATTACKER_UUID\n```\n\nThe `ATTACKER_UUID` is visible to the attacker from their own email.\n\n**Step 2: CSRF auto-approval via image tag**\n\nThe attacker hosts a page that the victim (admin with `rol_approve_users` right) visits:\n\n```html\n<img src=\"https://TARGET/adm_program/modules/registration.php?mode=create_user&user_uuid=ATTACKER_UUID\" width=\"1\" height=\"1\">\n```\n\nWhen the victim loads this page, Admidio silently accepts the attacker registration and assigns default organization roles. No confirmation or token is required.\n\n**Step 3: Force-assign registration to an existing account (account takeover)**\n\nIf the attacker knows the UUID of an existing member (obtainable from profile page URLs when the user list is visible) and has a pending registration:\n\n```html\n<img src=\"https://TARGET/adm_program/modules/registration.php?mode=assign_user&user_uuid=ATTACKER_REG_UUID&user_uuid_assigned=EXISTING_USER_UUID\" width=\"1\" height=\"1\">\n```\n\nThis merges the pending registration into the existing account, replacing that account login credentials with the attacker credentials.\n\n## Impact\n\n- **Manual Approval Bypass:** An attacker with a pending registration can force auto-approval without waiting for an administrator to manually review it. This grants them organization membership, including access to events, documents, mailing lists, and other role-restricted features.\n- **Account Takeover via assign_user CSRF:** If the attacker knows any member UUID (visible in profile page URLs), the `assign_user` mode merges the attacker registration into that member account, replacing the existing member login with the attacker credentials. This is a full account takeover requiring only that the victim admin visit a crafted URL.\n- **Low Attack Complexity:** The attacker only needs their own registration email to get their UUID. The CSRF payload is a plain GET request via an image tag -- no JavaScript required.\n- **Delegated Right:** The required victim right (`rol_approve_users`) is a common delegation target in organizations with membership approval workflows.\n\n## Recommended Fix\n\nAdd `SecurityUtils::validateCsrfToken($_POST[\"adm_csrf_token\"])` at the beginning of each approval action, consistent with how `delete_user` is already protected in the same file.\n\n```php\n// File: modules/registration.php\n\n} elseif (in_array($getMode, array('assign_member', 'assign_user'))) {\n // ADD: validate CSRF token\n SecurityUtils::validateCsrfToken($_POST['adm_csrf_token']);\n $registrationService = new RegistrationService($gDb, $getUserUUID);\n $message = $registrationService->assignRegistration($getUserUUIDAssigned, $getMode === 'assign_member');\n ...\n\n} elseif ($getMode === 'create_user') {\n // ADD: validate CSRF token\n SecurityUtils::validateCsrfToken($_POST['adm_csrf_token']);\n $registrationUser->acceptRegistration();\n ...\n\n} elseif ($getMode === 'delete_user') {\n SecurityUtils::validateCsrfToken($_POST['adm_csrf_token']); // already protected\n $registrationUser->delete();\n}\n```\n\nAdditionally, convert the approval action URLs from GET-based links to POST-form buttons (with the CSRF token in a hidden field). The existing `delete_user` button uses `callUrlHideElement()` which already sends the token in the POST body -- use the same pattern for approval buttons.",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:U/C:N/I:H/A:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Packagist",
"name" : "admidio/admidio"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "5.0.8"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/Admidio/admidio/security/advisories/GHSA-ph84-r98x-2j22"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-34384"
}, {
"type" : "WEB",
"url" : "https://github.com/Admidio/admidio/commit/707171c188b3e8f36007fc3f2bccbfac896ed019"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/Admidio/admidio"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-352" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-03-31T23:11:24Z",
"nvd_published_at" : "2026-03-31T21:16:30Z"
}
}