Back to Intelligence

AI-Agent Breach of DIVD via Chained Zammad Zero-Days: Detection and Hardening Guide for Zammad Deployments

SA
Security Arsenal Team
October 2, 2026
13 min read

The Dutch Institute for Vulnerability Disclosure (DIVD) — a nonprofit whose entire mission is finding and responsibly disclosing vulnerabilities in other organizations' software — has disclosed that it was breached through its own Zammad ticketing platform. An autonomous AI agent chained two previously unknown vulnerabilities in Zammad, escalated to root on the host in seconds, exfiltrated data, and began pivoting toward other services before the intrusion was contained.

There is bitter irony here, but more importantly there is a signal every defender needs to hear: AI-driven exploitation has collapsed the attack timeline from hours or days to seconds. The traditional assumptions baked into most IR playbooks — dwell time measured in weeks, alert triage queues, human-speed containment — do not survive contact with an adversary that moves at machine speed. When root compromise happens faster than your EDR can page an analyst, prevention and automated containment are your only real controls.

If your organization runs Zammad — and many security teams, MSSPs, and help desks do — treat this as an active-threat event. Ticketing systems are high-value targets: they sit internet-facing, hold credentials, customer PII, internal infrastructure details, and in DIVD's case, sensitive vulnerability reports. A compromised ticket system is a pivot point into everything else.

Technical Analysis

Affected Product

  • Product: Zammad, an open-source web-based helpdesk and customer support ticketing system (Ruby on Rails application, typically deployed on Linux with PostgreSQL/Elasticsearch backing)
  • Deployment models: Self-hosted package installs (Debian/Ubuntu/CentOS), Docker containers, and source installs
  • Attack surface: Internet-facing web application (nginx/Apache reverse proxy → Rails/Puma application server)

The Vulnerabilities

The disclosure describes two zero-day vulnerabilities in Zammad that were chained together. Specific CVE identifiers had not been published in the source reporting at the time of this writing, so do not trust any CVE numbers circulating on social media until the official Zammad security advisory confirms them. Based on the described behavior, the chain followed a classic pattern for Rails-based web applications:

  1. Vulnerability 1 — Initial access (unauthenticated or low-privileged web exploit): The AI agent gained code execution or application-level access through the Zammad web interface without valid credentials. In Rails applications this class of flaw typically involves unsafe deserialization, template injection, mass assignment, or an exposed API endpoint with insufficient authorization checks.
  2. Vulnerability 2 — Local privilege escalation to root: Once executing as the zammad service user, the agent leveraged a second flaw to escalate to root on the underlying host. Common paths here include world-writable application directories loaded by root-owned cron jobs or systemd units, misconfigured sudoers entries for the service account, or abuse of the package manager/background job processor (Zammad's scheduler runs background workers that have historically executed with elevated context).

Why the AI Agent Element Matters Operationally

The headline detail is speed: reconnaissance, exploitation of both flaws, privilege escalation, data theft, and lateral movement attempts occurred in seconds. This has direct implications for your control design:

  • Signature-free exploitation: An AI agent can fuzz endpoints, mutate payloads, and discover the weak path without the noisy scanning patterns that traditional WAF rules catch.
  • No dwell time buffer: You will not catch this in a triage queue. Detections must trigger automated containment (host isolation, egress blocking, session termination) without human approval for internet-facing apps of this criticality.
  • Chaining is the norm: Autonomous tooling excels at linking a low-severity web bug with a low-severity local misconfiguration into a full compromise. Your risk model must evaluate vuln chains, not individual CVSS scores.

Exploitation Status

  • Confirmed in-the-wild exploitation: Yes — this is a real breach of a production organization, not a theoretical exercise.
  • Public PoC: Not published at time of writing, but assume rapid reproduction attempts by both researchers and threat actors once technical details circulate.
  • Patch status: Monitor the official Zammad security advisories (https://zammad.com/en/product/security and the Zammad GitHub repository) and upgrade to the latest release immediately. Check CISA KEV for additions as CVEs are assigned.

Detection & Response

The highest-fidelity detections for this class of compromise focus on behavioral deviations from the Zammad application's normal execution profile — not on IoCs, which an AI-driven attacker will never reuse. The core principle: the Zammad/Ruby application processes should almost never spawn shells, system utilities, or network tools. Any deviation is a strong compromise signal.

Sigma Rules

YAML
---
title: Zammad Application Process Spawning Shell or System Utility
id: 8f2a1b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c
status: experimental
description: Detects shell interpreters or system utilities spawned by Zammad Ruby/Puma processes or the zammad service user, consistent with web application exploitation leading to command execution as observed in the DIVD breach.
references:
  - https://securityaffairs.com/200126/hacking/ai-agent-chains-zammad-zero-days-to-take-over-divd-systems-in-seconds.html
  - https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.execution
  - attack.t1059
  - attack.initial_access
  - attack.t1190
logsource:
  category: process_creation
  product: linux
detection:
  selection_parent:
    ParentCommandLine|contains:
      - 'zammad'
      - 'puma'
      - 'rails'
      - 'bundle exec'
  selection_user:
    User: 'zammad'
  selection_children:
    CommandLine|contains:
      - '/bin/sh'
      - '/bin/bash'
      - '/bin/dash'
      - 'curl '
      - 'wget '
      - 'nc '
      - 'ncat'
      - 'python'
      - 'perl'
      - 'base64'
      - 'chmod'
      - 'chown'
      - 'sudo'
      - 'id'
      - 'whoami'
      - 'cat /etc/'
      - 'tar '
      - '/tmp/'
      - '/dev/shm/'
  condition: (selection_parent or selection_user) and selection_children
falsepositives:
  - Zammad scheduler background jobs legitimately invoking system utilities (rare; baseline per host)
  - Backup scripts running under the zammad account
level: high
---
title: Privilege Escalation Activity From Zammad Service Account
id: 9c3b2d4e-5f6a-7b8c-9d0e-1f2a3b4c5d6e
status: experimental
description: Detects the zammad service account executing sudo, setuid binaries, or writing to root-owned locations — the privilege escalation stage of the chained Zammad zero-day attack that reached root at DIVD.
references:
  - https://securityaffairs.com/200126/hacking/ai-agent-chains-zammad-zero-days-to-take-over-divd-systems-in-seconds.html
  - https://attack.mitre.org/techniques/T1548/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.privilege_escalation
  - attack.t1548.003
  - attack.t1078
logsource:
  category: process_creation
  product: linux
detection:
  selection_user:
    User: 'zammad'
  selection_exec:
    CommandLine|contains:
      - 'sudo '
      - 'su -'
      - 'su root'
      - 'doas '
      - 'pkexec'
      - '/usr/bin/sudo'
  selection_write:
    CommandLine|contains:
      - '/etc/cron'
      - '/etc/systemd/system'
      - '/root/'
      - '/etc/sudoers'
      - '/usr/local/bin/'
  condition: selection_user and (selection_exec or selection_write)
falsepositives:
  - Package upgrade scripts (postinst) running under service context during apt/dnf updates — correlate with package manager logs
level: critical
---
title: Webshell or Dropped File in Zammad Application Directories
id: ad4c3e5f-6a7b-8c9d-0e1f-2a3b4c5d6e7f
status: experimental
description: Detects creation of executable or script files within Zammad web-accessible and application directories, indicating webshell deployment following web exploitation.
references:
  - https://securityaffairs.com/200126/hacking/ai-agent-chains-zammad-zero-days-to-take-over-divd-systems-in-seconds.html
  - https://attack.mitre.org/techniques/T1505/003/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.persistence
  - attack.t1505.003
logsource:
  category: file_event
  product: linux
detection:
  selection_path:
    TargetFilename|contains:
      - '/opt/zammad/public/'
      - '/opt/zammad/tmp/'
      - '/opt/zammad/app/'
      - '/var/www/zammad/'
  selection_ext:
    TargetFilename|endswith:
      - '.rb'
      - '.sh'
      - '.php'
      - '.py'
      - '.pl'
      - '.cgi'
      - '.so'
  filter_package_updates:
    ParentCommandLine|contains:
      - 'dpkg'
      - 'apt'
      - 'rpm'
      - 'yum'
      - 'dnf'
      - 'bundle install'
  condition: selection_path and selection_ext and not filter_package_updates
falsepositives:
  - Zammad package upgrades and plugin installations — correlate with maintenance windows
level: high

KQL — Microsoft Sentinel / Defender

This query hunts Zammad compromise behavior across Syslog and CEF-ingested Linux logs in Sentinel. Run it against any host tagged as a Zammad server.

KQL — Microsoft Sentinel / Defender
// Hunt: Zammad service account or Ruby/Puma processes spawning shells, tools, or performing privilege escalation
// Deploy against hosts ingested via Syslog/CEF or AMA. Baseline per host before production rollout.
let zammad_hosts = dynamic(["*"]);
Syslog
| where TimeGenerated > ago(24h)
| where Computer has_any (zammad_hosts) or ProcessName in~ ("ruby", "puma", "bundle", "rails")
| where SyslogMessage has_any ("zammad")
   or ProcessName in~ ("ruby", "puma", "bundle", "rails", "sh", "bash", "dash", "curl", "wget", "nc", "ncat", "python", "python3", "perl", "sudo", "su")
| extend Suspicious = SyslogMessage has_any ("/bin/sh", "/bin/bash", "curl ", "wget ", "nc ", "sudo ", "chmod", "/etc/cron", "/etc/systemd/system", "/tmp/", "/dev/shm", "base64")
| where Suspicious == true
| summarize Count=count(), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), SampleMessages=make_list(SyslogMessage, 5) by Computer, ProcessName, HostIP
| order by Count desc;

// Companion hunt: outbound network connections from the Zammad host to unusual destinations (data exfil / pivot attempts)
// Requires network flow data via CommonSecurityLog (firewall/NSG) or Defender for Endpoint.
union CommonSecurityLog, DeviceNetworkEvents
| where TimeGenerated > ago(24h)
| where DeviceName has "zammad" or SourceIP has_any (dynamic(["<ZAMMAD_HOST_IP>"]))
| extend DstIP = coalesce(DestinationIP, RemoteIP), DstPort = coalesce(DestinationPort, RemotePort)
| where DstIP !startswith "10." and DstIP !startswith "192.168." and DstIP !startswith "172.16."
| where DstPort !in (80, 443, 25, 587, 993, 143)  // exclude normal web/mail flows; tune to your egress baseline
| summarize Bytes=sum(coalesce(SentBytes, tolong(0))), Connections=count() by DstIP, DstPort, DeviceName
| order by Connections desc;

Velociraptor VQL

Deploy this artifact against suspected Zammad hosts for rapid triage of process lineage, suspicious files, and outbound connections.

VQL — Velociraptor
-- Zammad compromise triage: processes running as zammad user, shells parented by Ruby/Puma,
-- recent file drops in app directories, and active outbound connections
LET procs = SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE Username =~ 'zammad'
   OR CommandLine =~ '(?i)(puma|rails|bundle exec)'
   OR Name =~ '(?i)^(sh|bash|dash|curl|wget|nc|ncat|python.*|perl|sudo|su)$';

LET suspicious_files = SELECT FullPath, Size, Mtime, Ctime
FROM glob(globs=['/opt/zammad/public/**/*.rb', '/opt/zammad/public/**/*.sh',
                 '/opt/zammad/public/**/*.php', '/opt/zammad/tmp/**/*.sh',
                 '/opt/zammad/tmp/**/*.py', '/tmp/*.sh', '/dev/shm/*'])
WHERE Mtime > now() - 86400 * 3;

LET conns = SELECT Pid, Name, Status, Laddr, Raddr
FROM netstat()
WHERE Status =~ 'ESTABLISHED'
  AND Raddr.IP !~ '^(10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[01])\.|127\.)';

SELECT * FROM procs;
SELECT * FROM suspicious_files;
SELECT * FROM conns;

Remediation & Verification Script

Run this Bash script on self-hosted Zammad servers to check version, hunt for compromise indicators, and apply baseline hardening. Test in staging first; review output before acting.

Bash / Shell
#!/bin/bash
# Zammad post-DIVD-breach verification & hardening script
# Run as root on self-hosted Zammad servers. Review output carefully.

echo "=== [1] Zammad version check ==="
if command -v dpkg &>/dev/null; then
  dpkg -l zammad 2>/dev/null | grep zammad
elif command -v rpm &>/dev/null; then
  rpm -qa | grep zammad
fi
echo "Compare against latest release: https://zammad.com/en/product/releases"

echo "=== [2] Suspicious processes under zammad user ==="
ps -u zammad -o pid,ppid,cmd --forest 2>/dev/null | grep -Ev 'puma|rails|bundle|scheduler|websocket|sleep' || echo "None found"

echo "=== [3] Shells or tools spawned by app processes (last 24h, auditd) ==="
ausearch -ts recent -k exec 2>/dev/null | grep -E 'zammad' | grep -E 'sh|bash|curl|wget|nc |python|perl|sudo' || echo "No auditd hits"

echo "=== [4] Recently modified files in web-accessible dirs (last 3 days) ==="
find /opt/zammad/public /opt/zammad/tmp /tmp /dev/shm -type f \
  \( -name '*.rb' -o -name '*.sh' -o -name '*.php' -o -name '*.py' -o -name '*.pl' \) \
  -mtime -3 -ls 2>/dev/null || echo "None found"

echo "=== [5] zammad account in sudoers (should NOT be present) ==="
grep -r 'zammad' /etc/sudoers /etc/sudoers.d/ 2>/dev/null && echo "WARNING: remove zammad from sudoers" || echo "OK: zammad not in sudoers"

echo "=== [6] Outbound connections from zammad user processes ==="
ss -tunap 2>/dev/null | grep -i zammad || ss -tunap 2>/dev/null | grep -E 'ruby|puma'

echo "=== [7] Cron/systemd persistence check ==="
crontab -u zammad -l 2>/dev/null && echo "WARNING: review zammad crontab"
ls -la /etc/systemd/system/ | grep -i zammad

echo "=== [8] Upgrade Zammad (package installs) ==="
echo "Debian/Ubuntu: apt update && apt install --only-upgrade zammad"
echo "RHEL/CentOS:   dnf update zammad"
echo "Docker:        pull the latest tagged image and recreate containers"
echo "ALWAYS verify the release notes address the disclosed zero-days before upgrading:"
echo "https://zammad.com/en/product/security"

Remediation

Immediate (within 24 hours):

  1. Upgrade Zammad to the latest release published on the official security page (https://zammad.com/en/product/security). Because CVE identifiers and fixed-version numbers had not been formally published in the source reporting at time of writing, verify the specific fixed versions against the official Zammad advisory and GitHub release notes — do not rely on third-party summaries. Watch CISA KEV for additions and apply any stated federal remediation deadlines as your own benchmark.
  2. Assume breach on internet-facing Zammad instances. Run the triage script and hunts above. Review application logs (/opt/zammad/log/production.log), reverse proxy access logs, and auth logs for the past 30+ days for anomalous API calls, unexpected session creation, and admin account activity.
  3. Rotate all credentials the Zammad host could touch: Zammad admin and agent accounts, API tokens, email channel credentials (IMAP/SMTP), LDAP bind accounts, webhook secrets, and any third-party integrations. DIVD's attacker exfiltrated data and pivoted — assume yours would too.
  4. If you find evidence of compromise, treat connected systems as exposed and initiate your IR process. A ticket system is a directory of your infrastructure, your customers, and your open problems.

Short-term (this week):

  1. Reduce the blast radius of the service account. Remove the zammad user from sudoers entirely, run background workers and the web process under least-privilege systemd hardening (NoNewPrivileges=true, ProtectSystem=strict, PrivateTmp=true), and confirm nothing in the Zammad directory tree is writable by the service user and executed by root-owned jobs.
  2. Put Zammad behind authentication-gated access where feasible. SSO with MFA at the reverse proxy or an IdP-aware proxy kills unauthenticated exploitation paths outright. If the portal must be public for customer ticket submission, isolate it on a dedicated host or container with strict egress rules.
  3. Egress filtering: The Zammad host needs SMTP/IMAP, package repos, and upstream updates — nothing else. Deny-all egress by default would have broken the exfiltration and pivot stages of this attack.
  4. Enable and centralize logging: Ship Rails production logs, nginx/Apache access logs, auth.log, and auditd process execution to your SIEM. Deploy the Sigma rules above.

Strategic (this quarter):

  1. Adopt machine-speed containment for internet-facing apps. When exploitation-to-root takes seconds, your detection must be wired to automated response: host isolation, egress block, session revocation. Human-in-the-loop triage is a post-incident luxury for this threat class.
  2. Re-evaluate vuln chaining in risk ratings. A medium web bug plus a medium local misconfiguration equals a critical compromise path. Score chains, not individual findings, in your vulnerability management program.
  3. Segment ticketing/helpdesk infrastructure away from identity systems, production data, and management networks. These systems are attacker magnets precisely because of what they know about you.

Executive Takeaways

  • Attack speed has changed. An AI agent went from zero to root at DIVD in seconds. If your incident response assumes hours of dwell time, your playbook is already obsolete for internet-facing applications.
  • Ticketing systems are crown-jewel adjacent. They hold PII, credentials, infrastructure maps, and — for security organizations — vulnerability intelligence. Classify and defend them accordingly.
  • Zammad admins: patch now, hunt now, rotate credentials. Do not wait for formal CVE publication to act on a confirmed in-the-wild zero-day chain.
  • Defense-in-depth beat the attacker, eventually. DIVD caught and stopped the pivot. Egress controls, segmentation, and monitoring are what turn a breach into a bounded incident.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.