diff --git a/integrations/cisco_ftd/README.md b/integrations/cisco_ftd/README.md new file mode 100644 index 0000000..4843b96 --- /dev/null +++ b/integrations/cisco_ftd/README.md @@ -0,0 +1,155 @@ +# Cisco FTD Access-List Deny Decoders - Wazuh Integration + +## Table of Contents + +* [Introduction](#introduction) +* [Prerequisites](#prerequisites) +* [Installation and Configuration](#installation-and-configuration) + * [Decoder Placement Constraint](#decoder-placement-constraint) + * [Installing the Decoders (Drop-In Replacement)](#installing-the-decoders-drop-in-replacement) + * [Alternative: Merge Only the Added Blocks](#alternative-merge-only-the-added-blocks) +* [Rules](#rules) + +### Introduction + +This integration extends the stock Wazuh Cisco FTD decoders so that access-list +deny events (message **106023**) with the standard `%FTD-` prefix decode fully. +Blocked and denied firewall traffic otherwise decodes inconsistently, so some +fields are missing or truncated on the resulting alerts. + +Two related gaps cause this: interface names containing hyphens (`LAN-INT`, +`DMZ-INT`) that a `\w+` pattern cannot match, and ICMP denies that carry no port +and so do not fit a port-bearing pattern. + +**This integration ships decoders only.** The stock Cisco FTD rules already +alert on these messages; the improved decoding simply gives those alerts +complete, correctly-separated fields (`cisco.access_group`, `cisco.icmp_type`, +hyphenated interfaces, ports). See [Rules](#rules). + +> The `%FTD-session-` prefix variant is handled by the separate +> **cisco_ftd_session** integration. Switch and router authentication is handled +> by **cisco_ios**. + +### Prerequisites + +- A Wazuh manager receiving syslog from Cisco FTD appliances, over `` + syslog or a log collector on an agent. +- Sufficient privileges on the manager to edit files under `/var/ossec/`. +- No third-party software or Python dependencies. This integration is decoder + XML only. Installing it as a drop-in replacement under `etc/decoders/` (the + recommended path below) is upgrade-safe. + +### Installation and Configuration + +#### Decoder Placement Constraint + +**Wazuh commits the first child decoder whose `` matches, even when +its `` then fails to extract anything.** A child placed after a matching +sibling never runs, and the stock `cisco-ftd` parent has generic children, some +without a ``, that would otherwise claim 106023 events first. + +In the file shipped here this is **already handled**: `cisco-ftd-acl-deny` and +`cisco-ftd-acl-deny-icmp` sit immediately after the parent, above every generic +child. You only need to preserve that ordering yourself if you hand-merge the +blocks (see the alternative below). + +#### Installing the Decoders (Drop-In Replacement) + +`ruleset/decoders/cisco_ftd_decoders.xml` is a **complete replacement** for the +stock Cisco FTD decoder file: the stock decoder set with the two deny decoders +already merged in at the correct position. Because it keeps the stock decoder +names, the stock Cisco FTD rules keep working against it. + +Confirm the stock decoder filename on your release first (it carries a numeric +prefix), together with the stock rules file that depends on it: + +```bash +ls /var/ossec/ruleset/decoders/ | grep -i cisco-ftd # e.g. 0062-cisco-ftd_decoders.xml +ls /var/ossec/ruleset/rules/ | grep -i cisco-ftd # e.g. 0905-cisco-ftd_rules.xml +``` + +**Order matters.** You cannot just add the replacement alongside the stock +decoder: both define the same parent (`cisco-ftd`), so with the stock file still +present that parent name is duplicated and the manager errors out. A stock +decoder also cannot be excluded while the stock rules that depend on it are +still loaded. So the sequence is: **exclude the stock decoder and its rules +first, then add the replacement decoder, then re-include the rules.** + +**From the Wazuh dashboard** (recommended for Wazuh Cloud and other managed or +as-is deployments): + +1. **Exclude the stock decoder and its rules.** Server Management -> Settings -> + Edit configuration; in the `` block add both exclusions, then save + and restart the manager: + + ```xml + + + ruleset/decoders + ruleset/rules + ruleset/decoders/0062-cisco-ftd_decoders.xml + ruleset/rules/0905-cisco-ftd_rules.xml + ... + + etc/decoders + etc/rules + + ``` + +2. **Add the replacement decoder.** Server Management -> Decoders -> Manage + decoders files -> Add new decoders file. Name it `cisco_ftd_decoders.xml`, + paste the contents of this integration's decoder file, and save (stored under + `etc/decoders/`). Restart the manager. With the stock decoder excluded there + is no duplicate `cisco-ftd` parent. +3. **Re-include the rules.** Back in Settings, remove the `` line + so the stock FTD rules load again - this time against your replacement + decoder - keeping the ``. Save and restart. + +**From the backend (CLI):** the same three phases, editing +`/var/ossec/etc/ossec.conf` and the filesystem directly: + +1. Add both `` and `` to the `` block, + then restart. +2. Copy the replacement decoder in, then restart: + + ```bash + cp ruleset/decoders/cisco_ftd_decoders.xml /var/ossec/etc/decoders/ + chown wazuh:wazuh /var/ossec/etc/decoders/cisco_ftd_decoders.xml + chmod 660 /var/ossec/etc/decoders/cisco_ftd_decoders.xml + ``` +3. Remove the `` (keep the ``), then restart: + + ```bash + systemctl restart wazuh-manager + # or: /var/ossec/bin/wazuh-control restart + ``` + +Trade-off: your copy no longer receives upstream decoder improvements or new +message support. Review it against the stock file after each upgrade, and +re-merge if Wazuh adds FTD decoders you want. + +#### Alternative: Merge Only the Added Blocks + +If you prefer to leave the stock file managed by Wazuh, copy just the two +`cisco-ftd-acl-deny` / `cisco-ftd-acl-deny-icmp` blocks out of the shipped file +and paste them into `/var/ossec/ruleset/decoders/0062-cisco-ftd_decoders.xml`, +immediately after the `cisco-ftd` parent and **above** any generic child. Back +the stock file up first, then restart the manager. This edits the stock file in +place, so no exclusion is needed - but a manager upgrade replaces files under +`/var/ossec/ruleset/`, so the merge must be re-applied afterwards. + +```bash +cp /var/ossec/ruleset/decoders/0062-cisco-ftd_decoders.xml{,.bak} +``` + +### Rules + +**This integration ships no rules.** The stock Wazuh Cisco FTD ruleset +(`0905-cisco-ftd_rules.xml`) already alerts on `%FTD-` messages, including +106023 denies, keyed on the `cisco-ftd` decoder. The decoders here do not change +which alerts fire; they only ensure the fields on those alerts +(`cisco.access_group`, `cisco.icmp_type`/`cisco.icmp_code`, hyphenated +interfaces, separated ports) are complete and correct. + +Nothing extra to install: once the decoder is in place and the manager +restarted, the existing FTD rules pick up the improved fields automatically. diff --git a/integrations/cisco_ftd/ruleset/decoders/cisco_ftd_decoders.xml b/integrations/cisco_ftd/ruleset/decoders/cisco_ftd_decoders.xml new file mode 100644 index 0000000..a6cac39 --- /dev/null +++ b/integrations/cisco_ftd/ruleset/decoders/cisco_ftd_decoders.xml @@ -0,0 +1,440 @@ + + + + + [^%]*%FTD-[0-7]-[^:\s]+[:\s].* + + + + + cisco-ftd + %FTD-\d-106023: \w+ (?:tcp|udp) src + %(FTD)-(\d)-(\d+): (\w+) (\w+) src ([^:\s]+):([^/\s]+)/(\d+) dst ([^:\s]+):([^/\s]+)/(\d+) by access-group "([^"]+)" + product.name, event.severity, event.id, action, protocol, src_interface, srcip, srcport, dst_interface, dstip, dstport, cisco.access_group + + + + + cisco-ftd + %FTD-\d-106023: \w+ icmp src + %(FTD)-(\d)-(\d+): (\w+) (icmp) src ([^:\s]+):(\S+) dst ([^:\s]+):(\S+) \(type (\d+), code (\d+)\) by access-group "([^"]+)" + product.name, event.severity, event.id, action, protocol, src_interface, srcip, dst_interface, dstip, cisco.icmp_type, cisco.icmp_code, cisco.access_group + + + + + cisco-ftd + 2-106001 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+)/(\S+)\sto\s(\S+)/(\S+)\sflags\s(.+)\son\sinterface\s(\S+)) + header, product.name, event.severity, event.id, message, description, src_ip, src_port, dst_ip, dst_port, flags, interface + + + + + cisco-ftd + 5-718060|5-718061 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+):\scontext=(\d+)) + header, product.name, event.severity, event.id, message, description, context_ID + + + + + cisco-ftd + 5-718062 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\(context=(\d+)\)) + header, product.name, event.severity, event.id, message, description, context_ID + + + + + cisco-ftd + 1-106021|1-106022 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?(.+\sfrom\s(\S+)) + header, product.name, event.severity, event.id, message, srcip + + + + + cisco-ftd + 4-401004 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?(Shunned\spacket:\s(\S+)\s=\s(\S+).+) + header, product.name, event.severity, event.id, message, srcip, dstip + + + + + cisco-ftd + 2-106017 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+)\sto\s(\S+)) + header, product.name, event.severity, event.id, message, description, srcip, dstip + + + + + cisco-ftd + 2-106006|2-106007 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+)/(\S+)\sto\s(\S+)/(\S+)) + header, product.name, event.severity, event.id, message, description, srcip, srcport, dstip, dstport + + + + + cisco-ftd + 3-710003|7-710002|7-710005 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((\S+)\s(\w+).+from\s(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)) + header, product.name, event.severity, event.id, message, protocol, action, srcip, srcport, dstinterface, dstip, dstport + + + + + cisco-ftd + 4-106023: \w+ icmp src \S+:\S+ dst + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((\w+)\s(\w+)\ssrc\s(\S+):(\S+)\sdst\s(\S+):(\S+)) + header, product.name, event.severity, event.id, cisco.log, action, protocol, src_interface, srcip, dst_interface, dstip + + + + cisco-ftd + ftd-4-106023: \w+ icmp src \.+ by access-group (\.+) + message + + + + + cisco-ftd + 4-106023 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((\w+)\s(\w+)\ssrc\s(\S+):(\S+)/(\S+)\sdst\s(\S+):(\S+)/(\S+)) + header, product.name, event.severity, event.id, message, action, protocol, src_interface, srcip, srcport, dst_interface, dstip, dstport + + + + + cisco-ftd + 6-106015 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((\w+)\s(\w+)\s.+\sfrom\s(\S+)/(\S+)\sto\s(\S+)/(\S+)\sflags\s(\S+)\son\sinterface\s(\S+)) + header, product.name, event.severity, event.id, message, action, protocol, srcip, srcport, dstip, dstport, flags, interface + + + + + cisco-ftd + 6-308001 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?(.+\(from\s(\d+.\d+.\d+.\d+)\)) + header, product.name, event.severity, event.id, message, srcip + + + + + cisco-ftd + 6-605004|6-605005 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?(Login\s(\S+)\sfrom\s(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)\sfor\suser\s"(\w+)") + header, product.name, event.severity, event.id, message, action, srcip, srcport, interface, dstip, dstport, user + + + + + cisco-ftd + 4-733100 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?(Object\sdrop\srate\s(\d+)\sexceeded.\sCurrent\sburst\srate\sis\s(\S+)\sper\ssecond,\smax\sconfigured\srate\sis\s(\S+);\sCurrent\saverage\srate\sis\s(\S+)\sper\ssecond,\smax\sconfigured\srate\sis\s(\S+);\sCumulative\stotal\scount\sis\s(\S+)) + header, product.name, event.severity, event.id, message, rate_ID, burst_rate, max_burst_rate, average_rate, max_average_rate, cumulative_count + + + + + cisco-ftd + 5-111008 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?(User\s(\S+)\s(\S+)\sthe\s(.+)) + header, product.name, event.severity, event.id, message, username, type, command + + + + + cisco-ftd + 5-502103 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+):\sUname:\s(\S+)\sFrom:\s(\S+)\sTo:\s(\S+)) + header, product.name, event.severity, event.id, message, description, username, from_level, to_level + + + + + cisco-ftd + 3-421001 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+):(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)\sis\sdropped\sbecause\sapplication\shas\sfailed) + header, product.name, event.severity, event.id, message, description, src, src_ip, src_port, dst, dst_ip, dst_port + + + + + cisco-ftd + 3-421007 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+):(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)\sis\sskipped\sbecause\sapplication\shas\sfailed) + header, product.name, event.severity, event.id, message, description, src, src_ip, src_port, dst, dst_ip, dst_port + + + + + cisco-ftd + 3-106014 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\ssrc\s(\S+):(\S+)\sdst\s(\S+):(\S+)\s(\(.+\))) + header, product.name, event.severity, event.id, message, description, src, src_ip, dst, dst_ip, code + + + + + cisco-ftd + 4-500004 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\sfor\sprotocol=(\S+),\sfrom\s(\S+)/(\S+)\sto\s(\S+)/(\S+)) + header, product.name, event.severity, event.id, message, description, protocol, src_ip, src_port, dst_ip, dst_port + + + + + cisco-ftd + 4-313009 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\scode\s(\S+),\sfor\s\S+:(\S+)/(\S+)\s\(\S+\)\sto\s(\S+):(\S+)/(\S+)\s\(\S+\),\sICMP\sid\s(\S+),\sICMP\stype\s(\S+)) + header, product.name, event.severity, event.id, message, description, code, src, src_port, dst, dst_ip, dst_port, icmp_id, icmp_type + + + + + + cisco-ftd + 4-209005 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\s\ssrc\s=\s(\S+),\sdest\s=\s(\S+),\sproto\s=\s(\S+),\sid\s=\s(\S+)) + header, product.name, event.severity, event.id, message, description, src, dst, protocol, fragment_id + + + + + cisco-ftd + 6-305012 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+):(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)\sduration\s(\d+:\d+:\d+)) + header, product.name, event.severity, event.id, message, description, src, src_ip, src_port, dst, dst_ip, dst_port, duration + + + + + cisco-ftd + 5-111010 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?(User\s(\S+),\srunning\s(\S+)\sfrom\sIP\s(\S+),\s(\S+)\s(.+)) + header, product.name, event.severity, event.id, message, username, running, ip, type, command + + + + + cisco-ftd + 1-505015 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?(Module\s(.+),\sapplication\sup\s(\S+),\sversion\s(\S+)) + header, product.name, event.severity, event.id, message, module_id, app_up, version + + + + + cisco-ftd + 6-302014|6-302016 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\s(\d+)\sfor\s(\S+):(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)\sduration\s(\d+:\d+:\d+)\sbytes\s(\d+)) + header, product.name, event.severity, event.id, message, description, connection, src, src_ip, src_port, dst, dst_ip, dst_port, duration, bytes + + + + + cisco-ftd + 4-419002 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+):(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)\swith\sdifferent\sinitial\ssequence\snumber) + header, product.name, event.severity, event.id, message, description, src, src_ip, src_port, dst, dst_ip, dst_port + + + + + cisco-ftd + 4-405001 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+)/(\S+)\son\sinterface\s(\S+)\sto\s(\S+)/(\S+)\son\sinterface\s(\S+)) + header, product.name, event.severity, event.id, message, description, src_ip, new_arp, interface, existing_arp + + + + + cisco-ftd + 2-106020 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\s\(size\s=\s(\S+),\soffset\s=\s(\S+)\)\sfrom\s(\S+)\sto\s(\S+)) + header, product.name, event.severity, event.id, message, description, size, offset, src, dst + + + + + cisco-ftd + 5-500003 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\s\(hdrlen=(\S+),\spktlen=(\S+)\)\sfrom\s(\S+)/(\S+)\sto\s(\S+)/(\S+),\sflags:\s(.+),\son\sinterface\s(\S+)) + header, product.name, event.severity, event.id, message, description, hdrlen, pktlen, src_ip, src_port, dst_ip, dst_port, flags, interface + + + + + cisco-ftd + 3-202010 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+):(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)) + header, product.name, event.severity, event.id, message, description, src, src_ip, src_port, dst, dst_ip, dst_port + + + + + cisco-ftd + 1-105005 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\sinterface\s(\S+)) + header, product.name, event.severity, event.id, message, description, interface + + + + + cisco-ftd + 1-106101 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?(The\snumber\sof\s(\S+)\s(.+)\shas\sreached\slimit\s\((\S+)\)) + header, product.name, event.severity, event.id, message, log, description, log, limit + + + + + cisco-ftd + 4-409023 + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\sfor\suser\s([^:]+):(.+)) + header, product.name, event.severity, event.id, message, description, username, message + + + + + cisco-ftd + [^%]*%FTD-4-711004[:\s].* + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\sfor\s(.+),\sProcess\s=\s(\S+),\sPC\s=\s(\S+),\sCall\sstack\s=\s(\w+)) + header, product.name, event.severity, event.id, message, description, time, process, pc, call_stack + + + + + cisco-ftd + [^%]*%FTD-4-411001[:\s].* + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((.+)\son\sinterface\s(\S+)\s(.+)) + header, product.name, event.severity, event.id, message, description, interface, action + + + + + cisco-ftd + [^%]*%FTD-2-321006[:\s].* + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((System\smemory\susage)\sreached\sutilization\s(\S+)) + header, product.name, event.severity, event.id, message, description, percentage + + + + + cisco-ftd + [^%]*%FTD-4-405003[:\s].* + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?((IP\saddress\scollision)\sdetected\sbetween\shost\s(\S+)\sat\s(\S+)\sand\sinterface\s(\S+),\s(\S+)) + header, product.name, event.severity, event.id, message, description, host_ip, src_mac, interface, int_mac_address + + + + + cisco-ftd + ([^%]+)?%(FTD)-([0-7])-([^:\s]+):?\s?(.+)? + header, product.name, event.severity, event.id, message + diff --git a/integrations/cisco_ftd/sample-logs.log b/integrations/cisco_ftd/sample-logs.log new file mode 100644 index 0000000..8720bc2 --- /dev/null +++ b/integrations/cisco_ftd/sample-logs.log @@ -0,0 +1,3 @@ +Jul 10 11:04:18 192.0.2.1 : : %FTD-4-106023: Deny tcp src LAN-INT:192.0.2.124/65191 dst LAN-EXT:198.51.100.157/80 by access-group "CSM_FW_ACL_" [0x0, 0x0] +Jul 10 11:06:02 192.0.2.1 : : %FTD-4-106023: Deny udp src LAN-INT:192.0.2.124/51820 dst LAN-EXT:198.51.100.157/53 by access-group "CSM_FW_ACL_" [0x0, 0x0] +Jun 15 2026 07:28:42: %FTD-4-106023: Deny icmp src LAN-INT:192.0.2.27 dst LAN-INT:192.0.2.106 (type 8, code 0) by access-group "CSM_FW_ACL_" [0x0, 0x0] diff --git a/integrations/cisco_ftd_session/README.md b/integrations/cisco_ftd_session/README.md new file mode 100644 index 0000000..a873928 --- /dev/null +++ b/integrations/cisco_ftd_session/README.md @@ -0,0 +1,131 @@ +# Cisco FTD Session-Prefix Deny Decoders - Wazuh Integration + +## Table of Contents + +* [Introduction](#introduction) +* [Prerequisites](#prerequisites) +* [Installation and Configuration](#installation-and-configuration) + * [Installing the Decoders](#installing-the-decoders) + * [Enabling Alerts via the Stock FTD Rules](#enabling-alerts-via-the-stock-ftd-rules) +* [Rules](#rules) + +### Introduction + +Some Cisco FTD builds emit access-list deny events (message **106023**) with a +`%FTD-session-` prefix instead of the standard `%FTD-` prefix: + +``` +%FTD-session-4-106023: Deny tcp src LAN-INT:192.0.2.124/65191 dst LAN-EXT:198.51.100.157/80 by access-group "CSM_FW_ACL_" +``` + +The stock Cisco FTD parent decoder only matches `%FTD--`, so these +session-prefixed messages fall through undecoded and are visible only in the +archives. This integration adds a dedicated `cisco-ftd-session` parent decoder +plus TCP/UDP and ICMP deny children, so the same denied traffic is decoded with +full fields. + +**This integration ships decoders only.** The decoders emit `product.name=FTD`, +exactly as the stock Cisco FTD decoders do, so a one-line change to the stock +FTD ruleset makes its existing rules alert on session-prefixed events too - no +duplicate rules to maintain. See [Rules](#rules). + +> The standard `%FTD-` prefix is handled by the separate **cisco_ftd** +> integration. Switch and router authentication is handled by **cisco_ios**. + +### Prerequisites + +- A Wazuh manager receiving syslog from Cisco FTD appliances that emit the + `%FTD-session-` prefix, over `` syslog or a log collector on an agent. +- Sufficient privileges on the manager to edit files under `/var/ossec/`. +- The stock Cisco FTD ruleset (`0905-cisco-ftd_rules.xml`) present, since + alerting reuses it (see [Rules](#rules)). +- No third-party software or Python dependencies. This integration is decoder + XML only. + +### Installation and Configuration + +#### Installing the Decoders + +This is a new decoder file with no stock counterpart, so - unlike the +**cisco_ftd** and **cisco_ios** integrations - nothing needs to be excluded. It +simply loads alongside the stock decoders. + +**From the Wazuh dashboard** (recommended for Wazuh Cloud and other managed or +as-is deployments): Server Management -> Decoders -> Manage decoders files -> +Add new decoders file. Name it `cisco_ftd_session_decoders.xml`, paste the +contents of this integration's decoder file, and save. Restart the manager. + +**From the backend (CLI):** + +```bash +cp ruleset/decoders/cisco_ftd_session_decoders.xml /var/ossec/etc/decoders/ +chown wazuh:wazuh /var/ossec/etc/decoders/cisco_ftd_session_decoders.xml +chmod 660 /var/ossec/etc/decoders/cisco_ftd_session_decoders.xml +``` + +Either way it survives manager upgrades, since it lives under `etc/` rather than +`ruleset/`. + +#### Enabling Alerts via the Stock FTD Rules + +The decoders here emit `product.name=FTD`, but the stock Cisco FTD base rule +(id `91500`) keys on the decoder name (`cisco-ftd`), which does not match the +`cisco-ftd-session` parent. Changing that base rule to key on the `product.name` +field instead makes the entire stock FTD ruleset fire for both prefixes - the +stock `cisco-ftd` decoders and the `cisco-ftd-session` decoders here both emit +`product.name=FTD`, so standard-prefix behaviour is unchanged: + +```xml + + + FTD + Cisco FTD messages grouped. + +``` + +**Recommended (upgrade-safe): own a copy of the rules file.** Rather than edit +the stock file in place - which a manager upgrade overwrites - take ownership of +it the same way the decoder integrations do: + +1. Copy the stock FTD rules file into `etc/rules/`, and apply the 91500 change + above to the copy: + + ```bash + cp /var/ossec/ruleset/rules/0905-cisco-ftd_rules.xml /var/ossec/etc/rules/ + chown wazuh:wazuh /var/ossec/etc/rules/0905-cisco-ftd_rules.xml + chmod 660 /var/ossec/etc/rules/0905-cisco-ftd_rules.xml + # then edit rule 91500 in the copy: decoded_as cisco-ftd -> field product.name = FTD + ``` + +2. Exclude the stock rules file so only your copy loads (the IDs are identical, + so both cannot load at once). Server Management -> Settings -> Edit + configuration, in the `` block: + + ```xml + ruleset/rules/0905-cisco-ftd_rules.xml + ``` + +3. Restart the manager. + +Because your copy lives under `etc/rules/` and the stock file is excluded, the +change survives upgrades. Review the copy against the stock file after each +upgrade so you pick up new FTD rules. + +**Quick alternative (not upgrade-safe):** edit rule 91500 directly in +`/var/ossec/ruleset/rules/0905-cisco-ftd_rules.xml` and restart. This is a +default rules file (read-only in the dashboard's rules editor), so make the edit +on the backend. A manager upgrade overwrites it, so re-apply afterwards. + +### Rules + +**This integration ships no rules.** Alerting reuses the stock Cisco FTD ruleset +via the rule 91500 change above. Once 91500 matches `product.name=FTD`, every +stock FTD rule that fires for a `%FTD-` deny also fires for the equivalent +`%FTD-session-` deny, because both decode to the same fields (`action`, +`protocol`, `srcip`, `cisco.access_group`, and so on). Owning a copy of the +rules file (the recommended path above) keeps that change through upgrades. + +If you would rather not reuse the stock ruleset at all, ship a small custom +rules file keyed on `decoded_as cisco-ftd-session` (a base rule plus deny / ICMP +/ frequency rules in the user-defined 110000 block) - fully self-contained, but +it only covers the 106023 deny case rather than the whole FTD ruleset. diff --git a/integrations/cisco_ftd_session/ruleset/decoders/cisco_ftd_session_decoders.xml b/integrations/cisco_ftd_session/ruleset/decoders/cisco_ftd_session_decoders.xml new file mode 100644 index 0000000..8368311 --- /dev/null +++ b/integrations/cisco_ftd_session/ruleset/decoders/cisco_ftd_session_decoders.xml @@ -0,0 +1,404 @@ + + + + + [^%]*%FTD-(?:session-)?[0-7]-[^:\s]+[:\s].* + + + + + cisco-ftd-session + 2-106001 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+)/(\S+)\sto\s(\S+)/(\S+)\sflags\s(.+)\son\sinterface\s(\S+)) + header, product.name, event.severity, event.id, message, description, src_ip, src_port, dst_ip, dst_port, flags, interface + + + + + cisco-ftd-session + 5-718060|5-718061 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+):\scontext=(\d+)) + header, product.name, event.severity, event.id, message, description, context_ID + + + + + cisco-ftd-session + 5-718062 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\(context=(\d+)\)) + header, product.name, event.severity, event.id, message, description, context_ID + + + + + cisco-ftd-session + 1-106021|1-106022 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?(.+\sfrom\s(\S+)) + header, product.name, event.severity, event.id, message, srcip + + + + + cisco-ftd-session + 4-401004 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?(Shunned\spacket:\s(\S+)\s=\s(\S+).+) + header, product.name, event.severity, event.id, message, srcip, dstip + + + + + cisco-ftd-session + 2-106017 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+)\sto\s(\S+)) + header, product.name, event.severity, event.id, message, description, srcip, dstip + + + + + cisco-ftd-session + 2-106006|2-106007 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+)/(\S+)\sto\s(\S+)/(\S+)) + header, product.name, event.severity, event.id, message, description, srcip, srcport, dstip, dstport + + + + + cisco-ftd-session + 3-710003|7-710002|7-710005 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((\S+)\s(\w+).+from\s(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)) + header, product.name, event.severity, event.id, message, protocol, action, srcip, srcport, dstinterface, dstip, dstport + + + + + cisco-ftd-session + 4-106023: \w+ icmp src \S+:\S+ dst + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((\w+)\s(\w+)\ssrc\s(\S+):(\S+)\sdst\s(\S+):(\S+)) + header, product.name, event.severity, event.id, cisco.log, action, protocol, src_interface, srcip, dst_interface, dstip + + + + cisco-ftd-session + ftd-session-4-106023: \w+ icmp src \.+ by access-group (\.+) + message + + + + + cisco-ftd-session + 4-106023 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((\w+)\s(\w+)\ssrc\s(\S+):(\S+)/(\S+)\sdst\s(\S+):(\S+)/(\S+)) + header, product.name, event.severity, event.id, message, action, protocol, src_interface, srcip, srcport, dst_interface, dstip, dstport + + + + + cisco-ftd-session + 6-106015 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((\w+)\s(\w+)\s.+\sfrom\s(\S+)/(\S+)\sto\s(\S+)/(\S+)\sflags\s(\S+)\son\sinterface\s(\S+)) + header, product.name, event.severity, event.id, message, action, protocol, srcip, srcport, dstip, dstport, flags, interface + + + + + cisco-ftd-session + 6-308001 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?(.+\(from\s(\d+.\d+.\d+.\d+)\)) + header, product.name, event.severity, event.id, message, srcip + + + + + cisco-ftd-session + 6-605004|6-605005 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?(Login\s(\S+)\sfrom\s(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)\sfor\suser\s"(\w+)") + header, product.name, event.severity, event.id, message, action, srcip, srcport, interface, dstip, dstport, user + + + + + cisco-ftd-session + 4-733100 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?(Object\sdrop\srate\s(\d+)\sexceeded.\sCurrent\sburst\srate\sis\s(\S+)\sper\ssecond,\smax\sconfigured\srate\sis\s(\S+);\sCurrent\saverage\srate\sis\s(\S+)\sper\ssecond,\smax\sconfigured\srate\sis\s(\S+);\sCumulative\stotal\scount\sis\s(\S+)) + header, product.name, event.severity, event.id, message, rate_ID, burst_rate, max_burst_rate, average_rate, max_average_rate, cumulative_count + + + + + cisco-ftd-session + 5-111008 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?(User\s(\S+)\s(\S+)\sthe\s(.+)) + header, product.name, event.severity, event.id, message, username, type, command + + + + + cisco-ftd-session + 5-502103 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+):\sUname:\s(\S+)\sFrom:\s(\S+)\sTo:\s(\S+)) + header, product.name, event.severity, event.id, message, description, username, from_level, to_level + + + + + cisco-ftd-session + 3-421001 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+):(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)\sis\sdropped\sbecause\sapplication\shas\sfailed) + header, product.name, event.severity, event.id, message, description, src, src_ip, src_port, dst, dst_ip, dst_port + + + + + cisco-ftd-session + 3-421007 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+):(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)\sis\sskipped\sbecause\sapplication\shas\sfailed) + header, product.name, event.severity, event.id, message, description, src, src_ip, src_port, dst, dst_ip, dst_port + + + + + cisco-ftd-session + 3-106014 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\ssrc\s(\S+):(\S+)\sdst\s(\S+):(\S+)\s(\(.+\))) + header, product.name, event.severity, event.id, message, description, src, src_ip, dst, dst_ip, code + + + + + cisco-ftd-session + 4-500004 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\sfor\sprotocol=(\S+),\sfrom\s(\S+)/(\S+)\sto\s(\S+)/(\S+)) + header, product.name, event.severity, event.id, message, description, protocol, src_ip, src_port, dst_ip, dst_port + + + + + cisco-ftd-session + 4-313009 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\scode\s(\S+),\sfor\s\S+:(\S+)/(\S+)\s\(\S+\)\sto\s(\S+):(\S+)/(\S+)\s\(\S+\),\sICMP\sid\s(\S+),\sICMP\stype\s(\S+)) + header, product.name, event.severity, event.id, message, description, code, src, src_port, dst, dst_ip, dst_port, icmp_id, icmp_type + + + + + + cisco-ftd-session + 4-209005 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\s\ssrc\s=\s(\S+),\sdest\s=\s(\S+),\sproto\s=\s(\S+),\sid\s=\s(\S+)) + header, product.name, event.severity, event.id, message, description, src, dst, protocol, fragment_id + + + + + cisco-ftd-session + 6-305012 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+):(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)\sduration\s(\d+:\d+:\d+)) + header, product.name, event.severity, event.id, message, description, src, src_ip, src_port, dst, dst_ip, dst_port, duration + + + + + cisco-ftd-session + 5-111010 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?(User\s(\S+),\srunning\s(\S+)\sfrom\sIP\s(\S+),\s(\S+)\s(.+)) + header, product.name, event.severity, event.id, message, username, running, ip, type, command + + + + + cisco-ftd-session + 1-505015 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?(Module\s(.+),\sapplication\sup\s(\S+),\sversion\s(\S+)) + header, product.name, event.severity, event.id, message, module_id, app_up, version + + + + + cisco-ftd-session + 6-302014|6-302016 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\s(\d+)\sfor\s(\S+):(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)\sduration\s(\d+:\d+:\d+)\sbytes\s(\d+)) + header, product.name, event.severity, event.id, message, description, connection, src, src_ip, src_port, dst, dst_ip, dst_port, duration, bytes + + + + + cisco-ftd-session + 4-419002 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+):(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)\swith\sdifferent\sinitial\ssequence\snumber) + header, product.name, event.severity, event.id, message, description, src, src_ip, src_port, dst, dst_ip, dst_port + + + + + cisco-ftd-session + 4-405001 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+)/(\S+)\son\sinterface\s(\S+)\sto\s(\S+)/(\S+)\son\sinterface\s(\S+)) + header, product.name, event.severity, event.id, message, description, src_ip, new_arp, interface, existing_arp + + + + + cisco-ftd-session + 2-106020 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\s\(size\s=\s(\S+),\soffset\s=\s(\S+)\)\sfrom\s(\S+)\sto\s(\S+)) + header, product.name, event.severity, event.id, message, description, size, offset, src, dst + + + + + cisco-ftd-session + 5-500003 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\s\(hdrlen=(\S+),\spktlen=(\S+)\)\sfrom\s(\S+)/(\S+)\sto\s(\S+)/(\S+),\sflags:\s(.+),\son\sinterface\s(\S+)) + header, product.name, event.severity, event.id, message, description, hdrlen, pktlen, src_ip, src_port, dst_ip, dst_port, flags, interface + + + + + cisco-ftd-session + 3-202010 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\sfrom\s(\S+):(\S+)/(\S+)\sto\s(\S+):(\S+)/(\S+)) + header, product.name, event.severity, event.id, message, description, src, src_ip, src_port, dst, dst_ip, dst_port + + + + + cisco-ftd-session + 1-105005 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\sinterface\s(\S+)) + header, product.name, event.severity, event.id, message, description, interface + + + + + cisco-ftd-session + 1-106101 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?(The\snumber\sof\s(\S+)\s(.+)\shas\sreached\slimit\s\((\S+)\)) + header, product.name, event.severity, event.id, message, log, description, log, limit + + + + + cisco-ftd-session + 4-409023 + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\sfor\suser\s([^:]+):(.+)) + header, product.name, event.severity, event.id, message, description, username, message + + + + + cisco-ftd-session + [^%]*%FTD-(?:session-)?4-711004[:\s].* + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\sfor\s(.+),\sProcess\s=\s(\S+),\sPC\s=\s(\S+),\sCall\sstack\s=\s(\w+)) + header, product.name, event.severity, event.id, message, description, time, process, pc, call_stack + + + + + cisco-ftd-session + [^%]*%FTD-(?:session-)?4-411001[:\s].* + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((.+)\son\sinterface\s(\S+)\s(.+)) + header, product.name, event.severity, event.id, message, description, interface, action + + + + + cisco-ftd-session + [^%]*%FTD-(?:session-)?2-321006[:\s].* + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((System\smemory\susage)\sreached\sutilization\s(\S+)) + header, product.name, event.severity, event.id, message, description, percentage + + + + + cisco-ftd-session + [^%]*%FTD-(?:session-)?4-405003[:\s].* + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?((IP\saddress\scollision)\sdetected\sbetween\shost\s(\S+)\sat\s(\S+)\sand\sinterface\s(\S+),\s(\S+)) + header, product.name, event.severity, event.id, message, description, host_ip, src_mac, interface, int_mac_address + + + + + cisco-ftd-session + ([^%]+)?%(FTD)-(?:session-)?([0-7])-([^:\s]+):?\s?(.+)? + header, product.name, event.severity, event.id, message + diff --git a/integrations/cisco_ftd_session/sample-logs.log b/integrations/cisco_ftd_session/sample-logs.log new file mode 100644 index 0000000..56b93ca --- /dev/null +++ b/integrations/cisco_ftd_session/sample-logs.log @@ -0,0 +1,2 @@ +Jul 10 11:04:18 192.0.2.1 : : %FTD-session-4-106023: Deny tcp src LAN-INT:192.0.2.124/65191 dst LAN-EXT:198.51.100.157/80 by access-group "CSM_FW_ACL_" [0x0, 0x0] +Jul 10 11:09:19 192.0.2.1 : : %FTD-session-4-106023: Deny icmp src DMZ-INT:192.0.2.23 dst LAN-EXT:198.51.100.5 (type 8, code 0) by access-group "CSM_FW_ACL_" [0x0, 0x0] diff --git a/integrations/cisco_ios/README.md b/integrations/cisco_ios/README.md new file mode 100644 index 0000000..8ce4140 --- /dev/null +++ b/integrations/cisco_ios/README.md @@ -0,0 +1,176 @@ +# Cisco NX-OS / IOS-XE Authentication Decoders - Wazuh Integration + +## Table of Contents + +* [Introduction](#introduction) +* [Prerequisites](#prerequisites) +* [Installation and Configuration](#installation-and-configuration) + * [Decoder Placement Constraint](#decoder-placement-constraint) + * [Installing the Decoders (Drop-In Replacement)](#installing-the-decoders-drop-in-replacement) + * [Alternative: Merge Only the Added Blocks](#alternative-merge-only-the-added-blocks) + * [Installing the Rules](#installing-the-rules) + +### Introduction + +This integration extends the stock Wazuh Cisco IOS decoders to cover **Cisco +NX-OS (Nexus)** and **IOS-XE** authentication and user-administration events. +Login results and account-management events are wrapped in `SYSTEM_MSG` with a +body that differs from the classic IOS formats, so the stock Cisco IOS decoders +do not extract the username, source address or outcome. The result is that +switch authentication activity becomes first-class alerts with usable fields, +rather than raw text in `archives.log`. + +> Cisco FTD firewall denies are handled by the separate **cisco_ftd** and +> **cisco_ftd_session** integrations. + +### Prerequisites + +- A Wazuh manager receiving syslog from Cisco Nexus switches or IOS-XE devices, + over `` syslog or a log collector on an agent. +- Sufficient privileges on the manager to edit files under `/var/ossec/`. +- No third-party software or Python dependencies. This integration is decoder + and rule XML only. Installing the decoders as a drop-in replacement under + `etc/decoders/` (the recommended path below) is upgrade-safe. + +### Installation and Configuration + +#### Decoder Placement Constraint + +**Wazuh commits the first child decoder whose `` matches, even when +its `` then fails to extract anything.** A child placed after a matching +sibling never runs. This matters here because: + +- `cisco-ios-default` has **no** ``, so it matches every message that + reaches it. Anything placed after it is dead code. +- `cisco-ios-login` (prematch `Login \w+`) and `cisco-ios-auth` (prematch + `Authentication \w+`), on releases that ship them, also match the NX-OS + wordings and then fail to extract. + +In the file shipped here this is **already handled**: the `cisco-nxos-*` +decoders sit above `cisco-ios-default` (and above `cisco-ios-login` / +`cisco-ios-auth` where present). Each `` is specific enough that it +does not collide with the classic IOS formats. You only need to preserve that +ordering yourself if you hand-merge the blocks (see the alternative below). + +> Note on the NX-OS timestamp: it is year-first and preceded by the switch +> hostname (`NEXUS-SW-01: 2026 Jun 26 07:34:55 UTC: %AUTHPRIV-6-SYSTEM_MSG: ...`). +> The stock `cisco-ios` parent prematch is unanchored and matches from the month +> token onwards, so the leading hostname and year are ignored for parent +> selection. No change to the parent decoder is required. + +#### Installing the Decoders (Drop-In Replacement) + +`ruleset/decoders/cisco_ios_decoders.xml` is a **complete replacement** for the +stock Cisco IOS decoder file: the stock decoder set with the six `cisco-nxos-*` +decoders already merged in at the correct position. Because it keeps the stock +decoder names, the stock Cisco IOS rules keep working against it. + +Confirm the stock decoder filename on your release first (it carries a numeric +prefix), together with the stock Cisco IOS rules file that depends on it: + +```bash +ls /var/ossec/ruleset/decoders/ | grep -i cisco-ios # e.g. 0065-cisco-ios_decoders.xml +ls /var/ossec/ruleset/rules/ | grep -i cisco # the stock Cisco IOS rules file +``` + +**Order matters.** You cannot just add the replacement alongside the stock +decoder: both define the same parent (`cisco-ios`), so with the stock file still +present that parent name is duplicated and the manager errors out. A stock +decoder also cannot be excluded while the stock rules that depend on it are +still loaded. So the sequence is: **exclude the stock decoder and its rules +first, then add the replacement decoder, then re-include the rules.** + +**From the Wazuh dashboard** (recommended for Wazuh Cloud and other managed or +as-is deployments): + +1. **Exclude the stock decoder and its rules.** Server Management -> Settings -> + Edit configuration; in the `` block add both exclusions (use the + rules filename from the grep above), then save and restart the manager: + + ```xml + + + ruleset/decoders + ruleset/rules + ruleset/decoders/0065-cisco-ios_decoders.xml + ruleset/rules/0215-cisco-ios_rules.xml + ... + + etc/decoders + etc/rules + + ``` + +2. **Add the replacement decoder.** Server Management -> Decoders -> Manage + decoders files -> Add new decoders file. Name it `cisco_ios_decoders.xml`, + paste the contents of this integration's decoder file, and save (stored under + `etc/decoders/`). Restart the manager. With the stock decoder excluded there + is no duplicate `cisco-ios` parent. +3. **Re-include the rules.** Back in Settings, remove the `` line + so the stock IOS rules load again - this time against your replacement + decoder - keeping the ``. Save and restart. + +**From the backend (CLI):** the same three phases, editing +`/var/ossec/etc/ossec.conf` and the filesystem directly: + +1. Add both `` and `` to the `` block, + then restart. +2. Copy the replacement decoder in, then restart: + + ```bash + cp ruleset/decoders/cisco_ios_decoders.xml /var/ossec/etc/decoders/ + chown wazuh:wazuh /var/ossec/etc/decoders/cisco_ios_decoders.xml + chmod 660 /var/ossec/etc/decoders/cisco_ios_decoders.xml + ``` +3. Remove the `` (keep the ``), then restart: + + ```bash + systemctl restart wazuh-manager + # or: /var/ossec/bin/wazuh-control restart + ``` + +Trade-off: your copy no longer receives upstream decoder improvements or new +message support. Review it against the stock file after each upgrade, and +re-merge if Wazuh adds IOS decoders you want. + +#### Alternative: Merge Only the Added Blocks + +If you prefer to leave the stock file managed by Wazuh, copy just the six +`cisco-nxos-*` blocks out of the shipped file and paste them into +`/var/ossec/ruleset/decoders/0065-cisco-ios_decoders.xml`, **above** +`cisco-ios-default` (and above `cisco-ios-login` / `cisco-ios-auth` where +present). Back the stock file up first: + +```bash +cp /var/ossec/ruleset/decoders/0065-cisco-ios_decoders.xml{,.bak} +``` + +Trade-off: a manager upgrade replaces files under `/var/ossec/ruleset/`, so the +merge must be re-applied afterwards. Keep this file alongside your +change-management notes so the re-apply is mechanical. + +#### Installing the Rules + +This integration's own rules (`cisco_ios_rules.xml`) have no ordering hazard; +they select on `if_sid` and field values, and chain off the stock Cisco IOS +rule `4715`, so they need the stock IOS rules loaded (re-included in step 3 +above). + +**From the Wazuh dashboard:** Server Management -> Rules -> Manage rules files +-> Add new rules file. Name it `cisco_ios_rules.xml`, paste the contents, and +save. Restart the manager. + +**From the backend (CLI):** + +```bash +cp ruleset/rules/cisco_ios_rules.xml /var/ossec/etc/rules/ +chown wazuh:wazuh /var/ossec/etc/rules/cisco_ios_rules.xml +chmod 660 /var/ossec/etc/rules/cisco_ios_rules.xml +``` + +Then restart the manager: + +```bash +systemctl restart wazuh-manager +# or: /var/ossec/bin/wazuh-control restart +``` diff --git a/integrations/cisco_ios/ruleset/decoders/cisco_ios_decoders.xml b/integrations/cisco_ios/ruleset/decoders/cisco_ios_decoders.xml new file mode 100644 index 0000000..cacdf6d --- /dev/null +++ b/integrations/cisco_ios/ruleset/decoders/cisco_ios_decoders.xml @@ -0,0 +1,376 @@ + + + + + + + + + ^%\w+-\d-\w+: + + + + + + ^%\w+-\d-\w+: + + + + + + ^\d+:\d+:\d+: %\w+-\d-\w+: + + + + + + ^\d+: %\w+-\d-\w+: + + + + + ^\d+: %\w+-\d-\w+: + + + + + + \p*\w+\s+\d*\s\d+:\d+:\d+:\s+%| + \p*\w+\s+\d*\s\d+\s\d+:\d+:\d+:\s+%| + \p*\w+\s+\d*\s\d+:\d+:\d+\s+\w+:\s+%| + \p*\w+\s+\d*\s\d+\s\d+:\d+:\d+\s+\w+:\s+%| + \p*\w+\s+\d*\s\d+:\d+:\d+.\d+:\s+%| + \p*\w+\s+\d*\s\d+\s\d+:\d+:\d+.\d+:\s+%| + \p*\w+\s+\d*\s\d+:\d+:\d+.\d+\s+\w+:\s+%| + \w+\s+\d\p*\s\d+\s\d+:\d+:\d+.\d+\s+\w+:\s+% + + + + + ^\p*\w+\s+\d*\s\d+:\d+:\d+:\s+%| + ^\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+:\s+%| + ^\p*\w+\s+\d*\s\d+:\d+:\d+\s+\w+:\s+%| + ^\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+\s+\w+:\s+%| + ^\p*\w+\s+\d*\s\d+:\d+:\d+.\d+:\s+%| + ^\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+.\d+:\s+%| + ^\p*\w+\s+\d*\s\d+:\d+:\d+.\d+\s+\w+:\s+%| + ^\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+.\d+\s+\w+:\s+% + + + + + + ^\d+:\s\p*\w+\s+\d*\s\d+:\d+:\d+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+:\d+:\d+\s+\w+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+\s+\w+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+:\d+:\d+.\d+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+.\d+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+:\d+:\d+.\d+\s+\w+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+.\d+\s+\w+:\s+% + + + + + ^\d+:\s\p*\w+\s+\d*\s\d+:\d+:\d+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+:\d+:\d+\s+\w+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+\s+\w+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+:\d+:\d+.\d+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+.\d+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+:\d+:\d+.\d+\s+\w+:\s+%| + ^\d+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+.\d+\s+\w+:\s+% + + + + + + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+:\d+:\d+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+:\d+:\d+\s+\w+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+\s+\w+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+:\d+:\d+.\d+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+.\d+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+:\d+:\d+.\d+\s+\w+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+.\d+\s+\w+:\s+% + + + + + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+:\d+:\d+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+:\d+:\d+\s+\w+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+\s+\w+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+:\d+:\d+.\d+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+.\d+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+:\d+:\d+.\d+\s+\w+:\s+%| + ^\d+:\s\.+:\s\p*\w+\s+\d*\s\d+\s\d+:\d+:\d+.\d+\s+\w+:\s+% + + + + + + cisco-ios + %SEC-6-IPACCESSLOGP: list \S+ \S+ \S+ + %(\w+)-(\d)-(\w+): list \S+ (\w+) (\w+) (\d+.\d+.\d+.\d+)\((\d+)\) \S+ \S+ -> (\d+.\d+.\d+.\d+)\((\d+)\),| + %(\w+)-(\d)-(\w+): list \S+ (\w+) (\w+) (\d+.\d+.\d+.\d+)\((\d+)\) -> (\d+.\d+.\d+.\d+)\((\d+)\), + cisco.facility, cisco.severity, cisco.mnemonic, action, protocol, srcip, srcport, dstip, dstport + + + + + + cisco-ios + ids + %IPS-4-SIGNATURE: Sig:\d+ + %(\w+)-(\d)-(\w+): Sig:(\d+) \.+[(\d+.\d+.\d+.\d+):(\d+) -> (\d+.\d+.\d+.\d+):(\d+)] + cisco.facility, cisco.severity, cisco.mnemonic, id, srcip, srcport, dstip, dstport + name, id, srcip, dstip + First time Cisco IOS IDS/IPS module rule fired. + + + + + + cisco-ios + %SYS-5-CONFIG_I: Configured from console by \w+ \( + %(\w+)-(\d)-(\w+): Configured from console by \w+ \((\d+.\d+.\d+.\d+)\) + cisco.facility, cisco.severity, cisco.mnemonic, srcip + + + + cisco-ios + %SYS-5-CONFIG_I: Configured from console by \S+ on \w+ \( + %(\w+)-(\d)-(\w+): Configured from console by (\S+) on \w+ \((\d+.\d+.\d+.\d+)\) + cisco.facility, cisco.severity, cisco.mnemonic, srcuser, srcip + + + + + + + cisco-ios + %\w+-\d-\w+: change user '\S+' password + %(\w+)-(\d)-(\w+): change user '(\S+)' password + cisco.facility, cisco.severity, cisco.mnemonic, dstuser + + + + + cisco-ios + %\w+-\d-\w+: change user '\S+' expiration + %(\w+)-(\d)-(\w+): change user '(\S+)' expiration from '(\S+)' to '(\S+)' + cisco.facility, cisco.severity, cisco.mnemonic, dstuser, cisco.old_expiration, cisco.new_expiration + + + + + cisco-ios + %\w+-\d-\w+: add '\S+' to group + %(\w+)-(\d)-(\w+): add '(\S+)' to group '(\S+)' + cisco.facility, cisco.severity, cisco.mnemonic, dstuser, cisco.group + + + + + cisco-ios + %\w+-\d-\w+: Login \w+ for user + %(\w+)-(\d)-(\w+): Login (\w+) for user (\S+) + cisco.facility, cisco.severity, cisco.mnemonic, login_status, dstuser + + + + + cisco-ios + Authentication failure for illegal user + %(\w+)-(\d)-(\w+): \.+Authentication failure for illegal user (\S+) from (\d+.\d+.\d+.\d+) + cisco.facility, cisco.severity, cisco.mnemonic, dstuser, srcip + + + + + cisco-ios + pam_unix\(\S+\): session \w+ + %(\w+)-(\d)-(\w+): \S+: session (\w+) for user (\S+) + cisco.facility, cisco.severity, cisco.mnemonic, auth_status, srcuser + + + + cisco-ios + User \p(\w+)\p\.+vty0\p(\d+.\d+.\d+.\d+)\p + user, srcip + + + + cisco-ios + Login Success \puser: (\.+)\p \pSource: (\d+.\d+.\d+.\d+)\p \plocalport: (\d+)\p + user, srcip, srcport + + + + cisco-ios + connection from (\d+.\d+.\d+.\d+) + srcip + + + + cisco-ios + server (\d+.\d+.\d+.\d+):(\d+),(\d+) + srcip, srcport, dstport + + + + + + cisco-ios + %(\w+)-(\d)-(\w+): + cisco.facility, cisco.severity, cisco.mnemonic + + diff --git a/integrations/cisco_ios/ruleset/rules/cisco_ios_rules.xml b/integrations/cisco_ios/ruleset/rules/cisco_ios_rules.xml new file mode 100644 index 0000000..5099c6f --- /dev/null +++ b/integrations/cisco_ios/ruleset/rules/cisco_ios_rules.xml @@ -0,0 +1,112 @@ + + + + + + 4715 + + Cisco IOS/NX-OS messages grouped. + + + + + 110020 + ^failed$ + Cisco NX-OS: login failed for user $(dstuser). + authentication_failed,pci_dss_10.2.4,pci_dss_10.2.5,gdpr_IV_35.7.d,hipaa_164.312.b,nist_800_53_AU.14,nist_800_53_AC.7,tsc_CC6.1,tsc_CC6.8, + + + + 110020 + ^success + Cisco NX-OS: successful login for user $(dstuser). + authentication_success,pci_dss_10.2.5,gdpr_IV_32.2,hipaa_164.312.b,nist_800_53_AU.14,nist_800_53_AC.7,tsc_CC6.8, + + + + + 110020 + Authentication failure for illegal user + Cisco NX-OS: authentication failure for unknown user $(dstuser) from $(srcip). + authentication_failed,invalid_login,pci_dss_10.2.4,pci_dss_10.2.5,gdpr_IV_35.7.d,hipaa_164.312.b,nist_800_53_AU.14,nist_800_53_AC.7,tsc_CC6.1,tsc_CC6.8, + + + + + 110020 + change user '\S+' password + Cisco NX-OS: password changed for user $(dstuser). + account_changed,pci_dss_10.2.5,pci_dss_8.1.2,gdpr_IV_35.7.d,hipaa_164.312.b,nist_800_53_AU.14,nist_800_53_AC.2,tsc_CC6.1, + + + + 110020 + add '\S+' to group + Cisco NX-OS: user $(dstuser) added to group $(cisco.group). + account_changed,privilege_escalation,pci_dss_10.2.5,pci_dss_8.1.2,gdpr_IV_35.7.d,hipaa_164.312.b,nist_800_53_AU.14,nist_800_53_AC.2,tsc_CC6.1, + + + + 110020 + expiration from '\S+' to + Cisco NX-OS: account expiry for user $(dstuser) changed from $(cisco.old_expiration) to $(cisco.new_expiration). + account_changed,pci_dss_10.2.5,pci_dss_8.1.2,gdpr_IV_35.7.d,hipaa_164.312.b,nist_800_53_AU.14,nist_800_53_AC.2,tsc_CC6.1, + + + + 110020 + ^opened$|^closed$ + Cisco NX-OS: session $(auth_status) for user $(srcuser). + authentication_success,pci_dss_10.2.5,gdpr_IV_32.2,hipaa_164.312.b,nist_800_53_AU.14,tsc_CC6.8, + + + + + 110023 + + Cisco NX-OS: multiple authentication failures from $(srcip). + authentication_failures,pci_dss_10.2.4,pci_dss_10.2.5,pci_dss_11.4,gdpr_IV_35.7.d,hipaa_164.312.b,nist_800_53_AU.14,nist_800_53_AC.7,tsc_CC6.1,tsc_CC6.8, + + + + + + 110020 + logout + Cisco IOS: user $(dstuser) logged out of a VTY (Telnet/SSH) session from $(srcip) successfully. + authentication_success,gateway_auth,pci_dss_10.2.5,gdpr_IV_32.2, + + + + 110020 + login + Cisco IOS: user $(dstuser) logged in to a VTY (Telnet/SSH) session from $(srcip) successfully. + authentication_success,gateway_auth,pci_dss_10.2.5,gdpr_IV_32.2, + + + + 110020 + changed state to administratively down + Cisco IOS: interface administratively shut down (disabled). + network_iface, + + + diff --git a/integrations/cisco_ios/sample-logs.log b/integrations/cisco_ios/sample-logs.log new file mode 100644 index 0000000..52ad50b --- /dev/null +++ b/integrations/cisco_ios/sample-logs.log @@ -0,0 +1,20 @@ +NEXUS-SW-01: 2026 Jun 26 07:34:55 UTC: %AUTHPRIV-6-SYSTEM_MSG: change user 'jdoe.adm' password - usermod[5837] +NEXUS-SW-01: 2026 Jun 26 06:52:41 UTC: %AUTHPRIV-6-SYSTEM_MSG: pam_unix(dcos_sshd:session): session closed for user jdoe.adm - dcos_sshd[11008] +NEXUS-SW-01: 2026 Jun 26 06:47:39 UTC: %AUTHPRIV-6-SYSTEM_MSG: change user 'jdoe.adm' expiration from '2026-06-27' to '2026-06-28' - usermod[11063] +NEXUS-SW-01: 2026 Jun 26 06:47:39 UTC: %AUTHPRIV-6-SYSTEM_MSG: add 'jdoe.adm' to group 'network-admin' - usermod[11063] +NEXUS-SW-01: 2026 Jun 26 08:00:15 UTC: %AUTHPRIV-5-SYSTEM_MSG: Login failed for user **** - dcos_sshd[20522] +NEXUS-SW-01: 2026 Jun 26 08:00:15 UTC: %DAEMON-3-SYSTEM_MSG: error: PAM: Authentication failure for illegal user ***** from 198.51.100.191 - dcos_sshd[20518] + +Jul 15 15:25:30: %TTY-5-LOGIN: user1, vty0(192.0.2.10), User (user1) logout from vty0(192.0.2.10) successfully + +Jul 15 15:26:00: %TTY-5-LOGIN: user1, vty0(192.0.2.10), User (user1) login from vty0(192.0.2.10) successfully + +Jul 15 15:20:28: %LINK-5-CHANGED: Interface TenGigabitEthernet 2/0/14, changed state to administratively down. + +695334: Jul 14 21:16:59.101: %SEC_LOGIN-5-LOGIN_SUCCESS: Login Success [user: user2] [Source: 192.0.2.11] [localport: 22] at 18:16:59 utc Tue Jul 14 2026 + +146375: .Jul 14 21:13:10.077: %SSH-4-SSH2_UNEXPECTED_MSG: Unexpected message type has arrived. Terminating the connection from 192.0.2.11 + +15128: .Jul 13 00:43:58.138: %RADIUS-4-RADIUS_ALIVE: RADIUS server 192.0.2.30:1645,1646 is being marked alive. + +15127: .Jul 13 00:43:58.129: %RADIUS-4-RADIUS_DEAD: RADIUS server 192.0.2.30:1645,1646 is not responding.