Detection rules › Splunk

Cisco SD-WAN - Arbitrary File Overwrite Exploitation Activity

Status
production
Severity
medium
Group by
_time, dest, src
Author
Nasreddine Bencherchali, Splunk
Source
github.com/splunk/security_content

This analytic detects a exploitation activity attempts of targeting Cisco Catalyst SD-WAN Manager. It leverages the "serviceproxy_access.log" and identifies source-host combinations that perform all key stages of the exploitation as reported in public POCs in a short period: authentication/config collection (.dca), upload actions (uploadAck), and payload-style access (.gz/*). The behavior can indicate attempted exploitation activity associated with Cisco Catalyst SD-WAN Manager vulnerabilities CVE-2026-20122 (Arbitrary File Overwrite) and CVE-2026-20128 (Information Disclosure).

Known false positives

  • No false positives have been identified at this time.

MITRE ATT&CK coverage

TacticTechniques
Initial Access

Rule body

name: Cisco SD-WAN - Arbitrary File Overwrite Exploitation Activity
id: 2f3862c6-45ff-4a02-9bd4-7e25c209fcd9
version: 3
creation_date: '2026-03-12'
modification_date: '2026-05-13'
author: Nasreddine Bencherchali, Splunk
status: production
type: TTP
description: |
    This analytic detects a exploitation activity attempts of targeting Cisco Catalyst SD-WAN Manager.
    It leverages the "serviceproxy_access.log" and identifies source-host combinations that perform all key stages of the exploitation as reported in public POCs in a short period: authentication/config collection (`.dca`), upload actions (`uploadAck`), and payload-style access (`.gz/*`).
    The behavior can indicate attempted exploitation activity associated with Cisco Catalyst SD-WAN Manager vulnerabilities CVE-2026-20122 (Arbitrary File Overwrite) and CVE-2026-20128 (Information Disclosure).
data_source:
    - Cisco SD-WAN Service Proxy Access Logs
search: |-
    `cisco_sd_wan_service_proxy_access`
    | rex field=_raw "^\[.*?\]\s+\"(?<http_method>\S+)\s+(?<uri>\S+)\s+(?<http_protocol>[^\"]+)\"\s+(?<http_response_code>\S+)\s+(?<response_flags>\S+)\s+(?<bytes_in>\S+)\s+(?<bytes_out>\S+)\s+(?<duration>\S+)\s+(?<upstream_service_time>\S+)\s+\"(?<src>[^\"]+)\"\s+\"(?<http_user_agent>[^\"]+)\"\s+\"(?<x_request_id>[^\"]+)\"\s+\"(?<dest>[^\"]+)\"\s+\"(?<upstream_host>[^\"]+)\""
    | rex field=uri "(?<uri_path>[^\?]+)(?<uri_query>\?.*)?"
    | eval
        http_response_code = tonumber(http_response_code),
        bytes_in           = tonumber(bytes_in),
        bytes_out          = tonumber(bytes_out),
        duration           = tonumber(duration),
        upstream_service_time = if(upstream_service_time="-", null(), tonumber(upstream_service_time)),
        status             = http_response_code,
        bytes              = bytes_in + bytes_out,
        http_user_agent_length = len(http_user_agent)
    
    | search (
            (   http_method="POST"
                uri IN (
                    "*/dataservice/smartLicensing/uploadAck*"
                )
            )
            OR (
                http_method="GET"
                uri="*/reports/data/opt/data/containers/config/data-collection-agent/.dca*"
                )
            OR (uri="*.gz/*")
    )
    
    | eval uri_sequence_steps = case(
            match(uri, ".*/\.dca"),       "auth",
            match(uri, ".*/uploadAck"),   "upload",
            match(uri, ".*\.gz/.*"),      "payload",
            true(),                       "other"
    )
    
    | bin _time span=1m
    | stats
        dc(uri_sequence_steps)        as unique_uri_sequence_steps
        values(uri)                   as uri
        values(http_method)           as http_method
        values(http_user_agent)       as http_user_agent
        min(_time)                    as firstTime
        max(_time)                    as lastTime
    by src dest _time
    
    | where unique_uri_sequence_steps >= 3
    | `security_content_ctime(firstTime)`
    | `security_content_ctime(lastTime)`
    | sort 0 - firstTime
    | `cisco_sd_wan___arbitrary_file_overwrite_exploitation_activity_filter`
how_to_implement: |
    This detection requires Cisco SD-WAN Manager Envoy access logs to be ingested into Splunk.
    These logs are located in "/var/log/nms/containers/service-proxy/serviceproxy-access.log".
known_false_positives: |
    No false positives have been identified at this time.
references:
    - https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-sdwan-authbp-qwCX8D4v
    - https://github.com/zerozenxlabs/CVE-2026-20127---Cisco-SD-WAN-Preauth-RCE
finding:
    title: Cisco SD-WAN Manager exploitation activity from $src$ has been identified targeting host $dest$.
    entity:
        field: dest
        type: system
        score: 50
threat_objects:
    - field: src
      type: ip_address
analytic_story:
    - Cisco Catalyst SD-WAN Analytics
asset_type: Network
cve:
    - CVE-2026-20122
    - CVE-2026-20128
mitre_attack_id:
    - T1190
product:
    - Splunk Enterprise
    - Splunk Enterprise Security
    - Splunk Cloud
category: network
security_domain: network

Stages and Predicates

Stage 1: search

`cisco_sd_wan_service_proxy_access`

Stage 2: rex

| rex field=_raw "^\[.*?\]\s+\"(?<http_method>\S+)\s+(?<uri>\S+)\s+(?<http_protocol>[^\"]+)\"\s+(?<http_response_code>\S+)\s+(?<response_flags>\S+)\s+(?<bytes_in>\S+)\s+(?<bytes_out>\S+)\s+(?<duration>\S+)\s+(?<upstream_service_time>\S+)\s+\"(?<src>[^\"]+)\"\s+\"(?<http_user_agent>[^\"]+)\"\s+\"(?<x_request_id>[^\"]+)\"\s+\"(?<dest>[^\"]+)\"\s+\"(?<upstream_host>[^\"]+)\""

The parser skipped this rex command.

Stage 3: rex

| rex field=uri "(?<uri_path>[^\?]+)(?<uri_query>\?.*)?"

Stage 4: eval

| eval
    http_response_code = tonumber(http_response_code),
    bytes_in           = tonumber(bytes_in),
    bytes_out          = tonumber(bytes_out),
    duration           = tonumber(duration),
    upstream_service_time = if(upstream_service_time="-", null(), tonumber(upstream_service_time)),
    status             = http_response_code,
    bytes              = bytes_in + bytes_out,
    http_user_agent_length = len(http_user_agent)

Stage 5: search

| search (
        (   http_method="POST"
            uri IN (
                "*/dataservice/smartLicensing/uploadAck*"
            )
        )
        OR (
            http_method="GET"
            uri="*/reports/data/opt/data/containers/config/data-collection-agent/.dca*"
            )
        OR (uri="*.gz/*")
)

Stage 6: eval

| eval uri_sequence_steps = case(
        match(uri, ".*/\.dca"),       "auth",
        match(uri, ".*/uploadAck"),   "upload",
        match(uri, ".*\.gz/.*"),      "payload",
        true(),                       "other"
)
uri_sequence_steps =
ifmatch(uri, ".*/\.dca")"auth"
elifmatch(uri, ".*/uploadAck")"upload"
elifmatch(uri, ".*\.gz/.*")"payload"
else"other"

Stage 7: bucket

| bin _time span=1m

Stage 8: stats

| stats
    dc(uri_sequence_steps)        as unique_uri_sequence_steps
    values(uri)                   as uri
    values(http_method)           as http_method
    values(http_user_agent)       as http_user_agent
    min(_time)                    as firstTime
    max(_time)                    as lastTime
by src dest _time

Stage 9: where

| where unique_uri_sequence_steps >= 3

Stage 10: search

| `security_content_ctime(firstTime)`

Stage 11: search

| `security_content_ctime(lastTime)`

Stage 12: sort

| sort 0 - firstTime

Stage 13: search

| `cisco_sd_wan___arbitrary_file_overwrite_exploitation_activity_filter`

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
http_methodeq
  • "GET"
  • "POST"
field:"http_method" kind:eq
sourcetypeeq
  • cisco:sdwan:access
field:"sourcetype" kind:eq value:"cisco:sdwan:access"
unique_uri_sequence_stepsge
  • 3
field:"unique_uri_sequence_steps" kind:ge value:"3"
urieq
  • "*.gz/*"
  • "*/reports/data/opt/data/containers/config/data-collection-agent/.dca*"
field:"uri" kind:eq
uriin
  • "*/dataservice/smartLicensing/uploadAck*"
field:"uri" kind:in