CVE-2026-102490

Zammad Improper Privilege Management Local Privilege Escalation (CVE-2026-102490)

Privilege Escalation Last updated:

Detects exploitation and exposure of CVE-2026-102490, an actively-exploited (CISA KEV) improper privilege management (CWE-269) vulnerability in Zammad GmbH's Zammad help desk / ticketing platform. The flaw allows a lower-privileged local or authenticated actor to escalate privileges within the Zammad application context, obtaining agent or admin-level capabilities they were not granted. This detection surfaces vulnerable Zammad deployments, anomalous privilege/role changes in Zammad audit logs, and local escalation artifacts on hosts running the Zammad service (typically Ruby/Rails under a dedicated 'zammad' service account backed by Elasticsearch and PostgreSQL).

Vulnerability Intelligence

KEV — Known Exploited

What is CVE-2026-102490 Zammad Improper Privilege Management Local Privilege Escalation (CVE-2026-102490)?

Zammad Improper Privilege Management Local Privilege Escalation (CVE-2026-102490) (CVE-2026-102490) maps to the Privilege Escalation tactic — the adversary is trying to gain higher-level permissions in MITRE ATT&CK.

This page provides production-ready detection logic for Zammad Improper Privilege Management Local Privilege Escalation (CVE-2026-102490), covering the data sources and telemetry it touches: Syslog, Linux auditd, Zammad application log. The queries below are rated high severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Privilege Escalation
Microsoft Sentinel / Defender
kusto
// Zammad privilege escalation — anomalous role/permission grants and zammad service-account abuse (CVE-2026-102490)
let zammadHosts = dynamic(["zammad", "zammad-web", "zammad-app"]);
union isfuzzy=true Syslog, LinuxAuditLog
| where TimeGenerated > ago(1d)
| where (ProcessName has_any ("ruby", "rails", "zammad", "rake") or SyslogMessage has "zammad")
| where SyslogMessage has_any ("permission", "role", "admin", "Users::Permission", "user.roles", "privilege")
    or SyslogMessage matches regex @"(?i)(grant|add).{0,20}(admin|role|permission)"
| extend Account = coalesce(column_ifexists("Acct", ""), extract(@"user[_ ]?id[=:]\s*(\d+)", 1, SyslogMessage))
| project TimeGenerated, Computer, ProcessName, Account, SyslogMessage
| sort by TimeGenerated desc

Hunts Syslog/auditd on Zammad hosts for Rails/zammad process activity that grants roles, permissions, or admin to users — the observable side-effect of CVE-2026-102490 privilege escalation.

high severity medium confidence

Data Sources

Syslog Linux auditd Zammad application log

Required Tables

Syslog LinuxAuditLog

False Positives

  • Legitimate administrator provisioning a new agent and assigning the Admin or Agent role via the Zammad UI or rails console.
  • Automated LDAP/SAML role-sync jobs that reconcile Zammad permissions on a schedule.
  • Zammad upgrade/migration (rake db:migrate, zammad run rails r) that touches permission tables during maintenance windows.

Sigma rule & cross-platform mapping

The detection logic for Zammad Improper Privilege Management Local Privilege Escalation (CVE-2026-102490) (CVE-2026-102490) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  product: windows

Browse the community-maintained Sigma rules for this technique:


Testing Methodology

Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Zammad role escalation via rails console (lab)

    Expected signal: Zammad production.log and PostgreSQL history entry recording a role change to Admin for the target user; process telemetry for the ruby/rails rake invocation under the zammad account.

  2. Test 2Direct permission grant to low-privileged user (lab)

    Expected signal: production.log 'Users::Permission' / permission grant entry and corresponding history row.

  3. Test 3Suspicious zammad-account process referencing permissions (lab)

    Expected signal: ProcessRollup2 / auditbeat process event: ruby/rails executed by user 'zammad' with command line containing 'Permission' and 'admin'.


Response Playbook

Triage

  1. Confirm the affected host is running Zammad and identify the installed version (`zammad run rails r 'puts Version.get'` or check the package version); compare against the fixed release listed at https://zammad.com/en/product/releases/.
  2. Review the Zammad activity/audit log (Admin > System > Monitoring, or the `history` table in PostgreSQL) for recent role or permission changes — specifically any user granted the Admin or Agent role without a corresponding authorized admin action.
  3. Correlate the timestamp of any suspicious privilege change with web access logs and session data to identify the source user_id, IP address, and session that triggered the escalation.
  4. Determine whether the escalating account was a newly created or previously low-privileged (customer) account, which strongly indicates exploitation rather than legitimate administration.

Containment

  1. Isolate or restrict external access to the Zammad instance (block at reverse proxy / WAF) until the patch is applied, as this vulnerability is on the CISA KEV list and actively exploited.
  2. Revoke elevated roles from any account that was escalated without authorization and force a password reset plus session invalidation (`zammad run rails r 'Setting.set(...)'` / delete sessions) for affected and admin accounts.
  3. Apply the vendor-fixed Zammad release immediately per CISA BOD 26-04 prioritization guidance; schedule an emergency change if outside normal windows.

Evidence Collection

  1. Preserve the Zammad `production.log`, the PostgreSQL `history` and `users`/`roles`/`permissions` tables, and reverse-proxy access logs covering the suspected exploitation window.
  2. Capture the current role/permission assignments for all accounts (`zammad run rails r 'User.all.each{|u| puts "#{u.login}: #{u.roles.pluck(:name)}"}'`) as a baseline snapshot and export the OS-level auditd log for the zammad service account.

Escalation Criteria

  • ! Escalate to incident response if any customer-tier or newly registered account obtained Admin/Agent privileges, or if privileged actions (ticket data export, user impersonation, config change) followed the escalation.
  • ! Escalate to management and legal/compliance if evidence shows data access or exfiltration via the escalated account, given KEV status and potential breach-notification obligations.

Investigation Guide

Forensic Artifacts

  • > Zammad `production.log` entries showing permission/role assignment
  • > PostgreSQL `history` table rows recording role grants
  • > Reverse-proxy/web access logs for the exploiting session
  • > auditd records for the zammad service account
  • > Zammad session records in the database

Tuning Guidance

Baseline which accounts and automation (LDAP/SAML sync, onboarding workflows) legitimately modify Zammad roles, and whitelist those user_ids/source IPs. Narrow the regex to the exact log signature emitted by your Zammad version's permission-change code path once observed. Focus alerting on escalations where the target account was previously a customer or was created within the last 24 hours, which dramatically reduces false positives from routine administration.


Hunting Queries

Surface all Zammad role/permission grant activity over the past week to baseline normal admin behavior and spot anomalous escalations.

Hunting — KQL
kql
Syslog | where TimeGenerated > ago(7d) | where SyslogMessage has "zammad" and SyslogMessage has_any ("Admin","role","permission") | where SyslogMessage matches regex @"(?i)(grant|assign|add).{0,30}(admin|role)" | project TimeGenerated, Computer, SyslogMessage
Hunting — SPL
spl
index=linux (source="*zammad*production.log" OR sourcetype=syslog host="zammad*") ("role" OR "permission" OR "Admin") | rex field=_raw "(?i)user[_ ]?id[=:]\s*(?<uid>\d+)" | stats count values(_raw) as events by uid, host | where count > 0

Atomic Red Team Tests

Test 1 Zammad role escalation via rails console (lab)
linux

Simulates an unauthorized grant of the Admin role to a low-privileged user through the Zammad rails runner, reproducing the audit-log side-effect of CVE-2026-102490.

Command

bash
zammad run rails r 'u = User.find_by(login: "[email protected]"); u.roles = Role.where(name: ["Admin"]); u.save!'

Cleanup

bash
zammad run rails r 'u = User.find_by(login: "[email protected]"); u.roles = Role.where(name: ["Customer"]); u.save!'

Expected Telemetry

Zammad production.log and PostgreSQL history entry recording a role change to Admin for the target user; process telemetry for the ruby/rails rake invocation under the zammad account.

Expected Detection

KQL/SPL/EQL rules fire on the permission/role grant referencing 'Admin' on a zammad host.

Test 2 Direct permission grant to low-privileged user (lab)
linux

Grants an elevated permission (admin.user) directly, emulating privilege manipulation without a full role change.

Command

bash
zammad run rails r 'u = User.find_by(login: "[email protected]"); u.permissions = ["admin.user"]; u.save!'

Cleanup

bash
zammad run rails r 'u = User.find_by(login: "[email protected]"); u.permissions = []; u.save!'

Expected Telemetry

production.log 'Users::Permission' / permission grant entry and corresponding history row.

Expected Detection

Rules match the 'permission'/'Users::Permission' signature in process args and application logs.

Test 3 Suspicious zammad-account process referencing permissions (lab)
linux

Runs a rake task under the zammad service account that references permission tables, generating the process-launch telemetry the endpoint rules key on.

Command

bash
sudo -u zammad bash -c 'cd /opt/zammad && bundle exec rails r "puts Permission.pluck(:name).grep(/admin/)"'

Cleanup

bash
echo 'no cleanup required — read-only enumeration'

Expected Telemetry

ProcessRollup2 / auditbeat process event: ruby/rails executed by user 'zammad' with command line containing 'Permission' and 'admin'.

Expected Detection

CrowdStrike CQL and Elastic EQL rules match ruby/rails process by the zammad user referencing permission/admin.

Related Detections