The Dutch Institute for Vulnerability Disclosure (DIVD) — an organization whose entire mission is finding and disclosing vulnerabilities before criminals abuse them — has disclosed that its own network was breached. The entry point was a chain of two unpatched vulnerabilities in the open-source Zammad ticketing system, and according to DIVD's reporting, the intrusion involved AI-driven attack techniques that accelerated the adversary's ability to operate inside the environment.
Let that sink in for a moment. A volunteer-run vulnerability disclosure organization — staffed by people who live and breathe this work — was compromised through a helpdesk application. If it can happen to DIVD, the assumption that your ticketing platform is a low-risk internal tool needs to die today.
This post breaks down what defenders can take away from the disclosure, why ticketing systems are now tier-one attack surface, how AI-assisted intrusion tradecraft changes your dwell-time assumptions, and concrete detection and hardening guidance you can apply to Zammad deployments immediately.
Why Ticketing Systems Are a High-Value Target
I've led IR engagements where the ticketing system was the pivot point, and the pattern is always the same: nobody treats it as critical infrastructure until it's the reason the attacker owned the domain. Consider what a platform like Zammad actually holds:
- Credential material in plain text. Users routinely paste passwords, API keys, VPN configs, and screenshots of secrets into tickets.
- A directory of your organization. Agents, customers, escalation chains, and internal procedures are all enumerated in one place.
- A trusted communication channel. An attacker with agent-level access can send password-reset links, 'updated payment instructions,' or malware-laden 'attachments' from an address every recipient trusts.
- An integration hub. Zammad connects to LDAP/Active Directory, email (IMAP/SMTP), Slack, GitLab, CTI systems, and more. Those stored integration credentials are lateral-movement gold.
DIVD's case adds a sharper edge: the institute's tickets presumably contained vulnerability reports and disclosure coordination details — intelligence that is directly weaponizable against other organizations. If your SOC, IR team, or IT department coordinates sensitive work through Zammad, assume an attacker reads it as a target list.
Technical Analysis
The Attack Chain
Based on DIVD's disclosure, the intrusion required chaining two separate vulnerabilities in Zammad. Public technical details and CVE assignments were still pending at the time of reporting — DIVD and Zammad's maintainers are coordinating disclosure, and defenders should watch the official Zammad security advisories page for identifiers as they are published.
What we know from a defender's perspective:
- The flaws were unpatched at time of exploitation (zero-days). There was no vendor fix available when DIVD was hit. This means signature- and patch-based defenses alone would not have prevented entry — behavioral detection and egress monitoring were the safety net.
- Two bugs were chained. Single-vulnerability exploitation is opportunistic; chaining implies a deliberate, capable actor who understood Zammad's architecture — likely an initial access primitive (e.g., authentication bypass or unauthenticated input handling flaw) combined with a second flaw for code execution, session hijacking, or privilege escalation.
- AI-driven techniques were used during the breach. This is the detail that should recalibrate your threat model. Based on what we're seeing across the industry in 2025–2026, 'AI-driven' in practice means LLM-assisted reconnaissance and exploit refinement, automated analysis of stolen data at machine speed, and rapid generation of context-aware social engineering content. The practical effect: attacker dwell time compresses. Actions that took a human operator days — parsing ticket contents, identifying high-value targets, crafting convincing internal phishing — can now happen in hours or minutes.
Affected Products and Platforms
- Product: Zammad open-source ticketing/helpdesk system (self-hosted deployments)
- Deployment models affected: Package-based installs (DEB/RPM), Docker Compose deployments, and source installs. SaaS instances hosted by Zammad GmbH are patched by the vendor — confirm with your provider.
- Versions: Specific vulnerable version ranges will be confirmed in the coordinated advisory. Treat any Zammad instance not updated to the latest stable release as potentially exposed until the advisory lands.
- Exposure: Any Zammad instance reachable from the internet — and many are, by design, since customer-facing ticket portals are the product's core function.
Exploitation Status
- Confirmed in-the-wild exploitation: Yes — DIVD's breach is a confirmed real-world compromise, not a theoretical exercise.
- Public PoC: Not publicly released at time of writing (coordinated disclosure in progress). Expect PoCs and mass-scanning to follow quickly once patches ship — this is the standard exploitation economics of a publicized zero-day.
- CISA KEV: Monitor the KEV catalog; given confirmed exploitation, a listing is plausible once CVEs are assigned.
Critical implication: The window between patch release and mass exploitation of web-facing applications is now measured in hours. When Zammad publishes the fix, treat it as an emergency change, not a routine update.
Detection & Response
Because the exact CVE mechanics are not yet public, the detection strategy below targets behavioral indicators common to web-application compromise chains as they manifest on a Zammad host: the application process spawning unexpected children, webshell artifacts in the web root, suspicious API session abuse, and outbound connections from a host that should have a tightly bounded egress profile. These rules are tuned for the Zammad technology stack (Ruby on Rails application server, PostgreSQL, Elasticsearch, Nginx/Apache reverse proxy) and should be validated in your environment before broad deployment.
Sigma Rules
---
title: Zammad Application Process Spawning Shell or Command Interpreter
id: 3f9c2e71-8a4d-4b1e-9f67-2c5d8e1a7b3c
status: experimental
description: Detects the Zammad Rails application server, web server worker, or background job process spawning shells or command interpreters, consistent with post-exploitation activity following web application compromise such as the DIVD breach via Zammad zero-days.
references:
- https://www.bleepingcomputer.com/news/security/divd-says-zammad-zero-days-enabled-ai-driven-network-breach/
- https://attack.mitre.org/techniques/T1059/
- https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/04/06
tags:
- attack.initial_access
- attack.execution
- attack.t1190
- attack.t1059.004
logsource:
category: process_creation
product: linux
detection:
selection_parent:
ParentImage|endswith:
- '/ruby'
- '/puma'
- '/rails'
- '/nginx'
- '/apache2'
- '/httpd'
- '/sidekiq'
selection_parent_user:
User:
- 'zammad'
- 'www-data'
- 'nginx'
selection_child:
Image|endswith:
- '/bash'
- '/sh'
- '/dash'
- '/zsh'
- '/python'
- '/python3'
- '/perl'
- '/curl'
- '/wget'
- '/nc'
- '/ncat'
- '/netcat'
- '/base64'
condition: (selection_parent or selection_parent_user) and selection_child
falsepositives:
- Zammad scheduler or import jobs legitimately invoking curl or shell wrappers for integration tasks - baseline and exclude known job patterns
- Administrative troubleshooting directly on the host
level: high
---
title: Webshell or Unexpected Executable Written to Zammad Web Directories
id: 8b4e1d92-6c3f-4a58-b2e9-7d1c4f6a9e52
status: experimental
description: Detects creation of script or executable files in Zammad public/web-served directories, a common persistence and post-exploitation artifact after exploiting web application vulnerabilities as seen in the DIVD breach.
references:
- https://www.bleepingcomputer.com/news/security/divd-says-zammad-zero-days-enabled-ai-driven-network-breach/
- 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/'
- '/var/www/zammad/public/'
- '/zammad/public/'
- '/tmp/'
- '/dev/shm/'
selection_ext:
TargetFilename|endswith:
- '.php'
- '.rb'
- '.py'
- '.pl'
- '.jsp'
- '.sh'
- '.elf'
condition: all of selection_*
falsepositives:
- Legitimate Zammad upgrades and asset compilation - correlate with change windows and exclude package manager writers (dpkg, rpm, docker)
level: high
---
title: Zammad PostgreSQL Database Bulk Read or Dump Activity
id: 5c7a3f18-2e9b-4d47-a1c6-9b8d3e5f2047
status: experimental
description: Detects database dump utilities or interactive SQL clients executed against the Zammad PostgreSQL database outside of backup windows, indicating potential bulk theft of ticket contents including credentials and sensitive reports.
references:
- https://www.bleepingcomputer.com/news/security/divd-says-zammad-zero-days-enabled-ai-driven-network-breach/
- https://attack.mitre.org/techniques/T1005/
- https://attack.mitre.org/techniques/T1213/
author: Security Arsenal
date: 2026/04/06
tags:
- attack.collection
- attack.t1005
- attack.t1213
logsource:
category: process_creation
product: linux
detection:
selection:
Image|endswith:
- '/pg_dump'
- '/pg_dumpall'
- '/psql'
filter_backup:
CommandLine|contains:
- 'cron'
- 'backup'
- '/usr/bin/zammad-backup'
condition: selection and not filter_backup
falsepositives:
- Scheduled Zammad backup jobs - exclude via known backup script paths and service accounts after baselining
level: medium
KQL — Microsoft Sentinel / Defender
The following query hunts for Zammad-related post-exploitation behaviors in environments ingesting Linux Syslog/auditd data into Sentinel, or where Defender for Endpoint covers the Zammad host. Adjust table and field mappings to your ingestion pipeline.
// Hunt 1: Shell or download tooling spawned under Zammad/web service accounts
// Requires Syslog (process exec via auditd) or DeviceProcessEvents if MDE-on-Linux is deployed
let suspiciousChildren = dynamic(["/bin/bash","/bin/sh","/usr/bin/curl","/usr/bin/wget","/usr/bin/python3","/bin/nc","/usr/bin/perl"]);
let zammadAccounts = dynamic(["zammad","www-data","nginx"]);
Syslog
| where Facility =~ "auth" or ProcessName has_any ("ruby","puma","rails","nginx","bash","sh","curl","wget")
| where SyslogMessage has_any (zammadAccounts) and SyslogMessage has_any (suspiciousChildren)
| project TimeGenerated, Computer, ProcessName, SyslogMessage, HostIP
| order by TimeGenerated desc;
// Hunt 2: Anomalous outbound connections from Zammad hosts to rare external destinations
// Useful for catching C2 or exfiltration staged from a compromised ticketing server
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessAccountName in~ ("zammad","www-data","nginx","postgres")
| where RemoteIPType == "Public"
| where RemoteUrl !has_any ("zammad.com","rubygems.org","elastic.co","github.com") // allow-list known update/package destinations
| summarize ConnectionCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
by DeviceName, InitiatingProcessName, RemoteIP, RemoteUrl, RemotePort
| where ConnectionCount < 50 // rare destinations are higher-signal than high-volume CDN traffic
| order by FirstSeen asc;
// Hunt 3: Zammad API abuse - bulk session creation or ticket export from a single source
// Requires Zammad application/access logs ingested via CommonSecurityLog or custom table (ZammadEvents_CL)
CommonSecurityLog
| where TimeGenerated > ago(7d)
| where RequestURL has_any ("/api/v1/tickets","/api/v1/sessions","/api/v1/users")
| summarize Requests = count(), DistinctURIs = dcount(RequestURL)
by SourceIP, RequestMethod, bin(TimeGenerated, 1h)
| where Requests > 200 or DistinctURIs > 100 // tune thresholds to your environment baseline
| order by Requests desc;
Velociraptor VQL
-- Hunt: Identify suspicious child processes spawned by Zammad application stack
-- Deploy as a hunt across Zammad servers to catch web-app compromise post-exploitation
SELECT Pid, Ppid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE Username =~ '(zammad|www-data|nginx)'
AND (
Exe =~ '(bash|sh|dash|python|perl|curl|wget|nc|ncat)$'
OR CommandLine =~ '(base64\s+-d|/dev/tcp/|curl\s+http|wget\s+http|chmod\s+\+x)'
)
-- Hunt: Webshell-style artifacts dropped in Zammad public or temp directories
SELECT FullPath, Size, Mtime, Ctime, Mode
FROM glob(globs=[
'/opt/zammad/public/**/*.php',
'/opt/zammad/public/**/*.sh',
'/opt/zammad/public/**/*.py',
'/var/www/zammad/public/**/*.php',
'/tmp/*.elf',
'/dev/shm/*'
])
WHERE NOT IsDir
ORDER BY Mtime DESC
-- Hunt: Outbound connections from the Zammad host process context
SELECT Pid, Name, Path, Status,
Laddr.IP AS LocalIP, Laddr.Port AS LocalPort,
Raddr.IP AS RemoteIP, Raddr.Port AS RemotePort
FROM netstat()
WHERE Status =~ 'ESTAB'
AND Name =~ '(ruby|puma|rails|nginx|bash|sh|curl|wget|python)'
AND RemoteIP !~ '^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|127\.)'
Verification and Hardening Script
#!/bin/bash
# zammad-exposure-audit.sh
# Defensive audit for self-hosted Zammad instances - run on the Zammad host
# Validates version, exposure, suspicious artifacts, and recent anomalous activity
set -euo pipefail
echo "=== [1] Zammad version and patch level ==="
if command -v dpkg &>/dev/null; then
dpkg -l zammad 2>/dev/null | tail -1
elif command -v rpm &>/dev/null; then
rpm -q zammad 2>/dev/null || echo "zammad rpm not found"
fi
if docker ps --format '{{.Names}}' 2>/dev/null | grep -qi zammad; then
echo "Docker deployment detected - image tags:"
docker ps --format '{{.Names}} {{.Image}}' | grep -i zammad
fi
echo -e "\n=== [2] Internet exposure check - listening services ==="
ss -tulpn 2>/dev/null | grep -E ':(80|443|3000|6042)\s' || echo "No web ports found listening"
echo -e "\n=== [3] Suspicious files in Zammad public directory (last 30 days) ==="
find /opt/zammad/public /var/www/zammad/public -type f \
\( -name '*.php' -o -name '*.sh' -o -name '*.py' -o -name '*.pl' -o -name '*.elf' \) \
-mtime -30 -exec ls -la {} \; 2>/dev/null || echo "No suspicious files found"
echo -e "\n=== [4] Shell/command execution under zammad or www-data (audit log) ==="
if command -v ausearch &>/dev/null; then
ausearch -ts recent -i 2>/dev/null | grep -E '(zammad|www-data)' | \
grep -E '(bash|/bin/sh|curl|wget|python|perl|nc )' | tail -50 || echo "No matching audit events"
else
echo "ausearch not available - install auditd for process auditing"
fi
echo -e "\n=== [5] Recent outbound connections from Zammad processes ==="
ss -tnp state established 2>/dev/null | grep -E '(ruby|puma|rails|nginx)' | head -30 || echo "None found"
echo -e "\n=== [6] Zammad user accounts with admin role (review for rogue agents) ==="
echo "Run manually inside Zammad: zammad run rails r \"User.joins(:roles).where(roles: {name: 'Admin'}).pluck(:login, :email, :last_login)\""
echo -e "\n=== [7] Failed authentication spikes in production log (possible probing) ==="
if [ -f /opt/zammad/log/production.log ]; then
grep -ci 'failed' /opt/zammad/log/production.log 2>/dev/null || true
grep -i 'failed\|unauthorized' /opt/zammad/log/production.log 2>/dev/null | tail -20
fi
echo -e "\nAudit complete. Cross-reference any findings against change records and escalate anomalies to IR."
Remediation
Immediate Actions (Today)
- Confirm your Zammad version and update to the latest stable release. Package deployments:
apt update && apt install --only-upgrade zammadoryum update zammad. Docker deployments: pull the latestzammad/zammad-docker-composeimages and recreate containers. Verify post-upgrade with the version check in the audit script above. Zammad backports security fixes to supported stable branches — do not sit on an EOL major version. - Monitor the official advisory channels for the coordinated disclosure of the two exploited vulnerabilities, and apply the specific fix the moment it ships: Zammad security advisories (https://zammad.com/en/product/security and https://github.com/zammad/zammad/security/advisories), and the DIVD disclosure at https://csirt.divd.nl. Given confirmed in-the-wild exploitation, treat the patch as an emergency change with same-day deployment.
- Reduce internet exposure. If your Zammad instance does not absolutely require public access, place it behind a VPN or an authenticated reverse proxy (SSO/OIDC front-door). If a public portal is required, enforce a WAF rule set and restrict agent/admin paths (
/api/v1/*sensitive endpoints, admin UI) to known IP ranges.
Investigation and Containment (If You Suspect Compromise)
- Rotate every credential Zammad touches. This includes LDAP/AD bind accounts, IMAP/SMTP credentials, API tokens for integrations (Slack, GitLab, CTI), and OAuth client secrets. Then force password resets for all agent accounts and revoke all active sessions.
- Hunt before you patch. Preserve
/opt/zammad/log/production.log, web server access logs, PostgreSQL logs, and auditd data before upgrading, since package updates can rotate or overwrite logs. Run the Sigma, KQL, and VQL content above; look specifically for new admin accounts, unexpected API sessions, ticket exports, and outbound connections from the host. - Review ticket contents as exfiltration scope. If compromise is confirmed, your breach-notification analysis must include what was stored in tickets — credentials, customer PII, and (for organizations like DIVD) vulnerability reports. Treat pasted secrets in tickets as compromised by definition.
Strategic Hardening (This Quarter)
- Segment the ticketing host. Zammad should sit in a DMZ-tier segment with egress filtering that permits only required destinations (mail relay, package repos, upstream integrations). A ticketing server that can initiate arbitrary outbound connections is a ticketing server that can exfiltrate.
- Enable MFA for all agent accounts and integrate Zammad with your IdP (SAML/OIDC) rather than local passwords. Disable or tightly control the API token surface; tokens are bearer credentials and bypass interactive MFA.
- Deploy auditd with process-execution rules on the host and forward to your SIEM — the Sigma rules above depend on it. A web server with no process telemetry is invisible to your SOC.
- Recalibrate dwell-time assumptions for AI-assisted adversaries. DIVD's experience reflects the 2025–2026 reality: LLM-assisted operators compress reconnaissance-to-action timelines dramatically. Your detection SLAs and escalation paths need to assume hours, not days. Automated containment triggers (host isolation on high-confidence detections) matter more than ever.
- Adopt a 'sensitive work off the ticketing system' policy. Vulnerability reports, IR coordination, and credential exchange belong in purpose-built, access-controlled systems — not in a customer-facing web application.
The Meta-Lesson
DIVD did the right thing: they detected the intrusion, investigated, and disclosed publicly — exactly what they ask of the organizations they notify. The uncomfortable takeaway for the rest of us is twofold. First, security tooling and administrative applications are attack surface, full stop — the helpdesk, the vulnerability scanner console, the SIEM itself. Second, the defender's response to zero-day reality is not despair; it's architecture. Segmentation, egress control, behavioral detection, and aggressive patching cadences are what convert an unpatched-vulnerability event from 'network breach' into 'contained incident.'
If you run Zammad today, start with step 1 and step 4. Then book time to work the rest of the list.
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.