Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Cisco IOS XE Guestshell Activation and Destroy
id: ff82a536-8fde-4963-a801-815826fcdf75
version: 1
creation_date: '2026-05-19'
modification_date: '2026-05-20'
author: Nasreddine Bencherchali
status: production
type: Anomaly
description: |
This analytic detects Cisco IOS-XE guestshell enable activity followed by activation and destroy lifecycle logs.
The detection focuses on HA_EM command logging for "guestshell enable" and "guestshell destroy", VMAN activation and destroy messages, and IM/IOX guestshell activation logs observed on some IOS-XE images.
data_source:
- Cisco IOS Logs
search: |-
`cisco_ios`
facility IN ("HA_EM", "VMAN", "IM", "AAA")
mnemonic IN ("LOG", "ACTIVATION_STATE", "IOX_INST_INFO", "INSTALL_STATE", "AAA_ACCOUNTING_MESSAGE")
message_text IN (
"*guestshell enable*",
"*guestshell destroy*",
"*Successfully activated virtual service 'guestshell*",
"*IOX SERVICE guestshell*",
"*Destroying virtual service 'guestshell*",
"*Successfully destroyed virtual service 'guestshell*"
)
| eval dest=coalesce(host, dvc, dest, "unknown")
| eval event_type=case(
like(message_text, "%guestshell enable%"), "guestshell_enable_command",
like(message_text, "%guestshell destroy%"), "guestshell_destroy_command",
like(message_text, "%Successfully activated virtual service 'guestshell%"), "vman_guestshell_activated",
like(message_text, "%IOX SERVICE guestshell%"), "im_iox_guestshell_activated",
like(message_text, "%Destroying virtual service 'guestshell%"), "vman_guestshell_destroying",
like(message_text, "%Successfully destroyed virtual service 'guestshell%"), "vman_guestshell_destroyed",
true(), "other"
)
| bin _time span=30m
| stats count min(_time) as firstTime
max(_time) as lastTime
values(event_type) as event_types
values(message_text) as message
by _time dest
| where
(
mvfind(event_types, "vman_guestshell_activated") >= 0
OR
mvfind(event_types, "im_iox_guestshell_activated") >= 0
OR
mvfind(event_types, "guestshell_enable_command") >= 0
)
AND
(
mvfind(event_types, "vman_guestshell_destroying") >= 0
OR
mvfind(event_types, "vman_guestshell_destroyed") >= 0
OR
mvfind(event_types, "guestshell_destroy_command") >= 0
)
| `security_content_ctime(firstTime)`
| `security_content_ctime(lastTime)`
| `cisco_ios_xe_guestshell_activation_and_destroy_filter`
how_to_implement: |
Use the Cisco Catalyst Add-on for Splunk (https://splunkbase.splunk.com/app/7538) to ingest Cisco IOS-XE syslog with sourcetype "cisco:ios".
Enable EEM catchall command logging to capture the "guestshell enable" and "guestshell destroy" commands as HA_EM/LOG events.
known_false_positives: |
No false positives have been identified at this time.
references:
- https://www.cisa.gov/news-events/cybersecurity-advisories/aa25-239a
- https://blog.talosintelligence.com/salt-typhoon-analysis/
drilldown_searches:
- name: View the detection results for - "$risk_object$"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be dest

search: '%original_detection_search% | search risk_object = "$risk_object$"'
earliest_offset: $info_min_time$
latest_offset: $info_max_time$
- name: View risk events for the last 7 days for - "$risk_object$"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be dest

search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$risk_object$") | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`'
earliest_offset: 7d
latest_offset: "0"
intermediate_findings:
entities:
- field: dest
type: system
score: 35
message: Cisco IOS-XE device $dest$ had guestshell enabled and destroyed within a short period.
analytic_story:
- Salt Typhoon
asset_type: Network
mitre_attack_id:
- T1059
- T1611
product:
- Splunk Enterprise
- Splunk Enterprise Security
- Splunk Cloud
category: network
security_domain: network
tests:
- name: True Positive Test
attack_data:
- data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/emerging_threats/SaltTyphoon/salttyphoon_cisco.log
source: ctb:catalyst:syslog
sourcetype: cisco:ios
test_type: unit
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Cisco IOS XE Log Clearing Sequence With Optional Loopback Removal
id: e20a6709-5f2c-4508-83fb-b3af6f705717
version: 1
creation_date: '2026-05-19'
modification_date: '2026-05-20'
author: Nasreddine Bencherchali
status: production
type: Anomaly
description: |
This analytic detects Cisco IOS-XE command sequences where show logging, clear logging, and exit occur within a short period.
It also detects the pattern where a loopback interface is removed before clearing logs and exiting.
data_source:
- Cisco IOS Logs
search: |-
`cisco_ios`
facility IN ("AAA", "HA_EM", "PARSER")
mnemonic IN ("AAA_ACCOUNTING_MESSAGE", "LOG", "CFGLOG_LOGGEDCMD")
message_text IN ("*show logging*", "*clear logging*", "*exit*", "*no interface Loopback*")

| eval cmd=lower(coalesce(command, message_text))
| eval event_type=case(
like(cmd, "%show logging%"), "show_logging",
like(cmd, "%clear logging%"), "clear_logging",
like(cmd, "%exit%"), "exit",
like(cmd, "%no interface loopback%"), "remove_loopback"
)
| where isnotnull(event_type)
| eval dest=coalesce(host, dvc, dest, "unknown")
| bin _time span=2m
| stats count min(_time) as firstTime
max(_time) as lastTime
values(event_type) as event_types
values(message_text) as message_text
values(cmd) as cmd
by _time dest
| where mvfind(event_types, "clear_logging") >= 0
AND
mvfind(event_types, "exit") >= 0
AND
(
mvfind(event_types, "show_logging") >= 0
OR
mvfind(event_types, "remove_loopback") >= 0
)
| `security_content_ctime(firstTime)`
| `security_content_ctime(lastTime)`
| `cisco_ios_xe_log_clearing_sequence_with_optional_loopback_removal_filter`
how_to_implement: |
Use the Cisco Catalyst Add-on for Splunk (https://splunkbase.splunk.com/app/7538) to Ingest Cisco IOS-XE syslog with sourcetype "cisco:ios".
Command visibility requires AAA command accounting, archive/config logging for configuration commands, or EEM catchall logging.
known_false_positives: |
No false positives have been identified at this time.
references:
- https://www.cisa.gov/news-events/cybersecurity-advisories/aa25-239a
- https://blog.talosintelligence.com/salt-typhoon-analysis/
drilldown_searches:
- name: View the detection results for - "$risk_object$"
search: '%original_detection_search% | search risk_object = "$risk_object$"'
earliest_offset: $info_min_time$
latest_offset: $info_max_time$
- name: View risk events for the last 7 days for - "$risk_object$"
search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$risk_object$") | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`'
earliest_offset: 7d
latest_offset: "0"
intermediate_findings:
entities:
- field: dest
type: system
score: 35
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

likely need 20 or 50 based on type

message: Cisco IOS-XE log clearing sequence was observed on $dest$.
threat_objects: []
analytic_story:
- Salt Typhoon
asset_type: Network
mitre_attack_id:
- T1070.001
- T1562
product:
- Splunk Enterprise
- Splunk Enterprise Security
- Splunk Cloud
category: network
security_domain: network
tests:
- name: True Positive Test
attack_data:
- data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/emerging_threats/SaltTyphoon/salttyphoon_cisco.log
source: ctb:catalyst:syslog
sourcetype: cisco:ios
test_type: unit
110 changes: 110 additions & 0 deletions detections/network/cisco_ios_xe_reconnaissance_command_activity.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: Cisco IOS XE Reconnaissance Command Activity
id: 71ac5328-2364-40cf-8381-92b8dc531399
version: 1
creation_date: '2026-05-19'
modification_date: '2026-05-20'
author: Nasreddine Bencherchali
status: production
type: Anomaly
description: |
This analytic detects bursts of Cisco IOS or NX-OS discovery commands associated with Salt Typhoon tradecraft.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets add a bit more to match other other ESCU descriptions style

data_source:
- Cisco IOS Logs
search: |-
`cisco_ios`
facility IN ("AAA", "HA_EM")
mnemonic IN ("AAA_ACCOUNTING_MESSAGE", "LOG")
message_text IN (
"*show running-config*",
"*show tacacs*",
"*show cdp neighbors*",
"*show file systems*",
"*dir bootflash:*",
"*show clock*",
"*show platform software status control-processor brief*",
"*terminal length 0*",
"*terminal width 0*"
)

| rex field=message_text "^\w+:(?<aaa_src>[^:@]+)(?:@[^:]*)?:(?<aaa_user>[^:]*):(?<aaa_command>.*?)(?:\s+\((?<aaa_result>SUCCESS|FAILURE)\))?$"
| rex field=message_text "^(?:[^:]+:\s+)?(?:catchall:\s+)?(?<eem_command>.+?)\s*$"
| eval command=lower(trim(coalesce(aaa_command, eem_command, "")))

| eval command_type=case(
like(command, "show running-config%"), "show_conf",
like(command, "show tacacs%"), "show_tacacs",
like(command, "show cdp neighbors detail%"), "show_cdp",
like(command, "show cdp neighbors%"), "show_cdp",
like(command, "show file systems%"), "show_file",
like(command, "dir bootflash:%"), "dir_bootflash",
like(command, "show clock%"), "show_clock",
like(command, "show platform software status control-processor brief%"), "show_platform",
like(command, "terminal length 0%"), "terminal",
like(command, "terminal width 0%"), "terminal",
true(), null())
| where isnotnull(command_type)
| eval user=coalesce(aaa_user, user, "unknown")
| eval src_ip=coalesce(aaa_src, src_ip, "unknown")
| eval dest=coalesce(host, dvc, dest, "unknown")
| bin _time span=5m
| stats count min(_time) as firstTime
max(_time) as lastTime
dc(command_type) as unique_recon_commands
values(command_type) as command_types
values(command) as commands
by _time dest user src_ip
| where unique_recon_commands >= 4
| `security_content_ctime(firstTime)`
| `security_content_ctime(lastTime)`
| `cisco_ios_xe_reconnaissance_command_activity_filter`
how_to_implement: |
Use the Cisco Catalyst Add-on for Splunk (https://splunkbase.splunk.com/app/7538) to Ingest Cisco IOS-XE syslog with sourcetype "cisco:ios".
On Nexus, local accounting can emit "%AAA-6-AAA_ACCOUNTING_MESSAGE".
On Catalyst, use TACACS+ command accounting or EEM catchall syslog for exec command visibility.
known_false_positives: |
Network audits and troubleshooting can produce similar command bursts. Tune the command list, threshold, and approved administrators for the environment.
references:
- https://www.cisa.gov/news-events/cybersecurity-advisories/aa25-239a
- https://blog.talosintelligence.com/salt-typhoon-analysis/
drilldown_searches:
- name: View the detection results for - "$risk_object$"
search: '%original_detection_search% | search risk_object = "$risk_object$"'
earliest_offset: $info_min_time$
latest_offset: $info_max_time$
- name: View risk events for the last 7 days for - "$risk_object$"
search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$risk_object$") | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`'
earliest_offset: 7d
latest_offset: "0"
intermediate_findings:
entities:
- field: dest
type: system
score: 25
message: User $user$ executed $unique_recon_commands$ Cisco reconnaissance command categories on $dest$.
- field: user
type: user
score: 25
message: User $user$ executed Cisco reconnaissance commands on $dest$ from $src_ip$.
threat_objects:
- field: commands
type: command
analytic_story:
- Salt Typhoon
asset_type: Network
mitre_attack_id:
- T1082
- T1016
- T1590
product:
- Splunk Enterprise
- Splunk Enterprise Security
- Splunk Cloud
category: network
security_domain: network
tests:
- name: True Positive Test
attack_data:
- data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/emerging_threats/SaltTyphoon/salttyphoon_cisco.log
source: ctb:nexus:syslog
sourcetype: cisco:ios
test_type: unit
91 changes: 91 additions & 0 deletions detections/network/cisco_ios_xe_remote_access_probe_burst.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Cisco IOS XE Remote Access Probe Burst
id: efb20922-17bc-4fb0-880c-be50cfc100dd
version: 1
creation_date: '2026-05-19'
modification_date: '2026-05-20'
author: Nasreddine Bencherchali
status: production
type: Anomaly
description: |
This analytic detects bursts of ping, SSH, and Telnet commands issued from Cisco IOS or NX-OS devices. The Salt Typhoon notes describe repeated SSH, Telnet-to-port-22, and ping activity across multiple IP addresses in a short time window.
data_source:
- Cisco IOS Logs
search: |-
`cisco_ios`
facility IN ("AAA", "HA_EM")
mnemonic IN ("AAA_ACCOUNTING_MESSAGE", "LOG")
message_text IN ("*ssh *", "*telnet *", "*ping *")
| rex field=message_text "^\w+:(?<aaa_src>[^:@]+)(?:@[^:]*)?:(?<aaa_user>[^:]*):(?<aaa_command>.*?)(?:\s+\((?<aaa_result>SUCCESS|FAILURE)\))?$"
| rex field=message_text "^(?:[^:]+:\s+)?(?:catchall:\s+)?(?<eem_command>.+?)\s*$"
| eval command=lower(trim(coalesce(aaa_command, eem_command, "")))
| where match(command, "^(ssh|telnet|ping)\s+")
| rex field=command "(?i)^(?:ssh(?:\s+-l\s+\S+)?|telnet|ping)\s+(?<target_ip>\d{1,3}(?:\.\d{1,3}){3})"
| eval command_type=case(match(command, "^ssh\s+"), "ssh", match(command, "^telnet\s+"), "telnet", match(command, "^ping\s+"), "ping")
| eval user=coalesce(aaa_user, user, "unknown")
| eval src_ip=coalesce(aaa_src, src_ip, "unknown")
| eval dest=coalesce(host, dvc, dest, "unknown")
| bin _time span=10m
| stats count as command_count
min(_time) as firstTime
max(_time) as lastTime
dc(target_ip) as distinct_targets
values(target_ip) as target_ips
values(command_type) as command_types
values(command) as commands
by _time dest user src_ip
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure, but i think it would be better to do values(src_ip) as src_ip and remove it from by clause to account for multiple src_ips at play

| where command_count >= 8 OR distinct_targets >= 5
| `security_content_ctime(firstTime)`
| `security_content_ctime(lastTime)`
| `cisco_ios_xe_remote_access_probe_burst_filter`
how_to_implement: |
Use the Cisco Catalyst Add-on for Splunk (https://splunkbase.splunk.com/app/7538) to Ingest Cisco IOS-XE syslog with sourcetype "cisco:ios".
Command visibility requires AAA command accounting, archive/config logging for configuration commands, or EEM catchall logging.
known_false_positives: |
Network reachability testing, migration validation, and troubleshooting can generate repeated ping, SSH, or Telnet commands.
references:
- https://www.cisa.gov/news-events/cybersecurity-advisories/aa25-239a
- https://blog.talosintelligence.com/salt-typhoon-analysis/
drilldown_searches:
- name: View the detection results for - "$risk_object$"
search: '%original_detection_search% | search risk_object = "$risk_object$"'
earliest_offset: $info_min_time$
latest_offset: $info_max_time$
- name: View risk events for the last 7 days for - "$risk_object$"
search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$risk_object$") | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`'
earliest_offset: 7d
latest_offset: "0"
intermediate_findings:
entities:
- field: dest
type: system
score: 25
message: User $user$ issued $command_count$ ping, SSH, or Telnet commands from Cisco device $dest$ across $distinct_targets$ targets.
- field: user
type: user
score: 25
message: User $user$ issued a Cisco remote access probe burst from $dest$.
threat_objects:
- field: target_ips
type: ip_address
- field: commands
type: command
analytic_story:
- Salt Typhoon
asset_type: Network
mitre_attack_id:
- T1018
- T1021.004
- T1046
product:
- Splunk Enterprise
- Splunk Enterprise Security
- Splunk Cloud
category: network
security_domain: network
tests:
- name: True Positive Test
attack_data:
- data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/emerging_threats/SaltTyphoon/salttyphoon_cisco.log
source: ctb:nexus:syslog
sourcetype: cisco:ios
test_type: unit
Loading
Loading