← All research

Research

Critical vulnerability in EGroupware product leads to remote code execution - CVE-2026-27823

A critical authorization bypass in EGroupware allows attackers to achieve remote code execution through arbitrary file upload and file read primitives. We break down the vulnerability, exploitation chain, responsible disclosure process, and how it was fixed by the EGroupware team.

image

During a recent vulnerability assessment, we identified a critical security issue affecting EGroupware - CVE-2026-27823. The vulnerability allows an attacker to execute arbitrary commands on an EGroupware instance using any valid account. Furthermore, if user registration is enabled on the server, this could be exploited without authentication.

The vulnerability has been fixed in version 23.1.20260224, 26.2.20260224 or higher. Users are strongly recommended to upgrade the EGroupware instances

The Vulnerability

Within EGroupware\SmallParT\Widgets\SmallPartMediaRecorder::ajax_upload() the application attempts to verify whether the current user is the teacher of the specified course ID.

image

Then it politely uploads the given file into the controllable file path.

image

Even though we asked Claude if the isTeacher check is bypassable, it said no; we decided to take a look by ourselves and then discovered the way to leverage it.

The authorization check is either insufficient or improperly enforced, allowing an attacker to bypass the intended access control mechanism. The most important check is that the course access list for the given course ID must contain $required_acl(self::ROLE_TEACHER) i.e., 3.

image

The key realization: $data['video']['course_id'] comes from attacker-controlled JSON. Nothing forces it to be an integer. If the attacker sends it as an array, every is_array($course) branch in isParticipant activates in the attacker's favor.

The course_acl for this course ID is taken from the request. It is quite a complex flow, but in short, if the request is like:

data={ "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": "/../../../../../../../../../usr/share/egroupware/header.inc.php" } }

Then the course access list is taken from the value participant_role. By simply setting it to 3, we can bypass the isTeacher check.

image

And the file path is taken from the video_path value.

image

One important thing is that, since the server is running as the www-data user, we can only edit the header.inc.php file.

image

Writing a PHP webshell directly into header.inc.php is not sufficient. In practice, OPcache prevents modifications to the file from taking effect immediately, so the injected code may never be executed. Moreover, an invalid header.inc.php would prevent EGroupware from starting, effectively taking the application offline.

Fortunately, gaining control over header.inc.php still provides multiple paths to code execution. One of the most interesting is the $GLOBALS['egw_info']['flags']['autoload']

During initialization, autoload.php checks whether this value is defined and callable. If so, it invokes it via call_user_func(), allowing an attacker to execute arbitrary PHP code.

image

For demonstration purposes, simply appending phpinfo(); to the file is enough to prove code execution. However, this introduces another challenge: the modified header.inc.php must remain syntactically valid and preserve its original functionality. Otherwise, the application will fail to start before the injected code can ever be reached.

Then we found another vulnerability that allows arbitrary file read:

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

This vulnerability lies in importexport_export_ui::download

where the server accepts _filename and uses it to read the file.

image

And we can read the file content

image

Finally, with that file content, we can obtain a valid header.inc.php file using the request.

image

After the server restarts or the cache expires, the server will execute the function. Also, another effective way is to change the admin setup password to fully control the server.

image

As an example, we ran a test on https://demo.egroupware.net/ to verify that it works.

image

We decided not to modify that content because it would break the system. We stopped there and reported it to the EGroupware team.

Timeline

Date

Event

February 24, 2026

Cenobe reported the vulnerability to EGroupware

February 24, 2026

EGroupware team fixed the vulnerability

July 06, 2026

The vulnerability was published on GitHub Advisories

July 08, 2026

We published this article

Our track record

We also maintain undisclosed zero-day research. Vulnerability research is core to what we do at Cenobe. It's not a side project. It's part of how we stay sharp, how we understand real-world attack surfaces, and how we deliver better results for our clients across penetration testing, red teaming, and attack surface management. If you'd like to talk about what we do, we're at cenobe.com.