Back to Intelligence

CVE-2026-76060: ZoneMinder OS Command Injection via Event Export — Detection and Remediation Guide

SA
Security Arsenal Team
August 25, 2026
10 min read

CISA published ICS advisory ICSA-26-237-02 disclosing CVE-2026-76060, an authenticated OS command injection vulnerability in ZoneMinder — the open-source video surveillance platform deployed worldwide across homes, small businesses, and critical infrastructure facilities. The flaw carries a CVSS v3 score of 8.8 (High) and affects ZoneMinder versions 1.37.48 through 1.38.3. Successful exploitation grants an attacker arbitrary command execution as the web server user — and the advisory language warns the chain can result in full code execution on the host.

ZoneMinder deployments deserve serious attention from defenders for three reasons. First, these systems are frequently exposed directly to the internet so administrators can view camera feeds remotely — Shodan and Censys consistently show thousands of reachable instances. Second, a compromised NVR/CCTV host is a dream foothold: it sits on internal networks, often with broad east-west visibility into camera VLANs, IoT segments, and sometimes bridged corporate networks. Third, CCTV infrastructure is notoriously under-patched — it falls into the gap between IT and physical security teams, and nobody owns the patch cycle.

If you run ZoneMinder anywhere in your environment, treat this as a priority patch. If you don't think you run ZoneMinder, go verify — shadow deployments of open-source surveillance software are common in facilities and warehouse environments.

Technical Analysis

Affected Products and Versions

AttributeDetail
VendorZoneMinder
ProductZoneMinder (open-source CCTV/NVR platform)
Affected versions1.37.48, 1.38.3 (per ICSA-26-237-02)
CVECVE-2026-76060
CVSS v38.8 (High)
CWECWE-78 — Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
DeploymentWorldwide; Information Technology sector flagged; vendor HQ in the United States

How the Vulnerability Works

The flaw lives in ZoneMinder's event export functionality. The exportFile HTTP request parameter is passed unsanitized into a shell command — a textbook CWE-78. An attacker who submits a crafted request to the export endpoint can inject shell metacharacters (e.g., ;, |, &&, backticks, $( ) command substitution) into the exportFile value, causing the underlying shell invoked by the PHP/web layer to execute arbitrary commands alongside — or instead of — the intended export operation.

Key exploitation characteristics from a defender's perspective:

  • Authentication required, but don't let that lower your guard. "Authenticated" in a ZoneMinder context frequently means default, weak, or shared credentials. ZoneMinder has a long history of default-credential deployments, and many instances run with authentication effectively disabled or with widely known admin passwords. An 8.8 CVSS score reflects the network-attack vector and low complexity once any valid session exists.
  • Execution context: the web server user. Commands execute as the account running Apache/Nginx (typically www-data or apache). That's enough to read ZoneMinder's configuration (including database credentials in zm.conf), write web shells into the webroot, stage payloads, and pivot. From there, privilege escalation on an unpatched CCTV box is usually trivial — these hosts run outdated kernels, excess sudo rules, and broad file permissions.
  • Attack chain of concern: reconnaissance → valid session (default/stolen creds) → crafted export request with injected exportFile → command execution as web user → web shell or reverse shell → credential harvesting from ZoneMinder DB config → lateral movement into camera/IoT/corporate segments.

Exploitation Status

As of the advisory publication, CISA has not added CVE-2026-76060 to the Known Exploited Vulnerabilities (KEV) catalog, and there are no confirmed reports of in-the-wild exploitation in the advisory text. However, OS command injection in internet-facing web applications is one of the most rapidly weaponized vulnerability classes — the window between public disclosure and mass scanning for this bug class is typically measured in days, not months. Given ZoneMinder's exposure profile, treat exploitation as imminent and patch accordingly. Monitor the CISA KEV catalog for status changes.

Detection & Response

The highest-fidelity detection signal for this vulnerability class is the web server process spawning shell interpreters and system utilities — that is almost never legitimate on a ZoneMinder host outside of the application's own narrow behaviors, and injected commands will ride exactly that path. A secondary signal is metacharacter-bearing request parameters targeting ZoneMinder endpoints in web/proxy logs.

YAML
---
title: ZoneMinder Web Server Spawning Shell Interpreter - Possible CVE-2026-76060 Exploitation
id: 3f7a2b91-6c4d-4e58-9a21-8b0c1d2e3f4a
status: experimental
description: Detects the Apache/Nginx/PHP worker process spawning a shell interpreter or common post-exploitation utility on a Linux host. Consistent with OS command injection in web applications such as CVE-2026-76060 in ZoneMinder's event export functionality, where the exportFile parameter is passed unsanitized to a shell.
references:
  - https://www.cisa.gov/news-events/ics-advisories/icsa-26-237-02
  - https://attack.mitre.org/techniques/T1059/004/
author: Security Arsenal
date: 2026/08/25
tags:
  - attack.execution
  - attack.t1059.004
  - attack.initial_access
  - attack.t1190
logsource:
  category: process_creation
  product: linux
detection:
  selection_parent:
    ParentImage|endswith:
      - '/apache2'
      - '/httpd'
      - '/php-fpm'
      - '/nginx'
  selection_child:
    Image|endswith:
      - '/sh'
      - '/bash'
      - '/dash'
      - '/curl'
      - '/wget'
      - '/nc'
      - '/ncat'
      - '/netcat'
      - '/python'
      - '/python3'
      - '/perl'
      - '/base64'
  filter_zoneminder_legit:
    CommandLine|contains:
      - 'zmaudit'
      - 'zmfilter'
      - '/usr/bin/zm'
  condition: selection_parent and selection_child and not filter_zoneminder_legit
falsepositives:
  - Legitimate ZoneMinder maintenance scripts invoked through the web UI; tune the filter to your local zm* binary paths
level: high
---
title: Web Request to ZoneMinder Export Endpoint With Shell Metacharacters
id: 8c1e4d62-3b7a-4f09-b6e5-2a9c0d1e4f5b
status: experimental
description: Detects HTTP requests to ZoneMinder event export functionality containing shell metacharacters or command substitution patterns in the exportFile parameter, indicating attempted exploitation of CVE-2026-76060 OS command injection.
references:
  - https://www.cisa.gov/news-events/ics-advisories/icsa-26-237-02
  - https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/08/25
tags:
  - attack.initial_access
  - attack.t1190
logsource:
  category: webserver
  product: linux
detection:
  selection_param:
    cs-uri-query|contains:
      - 'exportFile='
  selection_injection:
    cs-uri-query|contains:
      - '%3B'
      - '%7C'
      - '%26%26'
      - '%24%28'
      - '%60'
      - ';'
      - '|'
      - '&&'
      - '$('
      - '`'
      - '/bin/'
      - 'curl%20'
      - 'wget%20'
  condition: selection_param and selection_injection
falsepositives:
  - Rare; legitimate exportFile values are filenames and should not contain shell metacharacters. Validate against URL-encoded filenames in your environment.
level: high
KQL — Microsoft Sentinel / Defender
// Hunt for web server processes spawning shells or downloaders on ZoneMinder hosts
// Works against Defender for Endpoint (if deployed on Linux) and Syslog/CEF-ingested process events
let shellTools = dynamic(["/bin/sh", "/bin/bash", "/bin/dash", "/usr/bin/curl", "/usr/bin/wget", "/bin/nc", "/usr/bin/ncat", "/usr/bin/python3", "/usr/bin/perl", "/usr/bin/base64"]);
let webParents = dynamic(["apache2", "httpd", "php-fpm", "nginx"]);
union isfuzzy=true
    (DeviceProcessEvents
    | where InitiatingProcessFileName in~ (webParents)
    | where FileName in~ (shellTools) or ProcessCommandLine has_any ("curl ", "wget ", "base64 -d", "$(", "`/bin/")
    | project Timestamp, DeviceName, InitiatingProcessFileName, FileName, ProcessCommandLine, InitiatingProcessAccountName),
    (Syslog
    | where SyslogMessage has_any ("exportFile=", "cmd=sh", "cmd=/bin/sh")
    | where SyslogMessage has_any (";", "|", "&&", "$(", "/bin/")
    | project TimeGenerated, Computer, ProcessName, SyslogMessage)
| order by Timestamp desc
VQL — Velociraptor
-- Hunt for shell/downloader processes parented to the web server (ZoneMinder cmd injection - CVE-2026-76060)
SELECT Pid, Ppid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE Ppid IN (
    SELECT Pid FROM pslist()
    WHERE Name =~ 'apache2|httpd|php-fpm|nginx'
)
AND (Name =~ '^(sh|bash|dash|curl|wget|nc|ncat|python3?|perl|base64)$'
     OR CommandLine =~ '/bin/(sh|bash)|curl http|wget http|base64 -d')
Bash / Shell
#!/bin/bash
# CVE-2026-76060 ZoneMinder exposure check and remediation helper
# Run on ZoneMinder hosts. Requires root for package operations.
set -euo pipefail

echo "=== ZoneMinder CVE-2026-76060 Exposure Check ==="

# 1. Identify installed ZoneMinder version
echo "[+] Installed ZoneMinder package version:"
if command -v dpkg >/dev/null 2>&1; then
    dpkg -l | grep -i zoneminder || echo "    ZoneMinder not installed via dpkg"
elif command -v rpm >/dev/null 2>&1; then
    rpm -qa | grep -i zoneminder || echo "    ZoneMinder not installed via rpm"
fi

# 2. Check running version from the web config (if accessible)
echo "[+] Version reported by application (if web server running):"
curl -sk --max-time 5 http://localhost/zm/index.php 2>/dev/null | grep -oiE 'v1\.(37|38)\.[0-9]+' | head -1 || echo "    Unable to determine web version"

# 3. Flag vulnerable versions
echo "[+] Vulnerable versions per ICSA-26-237-02: 1.37.48, 1.38.3"
echo "    ACTION: Update to the latest ZoneMinder release (>1.38.3) immediately."

# 4. Update via package manager (Debian/Ubuntu example - adjust for your repo)
# apt-get update && apt-get install --only-upgrade zoneminder -y

# 5. Hunt for signs of prior exploitation: web server spawning shells
echo "[+] Recent suspicious child processes of web server (last 24h, auditd):"
ausearch -ts recent -k exec 2>/dev/null | grep -iE 'ppid.*(apache2|httpd|php-fpm)' | grep -iE '(\/bin\/sh|\/bin\/bash|curl|wget|nc )' | tail -20 || echo "    auditd key 'exec' not configured or no hits"

# 6. Check web logs for exportFile injection attempts
echo "[+] Scanning Apache logs for exportFile metacharacter injection:"
grep -hE 'exportFile=[^&]*(;|%3B|\||%7C|&&|%26%26|\$\(|%24%28|`|/bin/)' /var/log/apache2/access.log* /var/log/httpd/access_log* 2>/dev/null | tail -20 || echo "    No injection attempts found in available logs"

# 7. Check for dropped web shells in the ZoneMinder webroot
echo "[+] Recently modified .php files in webroot (possible web shells):"
find /usr/share/zoneminder /var/www -name '*.php' -mtime -14 2>/dev/null | head -20 || echo "    None found"

# 8. Network exposure check - is ZoneMinder reachable externally?
echo "[+] Listening web ports (confirm firewall restricts to trusted sources):"
ss -tlnp | grep -E ':(80|443)\b' || echo "    No web listeners found"

echo "=== Check complete. Review findings and apply updates. ==="

Remediation

  1. Update ZoneMinder immediately. Upgrade all instances past the affected range (1.37.48 / 1.38.3) to the latest stable release from the official ZoneMinder project (zoneminder.com) or your distribution's maintained package repository. Verify the installed version post-patch with dpkg -l | grep zoneminder or rpm -qa | grep zoneminder.
  2. Remove internet exposure. ZoneMinder should never be directly reachable from the public internet. Place it behind a VPN, reverse proxy with strong authentication (SSO/MFA), or IP allowlist. This single control neutralizes the "authenticated" prerequisite for external attackers.
  3. Enforce strong, unique authentication. Audit all ZoneMinder user accounts, rotate credentials, eliminate default passwords, and disable unused accounts. Enable ZoneMinder's built-in authentication (ZM_OPT_USE_AUTH) if it is off.
  4. Restrict network egress and segmentation. Place NVR hosts on an isolated camera/IoT VLAN with no direct path to corporate segments. Block outbound internet access from the ZoneMinder host except to required update repositories — this breaks reverse shells and payload staging even if injection succeeds.
  5. Apply least privilege to the web tier. Confirm the web server runs as a low-privilege user, remove unnecessary sudo rights for www-data/apache, and consider SELinux/AppArmor profiles confining the web server process.
  6. Hunt before and after patching. Run the detection content above across your ZoneMinder hosts and web logs. Patching closes the door; it does not evict an attacker who already walked through it. Review logs for exportFile requests containing shell metacharacters and inspect the webroot for unexpected PHP files.
  7. Monitor authoritative sources. Track CISA ICS advisory ICSA-26-237-02 and the CISA KEV catalog for updates to exploitation status, and subscribe to the ZoneMinder project's release channels for the patched build notification.

The recurring lesson from CCTV/NVR vulnerabilities is consistent: physical-security infrastructure is IT infrastructure, and it must be inventoried, segmented, monitored, and patched with the same rigor as any other internet-reachable asset. If ZoneMinder (or any NVR platform) isn't in your vulnerability management scope today, this advisory is your cue to fix that.

Related Resources

Security Arsenal Red Team Services AlertMonitor Platform Book a SOC Assessment pen-testing Intel Hub

Is your security operations ready?

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