From 9ba8f46e05bdbd4bbaa203f83e18c8d6a7b04891 Mon Sep 17 00:00:00 2001 From: JocLRojas Date: Fri, 7 Aug 2026 15:38:01 +0300 Subject: [PATCH] refactor(sonicwall): revamp filter and correlation rules Rebuild the SonicWall filter so the parsed events use clear, human-readable field names and match the fields their correlation rules actually consume. Refresh the seven remaining rules so they fire on the real fields the filter emits, and drop three rules that no longer made sense as security signals for this integration. Filter changes (filters/sonicwall/sonic_wall.yml): - Emit clean origin.ip / target.ip (no port or interface glued on) - Emit protocol as tcp/udp only, keep the service hint separately - Emit action / actionResult without leftover quotes - Rescue the full text of quoted fields (message, note, category, rule, session type, VPN policy, user, uuid, action, appName, device time) so they are no longer truncated at the first space - Rename cryptic vendor tokens (m, n, sn, sess, usr, gcat, pri, dpi, ipscat, cs6, ...) to self-explanatory names like log.eventCode, log.deviceSerial, log.sessionType, log.groupCategory - Keep both syslog KV and syslog CEF supported Rules changes (rules/sonicwall/sonicwall_firewall/): - Refresh 7 rules to use the new field names - Remove 3 rules that did not belong to this integration or fired on benign traffic (Capture Client, Encrypted Threats, Zero-Day) Validated against live traffic on env 10.11.11.129. --- filters/sonicwall/sonic_wall.yml | 1036 +++++++++++------ .../anti_spyware_detection.yml | 33 +- .../sonicwall_firewall/botnet_detection.yml | 27 +- .../capture_atp_verdicts.yml | 33 +- .../capture_client_threats.yml | 30 - .../encrypted_threats_detection.yml | 41 - .../gateway_antivirus_detection.yml | 29 +- .../intrusion_prevention_alert.yml | 34 +- .../sonicwall_admin_auth_failures.yml | 31 +- .../sonicwall_vpn_failures.yml | 32 +- .../zero_day_threat_detection.yml | 31 - 11 files changed, 799 insertions(+), 558 deletions(-) delete mode 100644 rules/sonicwall/sonicwall_firewall/capture_client_threats.yml delete mode 100644 rules/sonicwall/sonicwall_firewall/encrypted_threats_detection.yml delete mode 100644 rules/sonicwall/sonicwall_firewall/zero_day_threat_detection.yml diff --git a/filters/sonicwall/sonic_wall.yml b/filters/sonicwall/sonic_wall.yml index 80b37971e..d20d7b247 100644 --- a/filters/sonicwall/sonic_wall.yml +++ b/filters/sonicwall/sonic_wall.yml @@ -1,296 +1,482 @@ -# SonicWall Firewall, version 3.2.0 -# Based on docs -# Support Syslog CEF format +# SonicWall Firewall — version 4.0.0 # -# Documentations -# 1- https://www.sonicwall.com/de-de/techdocs/pdf/sonicos-6-5-4-log-events-reference-guide.pdf -# 2- https://www.sonicwall.com/de-de/techdocs/pdf/SonicOS-X_7.0.1_LogEvents_ReferenceGuide.pdf -# 3- https://docs.elastic.co/integrations/sonicwall_firewall -# 4- https://www.ossec.net/docs/log_samples/firewalls/sonicwall.html +# Formats supported +# - SonicOS syslog KV: id=firewall sn=... time="..." fw=... msg="..." src=IP:PORT:IF ... +# - SonicOS syslog CEF: CEF:0|SonicWall|SonicOS|...|EventID|EventName|Sev|extension +# where `extension` carries the same k=v pairs as the KV variant. # -# Implementation -# 1. Parsing the RAW field containing the PfSense -# 2. Parsing headers of syslog the message +# References +# - https://www.sonicwall.com/techdocs/pdf/sonicos-6-5-4-log-events-reference-guide.pdf +# - https://www.sonicwall.com/techdocs/pdf/SonicOS-X_7.0.1_LogEvents_ReferenceGuide.pdf pipeline: - dataTypes: - firewall-sonicwall steps: - #......................................................................# - #......................................................................# - # Using grok to parse syslogHeader of the message - #......................................................................# + # ------------------------------------------------------------------- + # Syslog header () + # ------------------------------------------------------------------- - grok: + source: raw patterns: - - fieldName: log.priority - pattern: '\<{{.data}}\>' - - fieldName: log.syslogVersion - pattern: '{{.integer}}' - - fieldName: log.dvcTime - pattern: '{{.year}}-{{.monthNumber}}-{{.monthDay}}{{.space}}{{.time}}' - - fieldName: log.syslogHost - pattern: '{{.hostname}}' - - fieldName: log.irrelevant - pattern: '{{.word}}\=' - - fieldName: log.id + - fieldName: log.syslogPri + pattern: '\<{{.integer}}\>' + + - trim: + function: prefix + substring: "<" + fields: + - log.syslogPri + - trim: + function: suffix + substring: ">" + fields: + - log.syslogPri + + # ------------------------------------------------------------------- + # CEF header (only when the log line contains "CEF:") + # ------------------------------------------------------------------- + - grok: + source: raw + patterns: + - fieldName: "" + pattern: '{{.data}}CEF:' + - fieldName: log.cefVersion pattern: '{{.integer}}' - - fieldName: log.msgAll - pattern: '{{.greedy}}' + - fieldName: "" + pattern: '\|' + - fieldName: log.deviceVendor + pattern: '{{.data}}' + - fieldName: "" + pattern: '\|' + - fieldName: log.deviceProduct + pattern: '{{.data}}' + - fieldName: "" + pattern: '\|' + - fieldName: log.deviceVersion + pattern: '{{.data}}' + - fieldName: "" + pattern: '\|' + - fieldName: log.eventCode + pattern: '{{.data}}' + - fieldName: "" + pattern: '\|' + - fieldName: log.eventName + pattern: '{{.data}}' + - fieldName: "" + pattern: '\|' + - fieldName: log.cefSeverity + pattern: '{{.data}}' + - fieldName: "" + pattern: '\|' + where: contains("raw", "CEF:") + + # ------------------------------------------------------------------- + # Key/Value pass over raw + # ------------------------------------------------------------------- + - kv: source: raw + fieldSplit: " " + valueSplit: "=" + # ------------------------------------------------------------------- + # Rescue quoted / space-bearing values. + # ------------------------------------------------------------------- + - delete: + fields: + - log.msg + where: contains("raw", "msg=\"") - grok: + source: raw patterns: - - fieldName: log.dvcTime - pattern: '{{.monthName}}{{.space}}{{.monthDay}}{{.space}}{{.time}}' - - fieldName: log.srcIp - pattern: '{{.ipv4}}' - - fieldName: log.msgAll + - fieldName: log.grokTrash + pattern: '{{.data}}(msg=)' + - fieldName: log.message + pattern: '{{.data}}({{.word}}=)' + - fieldName: log.grokTrash pattern: '{{.greedy}}' - source: raw + where: contains("raw", "msg=\"") + - delete: + fields: + - log.note + where: contains("raw", "note=\"") - grok: + source: raw patterns: - - fieldName: log.priority - pattern: '\<{{.data}}\>' - - fieldName: log.irrelevant - pattern: '{{.data}}\=' - - fieldName: log.device - pattern: '{{.word}}' - - fieldName: log.irrelevant1 - pattern: '{{.data}}\=' - - fieldName: log.sn - pattern: '{{.word}}' - - fieldName: log.irrelevant2 - pattern: '{{.data}}\"' - - fieldName: log.dvcTime - pattern: '{{.year}}-{{.monthNumber}}-{{.monthDay}}{{.space}}{{.time}}' - - fieldName: log.irrelevant3 - pattern: '{{.data}}\=' - - fieldName: log.srcIp - pattern: '{{.ipv4}}' - - fieldName: log.msgAll + - fieldName: log.grokTrash + pattern: '{{.data}}(note=)' + - fieldName: log.note + pattern: '{{.data}}({{.word}}=)' + - fieldName: log.grokTrash pattern: '{{.greedy}}' - source: raw + where: contains("raw", "note=\"") - # ......................................................................# - # Checking if the log is in CEF format - #......................................................................# - # Using grok to parse syslogHeader of the message - # ......................................................................# + - delete: + fields: + - log.Category + where: contains("raw", "Category=\"") - grok: + source: raw patterns: - - fieldName: log.priority - pattern: '\<{{.data}}\>' - - fieldName: log.syslogVersion - pattern: '{{.integer}}' - - fieldName: log.dvcTime - pattern: '{{.year}}-{{.monthNumber}}-{{.monthDay}}{{.space}}{{.time}}' - - fieldName: log.syslogHost - pattern: '{{.hostname}}' - - fieldName: log.formatType - pattern: '(CEF:)' - - fieldName: log.formatVersion - pattern: '(\s)?{{.integer}}' - - fieldName: log.cefMsgAll + - fieldName: log.grokTrash + pattern: '{{.data}}(Category=)' + - fieldName: log.contentCategory + pattern: '{{.data}}({{.word}}=)' + - fieldName: log.grokTrash pattern: '{{.greedy}}' - source: log.msgAll - where: contains("log.msgAll", "CEF:") + where: contains("raw", "Category=\"") + - delete: + fields: + - log.rule + where: contains("raw", "rule=\"") - grok: + source: raw patterns: - - fieldName: log.dvcTime - pattern: '((?i)\b(?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:tember)?|oct(?:ober)?|nov(?:ember)?|dec(?:ember)?)\b){{.space}}{{.monthDay}}{{.space}}{{.year}}{{.space}}{{.time}}' - - fieldName: log.sn - pattern: '{{.word}}' - - fieldName: log.formatType - pattern: '(CEF:)' - - fieldName: log.formatVersion - pattern: '{{.integer}}' - - fieldName: log.cefMsgAll + - fieldName: log.grokTrash + pattern: '{{.data}}(rule=)' + - fieldName: log.rule + pattern: '{{.data}}({{.word}}=)' + - fieldName: log.grokTrash pattern: '{{.greedy}}' - source: log.msgAll - where: contains("log.msgAll", "CEF:") + where: contains("raw", "rule=\"") - #......................................................................# - # Removing unnecessary characters of the syslogHeader - #......................................................................# - - trim: - function: prefix - substring: "<" - fields: - - log.priority - - trim: - function: suffix - substring: ">" - fields: - - log.priority - - trim: - function: suffix - substring: ":" + - delete: fields: - - log.formatType - - #......................................................................# - # Using grok to parse CEF fields - #......................................................................# + - log.sess + where: contains("raw", "sess=\"") - grok: + source: raw patterns: - - fieldName: log.dvcVendor - pattern: '\|{{.data}}\|' - - fieldName: log.dvcProduct - pattern: '{{.data}}\|' - - fieldName: log.dvcVersion - pattern: '{{.data}}\|' - - fieldName: log.eventId - pattern: '{{.data}}\|' - - fieldName: log.eventName - pattern: '{{.data}}\|' - - fieldName: log.severity - pattern: '{{.data}}\|' - - fieldName: log.msgAll + - fieldName: log.grokTrash + pattern: '{{.data}}(sess=)' + - fieldName: log.sessionType + pattern: '{{.data}}({{.word}}=)' + - fieldName: log.grokTrash pattern: '{{.greedy}}' - source: log.cefMsgAll + where: contains("raw", "sess=\"") - - trim: - function: prefix - substring: "|" - fields: - - log.dvcVendor - - - trim: - function: suffix - substring: "|" + - delete: fields: - - log.dvcVendor - - log.dvcProduct - - log.dvcVersion - - log.eventId - - log.eventName - - log.severity - - # Using grok to extract values with spaces in fields + - log.vpnpolicy + where: contains("raw", "vpnpolicy=\"") - grok: + source: raw patterns: - - fieldName: log.trash - pattern: '{{.data}}msg=' - - fieldName: log.message - pattern: '\"{{.data}}\"' - - fieldName: log.trash2 + - fieldName: log.grokTrash + pattern: '{{.data}}(vpnpolicy=)' + - fieldName: log.vpnPolicy + pattern: '{{.data}}({{.word}}=)' + - fieldName: log.grokTrash pattern: '{{.greedy}}' - source: raw + where: contains("raw", "vpnpolicy=\"") + - delete: + fields: + - log.usr + where: contains("raw", "usr=\"") - grok: + source: raw patterns: - - fieldName: log.trash1 - pattern: '{{.data}}ipscat=' - - fieldName: log.ipscat1 - pattern: '\"{{.data}}\"' - - fieldName: log.trash3 + - fieldName: log.grokTrash + pattern: '{{.data}}(usr=)' + - fieldName: log.userRaw + pattern: '{{.data}}({{.word}}=)' + - fieldName: log.grokTrash pattern: '{{.greedy}}' - source: raw + where: contains("raw", "usr=\"") + - delete: + fields: + - log.uuid + where: contains("raw", "uuid=\"") - grok: + source: raw patterns: - - fieldName: log.trash4 - pattern: '{{.data}}cs6=' - - fieldName: log.cs61 - pattern: '\"{{.data}}\"' - - fieldName: log.trash5 + - fieldName: log.grokTrash + pattern: '{{.data}}(uuid=)' + - fieldName: log.eventUuid + pattern: '{{.data}}({{.word}}=)' + - fieldName: log.grokTrash pattern: '{{.greedy}}' - source: raw + where: contains("raw", "uuid=\"") + - delete: + fields: + - log.fwaction + where: contains("raw", "fw_action=\"") - grok: + source: raw patterns: - - fieldName: log.trash6 - pattern: '{{.data}}rule=' - - fieldName: log.rule1 - pattern: '\"{{.data}}\"' - - fieldName: log.trash7 + - fieldName: log.grokTrash + pattern: '{{.data}}(fw_action=)' + - fieldName: log.actionRaw + pattern: '{{.data}}({{.word}}=)' + - fieldName: log.grokTrash pattern: '{{.greedy}}' - source: raw + where: contains("raw", "fw_action=\"") + - delete: + fields: + - log.appName + where: contains("raw", "appName='") - grok: + source: raw patterns: - - fieldName: log.trash8 - pattern: '{{.data}}Category=' - - fieldName: log.category1 - pattern: '\"{{.data}}\"' - - fieldName: log.trash9 + - fieldName: log.grokTrash + pattern: '{{.data}}(appName=)' + - fieldName: log.appName + pattern: '{{.data}}({{.word}}=)' + - fieldName: log.grokTrash pattern: '{{.greedy}}' - source: raw + where: contains("raw", "appName='") + - delete: + fields: + - log.time + where: contains("raw", "time=\"") - grok: + source: raw patterns: - - fieldName: log.trash10 - pattern: '{{.data}}note=' - - fieldName: log.note1 - pattern: '\"{{.data}}\"' - - fieldName: log.trash11 + - fieldName: log.grokTrash + pattern: '{{.data}}(time=)' + - fieldName: log.deviceTimeRaw + pattern: '{{.data}}({{.word}}=)' + - fieldName: log.grokTrash pattern: '{{.greedy}}' - source: raw + where: contains("raw", "time=\"") - - trim: - function: prefix - substring: '"' - fields: - - log.message - - log.note1 - - log.ipscat1 - - log.cs61 - - log.rule1 - - log.category1 - - log.fwaction + # ------------------------------------------------------------------- + # Strip the trailing `word=` that the rescue groks include in + # the captured value. + # ------------------------------------------------------------------- + - grok: + source: log.message + patterns: + - fieldName: log.message + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.grokTrash + pattern: '{{.word}}(=)' + where: exists("log.message") - - trim: - function: suffix - substring: '"' - fields: - - log.message - - log.note1 - - log.ipscat1 - - log.cs61 - - log.rule1 - - log.category1 - - log.fwaction + - grok: + source: log.note + patterns: + - fieldName: log.note + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.grokTrash + pattern: '{{.word}}(=)' + where: exists("log.note") - #......................................................................# - # Using kv to parse msgAll components from syslog format only - #......................................................................# - - kv: - fieldSplit: " " - valueSplit: "=" - source: log.msgAll + - grok: + source: log.contentCategory + patterns: + - fieldName: log.contentCategory + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.grokTrash + pattern: '{{.word}}(=)' + where: exists("log.contentCategory") + + - grok: + source: log.rule + patterns: + - fieldName: log.rule + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.grokTrash + pattern: '{{.word}}(=)' + where: exists("log.rule") + + - grok: + source: log.sessionType + patterns: + - fieldName: log.sessionType + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.grokTrash + pattern: '{{.word}}(=)' + where: exists("log.sessionType") + + - grok: + source: log.vpnPolicy + patterns: + - fieldName: log.vpnPolicy + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.grokTrash + pattern: '{{.word}}(=)' + where: exists("log.vpnPolicy") + + - grok: + source: log.userRaw + patterns: + - fieldName: log.userRaw + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.grokTrash + pattern: '{{.word}}(=)' + where: exists("log.userRaw") + + - grok: + source: log.eventUuid + patterns: + - fieldName: log.eventUuid + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.grokTrash + pattern: '{{.word}}(=)' + where: exists("log.eventUuid") + + - grok: + source: log.actionRaw + patterns: + - fieldName: log.actionRaw + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.grokTrash + pattern: '{{.word}}(=)' + where: exists("log.actionRaw") + + - grok: + source: log.appName + patterns: + - fieldName: log.appName + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.grokTrash + pattern: '{{.word}}(=)' + where: exists("log.appName") + + - grok: + source: log.deviceTimeRaw + patterns: + - fieldName: log.deviceTimeRaw + pattern: '{{.greedy}}{{.space}}' + - fieldName: log.grokTrash + pattern: '{{.word}}(=)' + where: exists("log.deviceTimeRaw") + + # ------------------------------------------------------------------- + # Split src / dst => ip[:port[:iface]] + # ------------------------------------------------------------------- + - grok: + source: log.src + patterns: + - fieldName: origin.ip + pattern: '{{.ipv4}}' + - fieldName: "" + pattern: ':' + - fieldName: origin.port + pattern: '{{.integer}}' + - fieldName: "" + pattern: ':' + - fieldName: log.sourceInterface + pattern: '{{.word}}' + where: contains("log.src", ":") + + - delete: + fields: + - log.src + where: contains("log.src", ":") - # ................................................# - # Rename fields - # ................................................# - rename: from: + - log.src + to: origin.ip + + - grok: + source: log.dst + patterns: + - fieldName: target.ip + pattern: '{{.ipv4}}' + - fieldName: "" + pattern: ':' + - fieldName: target.port + pattern: '{{.integer}}' + - fieldName: "" + pattern: ':' + - fieldName: log.targetInterface + pattern: '{{.word}}' + where: contains("log.dst", ":") + + - delete: + fields: - log.dst - to: target.ip + where: contains("log.dst", ":") + - rename: from: - - log.dstname - to: target.host + - log.dst + to: target.ip + + - grok: + source: log.natSrc + patterns: + - fieldName: log.natSourceIp + pattern: '{{.ipv4}}' + - fieldName: "" + pattern: ':' + - fieldName: log.natSourcePort + pattern: '{{.integer}}' + where: contains("log.natSrc", ":") + + - delete: + fields: + - log.natSrc + where: contains("log.natSrc", ":") + + - grok: + source: log.natDst + patterns: + - fieldName: log.natTargetIp + pattern: '{{.ipv4}}' + - fieldName: "" + pattern: ':' + - fieldName: log.natTargetPort + pattern: '{{.integer}}' + where: contains("log.natDst", ":") + + - delete: + fields: + - log.natDst + where: contains("log.natDst", ":") + + # ------------------------------------------------------------------- + # Split protocol => transport / service + # ------------------------------------------------------------------- + - grok: + source: log.proto + patterns: + - fieldName: protocol + pattern: '{{.word}}' + - fieldName: "" + pattern: '/' + - fieldName: log.appProto + pattern: '{{.notSpace}}' + where: contains("log.proto", "/") + + - delete: + fields: + - log.proto + where: contains("log.proto", "/") + - rename: from: - log.proto to: protocol + + # ------------------------------------------------------------------- + # Canonical + human-readable renames + # ------------------------------------------------------------------- - rename: from: - - log.src - to: origin.ip + - log.dstname + to: target.host - rename: from: - - log.fwaction - to: action + - log.srcMac + to: origin.mac - rename: from: - log.dstMac to: target.mac - rename: from: - - log.srcMac + - log.smac to: origin.mac - rename: from: @@ -298,188 +484,358 @@ pipeline: to: target.mac - rename: from: - - log.smac - to: origin.mac + - log.sent + to: origin.bytesSent - rename: from: - - log.message - to: log.msg + - log.rcvd + to: origin.bytesReceived + - rename: + from: + - log.spkt + to: origin.packagesSent + - rename: + from: + - log.rpkt + to: origin.packagesReceived + - rename: + from: + - log.id + to: log.sourceId + - rename: + from: + - log.sn + to: log.deviceSerial + - rename: + from: + - log.fw + to: log.deviceIp + - rename: + from: + - log.pri + to: log.priority + - rename: + from: + - log.c + to: log.messageClass + - rename: + from: + - log.gcat + to: log.groupCategoryId + - rename: + from: + - log.m + to: log.eventCode + - rename: + from: + - log.n + to: log.eventSerial + - rename: + from: + - log.app + to: log.appId + - rename: + from: + - log.srcZone + to: log.sourceZone + - rename: + from: + - log.dstZone + to: log.targetZone + - rename: + from: + - log.code + to: log.contentCode + - rename: + from: + - log.arg + to: log.webPath + - rename: + from: + - log.dpi + to: log.dpiEnabled + - rename: + from: + - log.ipscat + to: log.ipsCategory + - rename: + from: + - log.ipspri + to: log.ipsPriority - rename: from: - - log.note1 - to: log.note + - log.spycat + to: log.spywareCategory - rename: from: - - log.ipscat1 - to: log.ipscat + - log.spypri + to: log.spywarePriority + - rename: + from: + - log.af_service + to: log.appFirewallService + - rename: + from: + - log.af_type + to: log.appFirewallType + - rename: + from: + - log.result + to: log.threatResult + - rename: + from: + - log.cs6 + to: log.threatContext + + # ------------------------------------------------------------------- + # Strip residual quotes / apostrophes from rescued values. + # ------------------------------------------------------------------- + - trim: + function: prefix + substring: '"' + fields: + - log.message + - log.note + - log.contentCategory + - log.rule + - log.sessionType + - log.vpnPolicy + - log.eventUuid + - log.deviceTimeRaw + - log.actionRaw + - log.userRaw + - trim: + function: suffix + substring: '"' + fields: + - log.message + - log.note + - log.contentCategory + - log.rule + - log.sessionType + - log.vpnPolicy + - log.eventUuid + - log.deviceTimeRaw + - log.actionRaw + - log.userRaw + - trim: + function: prefix + substring: "'" + fields: + - log.appName + - trim: + function: suffix + substring: "'" + fields: + - log.appName + - rename: from: - - log.cs61 - to: log.cs6 + - log.actionRaw + to: action - rename: from: - - log.rule1 - to: log.rule + - log.userRaw + to: origin.user + - rename: from: - - log.category1 - to: log.category + - log.fwaction + to: action - # .......................................................................# - # Fields conversions - # .......................................................................# + # ------------------------------------------------------------------- + # Type casts + # ------------------------------------------------------------------- - cast: fields: - - log.gcat + - origin.port + - target.port + - log.natSourcePort + - log.natTargetPort + to: int + - cast: + fields: + - origin.bytesSent + - origin.bytesReceived + to: float + - cast: + fields: + - origin.packagesSent + - origin.packagesReceived + to: int + - cast: + fields: + - log.groupCategoryId + - log.eventCode + - log.priority to: string - #......................................................................# - # Adding action result - #......................................................................# + # ------------------------------------------------------------------- + # actionResult (canonical vocabulary) + # ------------------------------------------------------------------- - add: function: string params: key: actionResult - value: "forward" - where: 'equals("action", "forward")' + value: success + where: equals("action", "forward") - add: function: string params: key: actionResult - value: "blocked" - where: 'equals("action", "drop")' + value: denied + where: oneOf("action", ["drop", "dropped", "deny", "denied", "block", "blocked"]) - #......................................................................# - # Define Syslog Group Category (gcat) Values - #......................................................................# + # ------------------------------------------------------------------- + # Group category human label from log.groupCategoryId (1..17) + # ------------------------------------------------------------------- - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'System' - where: equals("log.gcat", "1") - + value: System + where: equals("log.groupCategoryId", "1") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'Log' - where: equals("log.gcat", "2") - + value: Log + where: equals("log.groupCategoryId", "2") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'Security Services' - where: equals("log.gcat", "3") - + value: Security Services + where: equals("log.groupCategoryId", "3") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'Users' - where: equals("log.gcat", "4") - + value: Users + where: equals("log.groupCategoryId", "4") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'Firewall Settings' - where: equals("log.gcat", "5") - + value: Firewall Settings + where: equals("log.groupCategoryId", "5") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'Network' - where: equals("log.gcat", "6") - + value: Network + where: equals("log.groupCategoryId", "6") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'VPN' - where: equals("log.gcat", "7") - + value: VPN + where: equals("log.groupCategoryId", "7") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'High Availability' - where: equals("log.gcat", "8") - + value: High Availability + where: equals("log.groupCategoryId", "8") - add: - function: 'string' + function: string params: key: log.groupCategory - value: '3G/4G, Modem, and Module' - where: equals("log.gcat", "9") - + value: 3G/4G, Modem, and Module + where: equals("log.groupCategoryId", "9") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'Firewall' - where: equals("log.gcat", "10") - + value: Firewall + where: equals("log.groupCategoryId", "10") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'Wireless' - where: equals("log.gcat", "11") - + value: Wireless + where: equals("log.groupCategoryId", "11") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'VoIP' - where: equals("log.gcat", "12") - + value: VoIP + where: equals("log.groupCategoryId", "12") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'SSL VPN' - where: equals("log.gcat", "13") - + value: SSL VPN + where: equals("log.groupCategoryId", "13") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'Anti-Spam' - where: equals("log.gcat", "14") - + value: Anti-Spam + where: equals("log.groupCategoryId", "14") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'WAN Acceleration' - where: equals("log.gcat", "15") - + value: WAN Acceleration + where: equals("log.groupCategoryId", "15") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'SD-WAN' - where: equals("log.gcat", "16") - + value: SD-WAN + where: equals("log.groupCategoryId", "16") - add: - function: 'string' + function: string params: key: log.groupCategory - value: 'Multi-Tenancy' - where: equals("log.gcat", "17") + value: Multi-Tenancy + where: equals("log.groupCategoryId", "17") - # Adding geolocation to origin.ip + # ------------------------------------------------------------------- + # Severity from syslog priority (SonicWall log.priority = 0..7) + # ------------------------------------------------------------------- + - add: + function: string + params: + key: severity + value: critical + where: oneOf("log.priority", ["0", "1", "2"]) + - add: + function: string + params: + key: severity + value: error + where: equals("log.priority", "3") + - add: + function: string + params: + key: severity + value: warning + where: equals("log.priority", "4") + - add: + function: string + params: + key: severity + value: info + where: oneOf("log.priority", ["5", "6"]) + - add: + function: string + params: + key: severity + value: debug + where: equals("log.priority", "7") + + # ------------------------------------------------------------------- + # Geolocation + # ------------------------------------------------------------------- - dynamic: plugin: com.utmstack.geolocation params: source: origin.ip destination: origin.geolocation where: exists("origin.ip") - - # Adding geolocation to target.ip + - dynamic: plugin: com.utmstack.geolocation params: @@ -487,56 +843,12 @@ pipeline: destination: target.geolocation where: exists("target.ip") - # .......................................................................# - # Adding severity based on log.pri - # .......................................................................# - - add: - function: 'string' - params: - key: severity - value: 'high' - where: oneOf("log.pri", ["0", "1", "2", "3"]) - - add: - function: 'string' - params: - key: severity - value: 'medium' - where: equals("log.pri", "4") - - add: - function: 'string' - params: - key: severity - value: 'low' - where: oneOf("log.pri", ["5", "6", "7"]) - - # ..........................................................................# - # Removing unnuse fields - #.........................................................................# + # ------------------------------------------------------------------- + # 13. Cleanup + # ------------------------------------------------------------------- - delete: fields: - - log.irrelevant - - log.irrelevant1 - - log.irrelevant2 - - log.irrelevant3 - - log.msgAll - - log.cefMsgAll - - log.pri - - log.gcat - - log.message - - log.note1 - - log.ipscat1 - - log.cs61 - - log.rule1 - - log.category1 - - log.trash - - log.trash1 - - log.trash2 - - log.trash3 - - log.trash4 - - log.trash5 - - log.trash6 - - log.trash7 - - log.trash8 - - log.trash9 - - log.trash10 - - log.trash11 \ No newline at end of file + - log.syslogPri + - log.cefVersion + - log.fwaction + - log.grokTrash diff --git a/rules/sonicwall/sonicwall_firewall/anti_spyware_detection.yml b/rules/sonicwall/sonicwall_firewall/anti_spyware_detection.yml index f0d6e5524..df5df3144 100644 --- a/rules/sonicwall/sonicwall_firewall/anti_spyware_detection.yml +++ b/rules/sonicwall/sonicwall_firewall/anti_spyware_detection.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v2.1.0 dataTypes: - firewall-sonicwall @@ -14,23 +14,26 @@ references: - https://www.sonicwall.com/techdocs/pdf/sonicos-6-5-4-log-events-reference-guide.pdf - https://attack.mitre.org/techniques/T1082/ description: | - Detects when SonicWall Anti-Spyware service identifies and blocks spyware, adware, or other potentially unwanted programs (PUPs) that may be attempting to collect sensitive information or establish persistence on the network. + Detects when SonicWall Anti-Spyware service identifies and blocks spyware, + adware or other potentially unwanted programs (PUPs) that may be attempting + to collect sensitive information or establish persistence on the network. Next Steps: - - Review the detected spyware category and priority level - - Investigate the source IP address for other malicious activities - - Check if the blocked spyware represents a targeted attack or widespread infection - - Verify that Anti-Spyware policies are properly configured and up-to-date - - Consider quarantining the affected host if multiple spyware detections occur - - Review network traffic patterns from the source to identify potential data exfiltration + - Review the detected spyware category and priority level. + - Investigate the source IP for other malicious activities. + - Check whether the blocked spyware represents a targeted attack or a + widespread infection. + - Verify Anti-Spyware policies are properly configured and signatures + up-to-date. + - Consider quarantining the affected host if multiple detections cluster + on the same source. where: | - (exists("log.spycat") || - contains("log.message", "spyware") || - contains("log.message", "Anti-Spyware") || - contains("log.eventName", "Anti-Spyware") || - contains("log.category", "Anti-Spyware") || - (exists("log.spypri") && !equals("log.spypri", "0"))) && - (equals("action", "blocked") || equals("log.fw_action", "drop")) + ( + oneOf("log.eventCode", ["1157", "1158", "1159"]) || + exists("log.spywareCategory") || + contains("log.message", ["spyware", "Anti-Spyware"]) || + contains("log.contentCategory", "Anti-Spyware") + ) && equals("actionResult", "denied") afterEvents: - indexPattern: v11-log-firewall-sonicwall-* with: diff --git a/rules/sonicwall/sonicwall_firewall/botnet_detection.yml b/rules/sonicwall/sonicwall_firewall/botnet_detection.yml index fdedd55ab..2cc6fdf46 100644 --- a/rules/sonicwall/sonicwall_firewall/botnet_detection.yml +++ b/rules/sonicwall/sonicwall_firewall/botnet_detection.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v2.1.0 dataTypes: - firewall-sonicwall @@ -14,17 +14,22 @@ references: - https://www.sonicwall.com/support/knowledge-base/understanding-geo-ip-and-botnet-filter-diagnostics-options/200527122256150 - https://attack.mitre.org/techniques/T1071/ description: | - Detects potential botnet command and control (C2) communication or infected host behavior identified by SonicWall's botnet filter. This includes suspicious outbound connections, HTML infection chains, or known botnet signatures. + Detects potential botnet command and control (C2) communication identified + by the SonicWall Botnet Filter. Includes matches against SonicWall's Botnet + Filter signature codes and message text indicating known botnet endpoints. Next Steps: - 1. Investigate the source IP for additional suspicious activity - 2. Check network logs for other connections from the same host - 3. Analyze DNS queries from the affected host - 4. Review endpoint logs for signs of malware infection - 5. Consider isolating the affected host if infection is confirmed - 6. Update threat intelligence feeds and security signatures - 7. Scan the host with updated antivirus/anti-malware tools -where: (equals("log.category", "Botnet") || contains("log.message", "botnet") || contains("log.message", "infected") || contains("log.message", "C&C") || contains("log.message", "command and control") || equals("log.af_service", "botnet")) && (equals("action", "blocked") || equals("action", "dropped") || equals("log.fw_action", "drop")) + 1. Investigate the source IP for other suspicious behavior (DNS, beaconing). + 2. Check endpoint logs on the internal host for signs of infection. + 3. Isolate the affected host if infection is confirmed. + 4. Update threat intel feeds and blocklists with the observed C2 endpoint. +where: | + ( + oneOf("log.eventCode", ["1370", "1371"]) || + equals("log.appFirewallService", "botnet") || + contains("log.message", ["botnet", "Botnet", "infected", "C&C", "command and control"]) || + contains("log.contentCategory", "Botnet") + ) && equals("actionResult", "denied") afterEvents: - indexPattern: v11-log-firewall-sonicwall-* with: @@ -32,7 +37,7 @@ afterEvents: operator: filter_term value: '{{.origin.ip}}' within: 2h - count: 10 + count: 5 groupBy: - adversary.ip - target.ip diff --git a/rules/sonicwall/sonicwall_firewall/capture_atp_verdicts.yml b/rules/sonicwall/sonicwall_firewall/capture_atp_verdicts.yml index d61d78fa8..77138ab69 100644 --- a/rules/sonicwall/sonicwall_firewall/capture_atp_verdicts.yml +++ b/rules/sonicwall/sonicwall_firewall/capture_atp_verdicts.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v2.1.0 dataTypes: - firewall-sonicwall @@ -14,16 +14,29 @@ references: - https://www.sonicwall.com/support/knowledge-base/capture-atp-overview/170503785055490 - https://attack.mitre.org/techniques/T1204/ description: | - Detects when SonicWall Capture ATP (Advanced Threat Protection) identifies a file as malicious after sandbox analysis. This indicates an attempted malware delivery or execution that was blocked by the ATP service. + Detects when SonicWall Capture ATP (Advanced Threat Protection) sandboxes a + file and returns a malicious verdict. Indicates an attempted malware + delivery. Also covers RTDMI (Real-Time Deep Memory Inspection) verdicts + which share the ATP verdict pipeline on the firewall. Next Steps: - 1. Investigate the source IP address for additional malicious activity - 2. Review the file hash and name for threat intelligence correlation - 3. Check if the same file was delivered to other internal systems - 4. Verify ATP policies are properly configured and up to date - 5. Consider blocking the source IP at the perimeter if confirmed malicious - 6. Document the incident and update threat intelligence feeds -where: (contains("log.msg", "Capture ATP") || contains("log.msg", "Gateway Anti-Virus") || contains("log.msg", "Sandbox") || equals("log.category", "Anti-Virus") || equals("log.af_type", "ATP")) && (contains("log.msg", "malicious") || contains("log.msg", "blocked") || contains("log.msg", "threat detected") || equals("log.result", "malicious") || equals("action", "blocked")) + 1. Investigate the source IP for additional malicious activity. + 2. Pivot on the file hash / URL captured in `log.note` against threat intel. + 3. Check whether the same file reached other internal systems. + 4. Verify ATP policies and enforce automated blocking if not already set. +where: | + ( + oneOf("log.eventCode", ["1440", "1441"]) || + equals("log.appFirewallType", "ATP") || + contains("log.message", ["Capture ATP", "Sandbox", "RTDMI"]) || + contains("log.note", ["Capture ATP", "malicious verdict", "ATP verdict"]) + ) && + ( + equals("log.threatResult", "malicious") || + contains("log.message", ["malicious", "threat"]) || + contains("log.note", ["malicious", "threat"]) || + equals("actionResult", "denied") + ) afterEvents: - indexPattern: v11-log-firewall-sonicwall-* with: @@ -31,7 +44,7 @@ afterEvents: operator: filter_term value: '{{.origin.ip}}' within: 1h - count: 2 + count: 1 groupBy: - adversary.host - adversary.ip diff --git a/rules/sonicwall/sonicwall_firewall/capture_client_threats.yml b/rules/sonicwall/sonicwall_firewall/capture_client_threats.yml deleted file mode 100644 index e62d849db..000000000 --- a/rules/sonicwall/sonicwall_firewall/capture_client_threats.yml +++ /dev/null @@ -1,30 +0,0 @@ -# Rule version v1.0.0 - -dataTypes: - - firewall-sonicwall -name: SonicWall Capture Client Threat Detection -impact: - confidentiality: 3 - integrity: 3 - availability: 2 -category: Defense Evasion, Privilege Escalation -technique: "T1055 - Process Injection" -adversary: origin -references: - - https://www.sonicwall.com/techdocs/pdf/sonicos-6-5-4-log-events-reference-guide.pdf - - https://attack.mitre.org/techniques/T1055/ -description: | - Detects threats identified by SonicWall Capture Client including advanced malware, zero-day exploits, and sophisticated attack techniques. Capture Client provides advanced threat protection through sandboxing and behavioral analysis. - - Next Steps: - 1. Immediately isolate the affected host to prevent lateral movement - 2. Review the specific threat details in SonicWall management console - 3. Analyze the malware sample if available for attribution and IOCs - 4. Check for any successful file downloads or executions on the host - 5. Scan the host with updated antivirus signatures - 6. Review network traffic for any data exfiltration attempts - 7. Update security policies if new attack vectors are identified -where: (contains("log.msg", "Capture Client") || contains("log.app", "Capture") || contains("log.category", "Capture")) && (exists("log.ipscat") || exists("log.ipspri") || exists("log.dpi") || equals("log.action", "drop")) -groupBy: - - adversary.host - - adversary.ip diff --git a/rules/sonicwall/sonicwall_firewall/encrypted_threats_detection.yml b/rules/sonicwall/sonicwall_firewall/encrypted_threats_detection.yml deleted file mode 100644 index 80eac950f..000000000 --- a/rules/sonicwall/sonicwall_firewall/encrypted_threats_detection.yml +++ /dev/null @@ -1,41 +0,0 @@ -# Rule version v1.0.0 - -dataTypes: - - firewall-sonicwall -name: SonicWall Encrypted Threats Detection -impact: - confidentiality: 3 - integrity: 3 - availability: 2 -category: Command and Control -technique: "T1573 - Encrypted Channel" -adversary: origin -references: - - https://www.sonicwall.com/solutions/advanced-threats/encrypted-threats/ - - https://attack.mitre.org/techniques/T1573/ -description: | - Detects threats hidden in encrypted traffic identified by SonicWall DPI-SSL (Deep Packet Inspection of SSL/TLS) including malware, exploits, and data exfiltration attempts over encrypted channels. This rule identifies when SonicWall's advanced threat protection has detected malicious activity within encrypted communications. - - Next Steps: - 1. Review the specific threat type and category identified in the event details - 2. Examine the source and destination IP addresses for indicators of compromise - 3. Check the SSL/TLS certificate details and validation status - 4. Investigate the application or service attempting the encrypted communication - 5. Review network traffic patterns to identify potential data exfiltration - 6. Consider temporarily blocking the source IP if malicious activity is confirmed - 7. Update security policies to prevent similar encrypted threats - 8. Document findings for threat intelligence and future prevention -where: | - (contains("log.eventName", "SSL") || contains("log.eventName", "TLS") || contains("log.eventName", "encrypted") || contains("log.eventName", "DPI-SSL") || contains("log.message", "SSL") || contains("log.message", "TLS") || contains("log.message", "encrypted") || contains("protocol", "SSL") || contains("protocol", "TLS")) && - (contains("log.eventName", "threat") || contains("log.eventName", "malware") || contains("log.eventName", "blocked") || contains("log.eventName", "violation") || contains("log.message", "threat") || contains("log.message", "malware") || contains("log.message", "blocked") || equals("log.result", "blocked") || equals("action", "blocked") || exists("log.ipscat") || exists("log.spycat")) -afterEvents: - - indexPattern: v11-log-firewall-sonicwall-* - with: - - field: origin.ip - operator: filter_term - value: '{{.origin.ip}}' - within: 30m - count: 3 -groupBy: - - adversary.ip - - target.ip diff --git a/rules/sonicwall/sonicwall_firewall/gateway_antivirus_detection.yml b/rules/sonicwall/sonicwall_firewall/gateway_antivirus_detection.yml index 96638b3df..4928138bf 100644 --- a/rules/sonicwall/sonicwall_firewall/gateway_antivirus_detection.yml +++ b/rules/sonicwall/sonicwall_firewall/gateway_antivirus_detection.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v2.1.0 dataTypes: - firewall-sonicwall @@ -14,23 +14,22 @@ references: - https://www.sonicwall.com/techdocs/pdf/sonicos-6-5-4-log-events-reference-guide.pdf - https://attack.mitre.org/techniques/T1105/ description: | - Detects when SonicWall Gateway Anti-Virus (GAV) identifies and blocks malicious content. This indicates potential malware attempting to enter the network through web traffic, email attachments, or file downloads. The Gateway Anti-Virus service scans HTTP, HTTPS, FTP, and SMTP traffic in real-time to detect and prevent malware from entering the network perimeter. + Detects when SonicWall Gateway Anti-Virus (GAV) identifies and blocks + malicious content in HTTP/HTTPS/FTP/SMTP traffic. Signals a malware delivery + attempt at the network perimeter. Next Steps: - 1. Review the specific malware signature or threat name in the log details - 2. Investigate the source IP address and geolocation for suspicious patterns - 3. Check if the same source has attempted other malicious activities - 4. Verify that the anti-virus definitions are up to date - 5. Consider implementing additional network segmentation if internal hosts are affected - 6. Review firewall policies to ensure proper traffic filtering - 7. Escalate to incident response team if part of a coordinated attack campaign + 1. Review the malware name/signature carried in `log.message` / `log.note`. + 2. Investigate the source IP and geolocation for correlated attempts. + 3. Confirm the AV definitions are current on the firewall. + 4. Escalate to incident response if the activity is part of a broader + campaign against the tenant. where: | - (contains("log.gcat", "Gateway Anti-Virus") || - contains("log.message", "virus") || - contains("log.message", "malware") || - contains("log.eventName", "Anti-Virus") || - contains("log.category", "Anti-Virus")) && - equals("action", "blocked") + ( + oneOf("log.eventCode", ["79", "608", "609", "1122"]) || + (equals("log.groupCategory", "Security Services") && contains("log.message", ["virus", "malware", "Anti-Virus"])) || + contains("log.contentCategory", "Anti-Virus") + ) && equals("actionResult", "denied") afterEvents: - indexPattern: v11-log-firewall-sonicwall-* with: diff --git a/rules/sonicwall/sonicwall_firewall/intrusion_prevention_alert.yml b/rules/sonicwall/sonicwall_firewall/intrusion_prevention_alert.yml index 332538062..24084525d 100644 --- a/rules/sonicwall/sonicwall_firewall/intrusion_prevention_alert.yml +++ b/rules/sonicwall/sonicwall_firewall/intrusion_prevention_alert.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v2.1.0 dataTypes: - firewall-sonicwall @@ -14,23 +14,27 @@ references: - https://www.sonicwall.com/techdocs/pdf/sonicos-6-5-4-log-events-reference-guide.pdf - https://attack.mitre.org/techniques/T1190/ description: | - Detects when SonicWall IPS identifies and blocks intrusion attempts, including buffer overflows, SQL injection, cross-site scripting, and other network-based attacks targeting vulnerabilities. This rule triggers when the SonicWall firewall's Intrusion Prevention System detects malicious traffic patterns or known attack signatures. + Detects when SonicWall Intrusion Prevention System (IPS) blocks an attack + matching a known signature — buffer overflow attempts, SQL injection, + cross-site scripting, exploit kits, etc. Reflects the IPS Prevention Alert + message family (event codes 88 / 89 / 100 / 785) as well as the descriptive + `log.message`, `log.contentCategory` and `log.ipsCategory` fields. Next Steps: - 1. Verify the blocked attack by reviewing the SonicWall logs for attack details and signatures matched - 2. Check if the attack was successfully blocked or if any traffic bypassed the IPS - 3. Investigate the source IP for additional malicious activity or patterns - 4. Review target systems for any signs of compromise if the attack was not fully blocked - 5. Update IPS signatures if new attack patterns are discovered - 6. Consider implementing additional network segmentation if attacks are targeting critical systems - 7. Review and update security policies if necessary to prevent similar attacks + 1. Review the matched signature and CVE (if any) in `log.message` / `log.note`. + 2. Confirm the block succeeded — check for follow-up connections from the + same source that bypassed IPS. + 3. Investigate the target for compromise signs if the signature was severity + high/critical. + 4. Update IPS profile if the target service is not supposed to expose that + surface. where: | - (exists("log.ipscat") || - contains("log.message", "IPS") || - contains("log.eventName", "Intrusion") || - contains("log.category", "Intrusion Prevention") || - (exists("log.ipspri") && !equals("log.ipspri", "0"))) && - (equals("action", "blocked") || equals("log.fw_action", "drop")) + ( + oneOf("log.eventCode", ["88", "89", "100", "785"]) || + exists("log.ipsCategory") || + contains("log.message", ["IPS Detection Alert", "IPS Prevention Alert", "Intrusion"]) || + contains("log.contentCategory", "Intrusion Prevention") + ) && equals("actionResult", "denied") afterEvents: - indexPattern: v11-log-firewall-sonicwall-* with: diff --git a/rules/sonicwall/sonicwall_firewall/sonicwall_admin_auth_failures.yml b/rules/sonicwall/sonicwall_firewall/sonicwall_admin_auth_failures.yml index 837882ae0..1ba922bd0 100644 --- a/rules/sonicwall/sonicwall_firewall/sonicwall_admin_auth_failures.yml +++ b/rules/sonicwall/sonicwall_firewall/sonicwall_admin_auth_failures.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v2.1.0 dataTypes: - firewall-sonicwall @@ -14,21 +14,24 @@ references: - https://www.sonicwall.com/techdocs/pdf/sonicos-6-5-4-log-events-reference-guide.pdf - https://attack.mitre.org/techniques/T1110/ description: | - Detects multiple failed authentication attempts to the SonicWall management interface, indicating potential brute force attacks against administrative credentials. + Detects failed authentication attempts against the SonicWall management + interface (GUI/CLI/API). Repeated failures from a single source IP suggest + a brute-force or credential-stuffing attack targeting admin credentials. Next Steps: - 1. Investigate the source IP address attempting authentication - 2. Check if the source IP is from an authorized management network - 3. Review for successful logins from the same IP after failures - 4. Consider blocking the source IP on the management interface - 5. Restrict management access to specific IP addresses - 6. Enable account lockout and two-factor authentication + 1. Investigate the source IP — geolocation, reputation, previous activity. + 2. Confirm the source is NOT from an authorized management network. + 3. Search for a successful admin login from the same IP AFTER the failures + (indicator of a successful brute force). + 4. Restrict management access to specific IP ranges and enforce MFA. where: | - ((contains("log.message", ["admin", "management", "login"]) && - contains("log.message", ["fail", "denied", "invalid", "incorrect"])) || - contains("log.eventName", ["Administrator login failed", "Login failure"]) || - contains("log.category", "Authentication Access")) && - exists("origin.ip") + ( + oneOf("log.eventCode", ["29", "32", "33", "1246"]) || + ( + contains("log.message", ["admin", "administrator", "login", "management"]) && + contains("log.message", ["failed", "fail", "denied", "invalid", "incorrect"]) + ) + ) && exists("origin.ip") afterEvents: - indexPattern: v11-log-firewall-sonicwall-* with: @@ -36,7 +39,7 @@ afterEvents: operator: filter_term value: '{{.origin.ip}}' within: 15m - count: 10 + count: 5 groupBy: - adversary.ip - adversary.user diff --git a/rules/sonicwall/sonicwall_firewall/sonicwall_vpn_failures.yml b/rules/sonicwall/sonicwall_firewall/sonicwall_vpn_failures.yml index 3dc38d521..8bf7ee4fa 100644 --- a/rules/sonicwall/sonicwall_firewall/sonicwall_vpn_failures.yml +++ b/rules/sonicwall/sonicwall_firewall/sonicwall_vpn_failures.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v2.1.0 dataTypes: - firewall-sonicwall @@ -14,21 +14,25 @@ references: - https://www.sonicwall.com/techdocs/pdf/sonicos-6-5-4-log-events-reference-guide.pdf - https://attack.mitre.org/techniques/T1133/ description: | - Detects multiple SSL VPN authentication failures from the same source IP on SonicWall firewalls, indicating brute force or credential stuffing attacks against remote access services. + Detects failed SSL VPN / NetExtender authentication attempts on a SonicWall + firewall. Repeated failures from a single source IP indicate brute-force or + credential-stuffing attacks against the remote access surface. Next Steps: - 1. Investigate the source IP and check threat intelligence databases - 2. Verify if the targeted user accounts exist and are active - 3. Check for successful VPN connections from the same IP - 4. Consider geo-restricting VPN access - 5. Enable MFA for VPN access if not already configured - 6. Block the source IP if confirmed malicious + 1. Investigate the source IP against threat intel; check for scanning. + 2. Verify whether the targeted usernames exist and are enabled. + 3. Look for a successful VPN login from the same IP after the failures. + 4. Enforce MFA on VPN, geo-restrict where possible, and block confirmed + malicious sources at the perimeter. where: | - ((contains("log.message", ["VPN", "SSL-VPN", "NetExtender"]) && - contains("log.message", ["fail", "denied", "invalid", "rejected"])) || - contains("log.eventName", ["VPN login failed", "SSL VPN authentication failed"]) || - contains("log.category", "VPN Access")) && - exists("origin.ip") + ( + oneOf("log.eventCode", ["548", "549", "550"]) || + ( + contains("log.message", ["VPN", "SSL VPN", "SSL-VPN", "NetExtender"]) && + contains("log.message", ["failed", "fail", "denied", "invalid", "rejected"]) + ) || + (equals("log.groupCategory", "SSL VPN") && contains("log.message", ["failed", "denied", "rejected"])) + ) && exists("origin.ip") afterEvents: - indexPattern: v11-log-firewall-sonicwall-* with: @@ -36,7 +40,7 @@ afterEvents: operator: filter_term value: '{{.origin.ip}}' within: 15m - count: 10 + count: 5 groupBy: - adversary.ip - adversary.user diff --git a/rules/sonicwall/sonicwall_firewall/zero_day_threat_detection.yml b/rules/sonicwall/sonicwall_firewall/zero_day_threat_detection.yml deleted file mode 100644 index 71c754a89..000000000 --- a/rules/sonicwall/sonicwall_firewall/zero_day_threat_detection.yml +++ /dev/null @@ -1,31 +0,0 @@ -# Rule version v1.0.0 - -dataTypes: - - firewall-sonicwall -name: SonicWall Zero-Day Threat Detection -impact: - confidentiality: 3 - integrity: 3 - availability: 3 -category: Initial Access -technique: "T1190 - Exploit Public-Facing Application" -adversary: origin -references: - - https://www.sonicwall.com/support/knowledge-base/capture-advanced-threat-protection-feature-overview/170504863294345 - - https://attack.mitre.org/techniques/T1190/ -description: | - Detects zero-day threats and unknown malware identified by SonicWall Capture ATP service including sandbox detonations and RTDMI (Real-Time Deep Memory Inspection) alerts. This rule triggers when the SonicWall firewall identifies previously unknown threats through advanced analysis techniques. - - Next Steps: - 1. Immediately isolate the affected system from the network if possible - 2. Review the full event details including file hashes, URLs, and source IPs - 3. Check if the threat was successfully blocked or if additional containment is needed - 4. Update threat intelligence feeds and IOCs based on the detected indicators - 5. Perform forensic analysis on any systems that may have been compromised - 6. Review firewall rules and security policies to ensure adequate protection - 7. Document the incident and update incident response procedures if necessary -where: | - (contains("log.eventName", "ATP") || contains("log.eventName", "zero-day") || contains("log.eventName", "unknown") || contains("log.eventName", "sandbox") || contains("log.eventName", "RTDMI") || contains("log.message", "ATP") || contains("log.message", "zero-day") || contains("log.message", "unknown malware") || contains("log.message", "sandbox")) && - (contains("log.eventName", "detected") || contains("log.eventName", "blocked") || contains("log.message", "detected") || contains("log.message", "blocked") || equals("log.result", "blocked") || equals("action", "blocked") || equals("log.severity", "critical") || equals("log.severity", "high")) -groupBy: - - adversary.ip