{"id":"CVE-2026-41660","aliases":["GHSA-rh3w-4ccx-prf9"],"url":"https://o3.security/vulnerability/CVE-2026-41660","summary":"Admidio: Inverted 2FA Reset Authorization Check Lets Group Leaders Strip Admin TOTP","details":"## Summary\n\nA logic error in Admidio's two-factor authentication reset inverts the authorization check. Non-admin users cannot remove their own TOTP configuration, but they can remove other users' TOTP, including administrators. A group leader with profile edit rights on an admin account can strip that admin's 2FA.\n\n## Details\n\nIn `modules/profile/two_factor_authentication.php` at line 84, the authorization check uses an inverted condition:\n\n```php\n// modules/profile/two_factor_authentication.php line 84\nif (!($gCurrentUser->isAdministrator() || $gCurrentUserId !== $userId))\n{\n    throw new AdmException('SYS_NO_RIGHTS');\n}\n```\n\nBy De Morgan's law, this condition evaluates as:\n- Blocks when: `NOT isAdministrator() AND $gCurrentUserId === $userId`\n- In practice: blocks non-admins from resetting their OWN 2FA\n- Passes: non-admins resetting OTHER users' 2FA (the opposite of the intended behavior)\n\nThe intended logic should block non-admins from resetting other users' 2FA. The `!==` operator on line 84 should be `===`.\n\nA group leader who holds `hasRightEditProfile()` permission on an admin user (checked earlier in the flow) can exploit this to strip 2FA from administrator accounts, reducing their security to password-only authentication.\n\n## Proof of Concept\n\n1. As `testuser` (a non-admin group leader with edit rights on admin profiles), send:\n\n```http\nPOST /adm_program/modules/profile/two_factor_authentication.php HTTP/1.1\nContent-Type: application/x-www-form-urlencoded\nCookie: ADMIDIO_..._SESSION_ID=<testuser_session>\n\nmode=reset&user_uuid=<admin_user_uuid>\n```\n\nResult: the server removes 2FA from the admin account.\n\n2. As `testuser`, attempt to reset their own 2FA:\n\n```http\nPOST /adm_program/modules/profile/two_factor_authentication.php HTTP/1.1\nContent-Type: application/x-www-form-urlencoded\nCookie: ADMIDIO_..._SESSION_ID=<testuser_session>\n\nmode=reset&user_uuid=<testuser_user_uuid>\n```\n\nResult: `SYS_NO_RIGHTS` error. The user cannot reset their own 2FA.\n\nThis confirms the authorization logic is inverted.\n\n## Impact\n\nA group leader (or any user with profile edit rights on an admin) can disable two-factor authentication on administrator accounts. This degrades admin account security to password-only, opening the door to credential stuffing or brute force attacks without a 2FA barrier.\n\n## Recommended Fix\n\nChange `!==` to `===` on line 84 of `modules/profile/two_factor_authentication.php`:\n\n```php\n// Fixed condition: block non-admins from resetting OTHER users' 2FA\nif (!($gCurrentUser->isAdministrator() || $gCurrentUserId === $userId))\n{\n    throw new AdmException('SYS_NO_RIGHTS');\n}\n```\n\n---\n*Found by [aisafe.io](https://aisafe.io)*","published":"2026-05-07T02:59:29.810Z","modified":"2026-08-12T03:51:13.364377579Z","cvss":{"score":7.1,"severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L"},"epss":{"score":0.00297,"percentile":0.2213,"asOf":"2026-08-13"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Packagist","name":"admidio/admidio","fixedVersion":"5.0.9"}],"fix":null,"references":[{"type":"WEB","url":"https://github.com/Admidio/admidio/releases/tag/v5.0.9"},{"type":"ADVISORY","url":"https://github.com/Admidio/admidio/security/advisories/GHSA-rh3w-4ccx-prf9"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/41xxx/CVE-2026-41660.json"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-41660"},{"type":"PACKAGE","url":"https://github.com/Admidio/admidio"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:13.364377579Z"}}