# Dirty Cert: Cisco Smart Software Manager Silently Patched Post-Auth RCE via Certificate Upload (no CVE stated)

> STAR Labs describes a post-authentication command injection in Cisco Smart Software Manager (CSSM). An authenticated admin who uploads a certificate whose intermediate carries shell command substitution gets command execution in the nginx configurator, which the article says runs as root. Cisco fixed it silently in 10-202608, and the article includes a full PoC.

- **Published:** 2026-11-12T02:05:03Z
- **Last reviewed:** 2026-11-12T02:05:03Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-5812
- **Card image:** https://intel.threadlinqs.com/og/threat/TL-2026-5812.png
- **ID:** TL-2026-5812
- **Severity:** HIGH
- **Category:** VULNERABILITY
- **Status:** PATCHED
- **Detections:** 9 (1 shown free below) · **IOCs:** 9
- **CVEs:** CVE-2026-76437

## Description

Yap Yuan Xi of STAR Labs published a write-up on 2026-09-24 of a post-authentication command injection in Cisco Smart Software Manager (CSSM), delivered as an installable OS that runs microservices behind an nginx reverse proxy. The author tested version 10-202606 as vulnerable. Cisco released 10-202608 on 2026-08-10 without a CVE or advisory text for this bug, and the sink was removed there. The author dates discovery to 2026-08-09, found by an AI-assisted hunting harness, and confirmed the fix by patch analysis on 2026-08-19.

The sink is in /frontend/usr/share/nginx/nginx_configurator/main.js. The functions valid_key(key) and valid_cert(cert) build shell commands from user-controlled input and run them with childProcess.execSync, for example echo "${cert}" | openssl x509 > /dev/null. They are reached during certificate upload via app.put('/certs/:type', saveKeyAndCert). The external entry point is PUT /backend/settings/csr/upload, which nginx proxies to the backend.

The backend validator (upload_validator.rb) checks that a CSR exists, that the certificate matches it, that the intermediate signed the leaf, and that the algorithm is allowlisted. An attacker satisfies these by generating a CSR through /backend/settings/csr/generate, creating their own CA and signing the CSR. Ruby's OpenSSL::X509::Certificate.new tolerates explanatory text before the -----BEGIN CERTIFICATE----- header, as RFC 7468 permits. The leaf certificate is normalized by to_pem, which strips that text, so the payload cannot ride in the leaf. The intermediate_certificate, however, is stored as-is in TrustStoreCert, and build_pem_bundle later sends it to the frontend. There valid_cert passes the bundle to execSync and the injected command substitution runs.

The PoC script (per the article) logs in as admin using default admin credentials, generates a CSR, signs it with a self-made CA, uploads the leaf with a malicious intermediate_certificate, redirects command output to a file in the nginx web root, fetches that file over HTTPS and then deletes it. Code runs with nginx permissions, which the article states are root on that microservice. Exploitation requires admin authentication.

The fix replaced the execSync calls with Node.js crypto APIs: crypto.createPrivateKey(key) with an RSA key-type check, and new crypto.X509Certificate(cert).

CVE correlation (unconfirmed): the article states no CVE. Cisco advisory cisco-sa-ssm-access-nttb2dhE (published 2026-10-07, fixed in 10-202608) covers Cisco License (Smart Software Manager) On-Prem and lists CVE-2026-76437, an admin-authenticated command injection in the web management interface (CVSS 4.9, CWE-78, credited to Gabriele Paris of NATO NCSC, not STAR Labs). The advisory does not mention certificate upload, so this record does not assert that it is the same bug. No in-the-wild exploitation is reported: Cisco PSIRT states it is not aware of public announcements or malicious use of the advisory's CVEs. Severity HIGH is an analyst estimate because root-level RCE is reachable once admin access is held; Cisco's own score for the possibly related CVE is lower because of the PR:H requirement.

## MITRE ATT&CK

- T1078.001 Valid Accounts: Default Accounts
- T1190 Exploit Public-Facing Application
- T1059.004 Command and Scripting Interpreter: Unix Shell
- T1074.001 Data Staged: Local Data Staging
- T1070.004 Indicator Removal: File Deletion

## Free detection (Splunk SPL, Microsoft KQL, Sigma)

**Cisco CSSM Dirty Cert - CSR Generate/Upload Chain With Output Fetch via /backend/settings/csr/upload (Exploitation)** (`TL-2026-5812-SPL-001`)

Detects the Dirty Cert exploitation chain against Cisco Smart Software Manager (CSSM; post-auth command injection, CWE-78, no CVE stated by STAR Labs; possibly related to CVE-2026-76437, linkage unconfirmed). Flags PUT/POST to /backend/settings/csr/upload, the external entry point that carries the malicious intermediate_certificate, and correlates it with /backend/settings/csr/generate from the same source (CSR creation and attacker-CA signing; the attacker-signed intermediate lands in the appliance trust store, T1553.004) and a subsequent HTTPS GET of a non-static file (PoC output retrieval, T1071.001). Admin authentication is required, often via default admin credentials (T1078.001).

- **Languages:** Splunk SPL, Microsoft KQL, Sigma
- **ATT&CK:** T1190, T1078.001, T1078, T1553.004, T1071.001
- **Data sources:** nginx_access_logs (index=web, sourcetype=access_combined), CommonSecurityLog (WAF/proxy), webserver logsource
- **Severity:** high
- **Confidence:** high

### Splunk SPL

```spl
index=web sourcetype=access_combined earliest=-24h | eval stage=case(in(method,"PUT","POST") AND like(uri_path,"%/backend/settings/csr/generate"),"generate", in(method,"PUT","POST") AND like(uri_path,"%/backend/settings/csr/upload"),"upload", method="GET" AND status=200 AND NOT like(uri_path,"/backend/%") AND NOT match(uri_path,"[.](js|css|map|png|jpe?g|gif|svg|ico|woff2?|html?)$"),"fetch") | where isnotnull(stage) | stats count min(eval(if(stage="upload",_time,null()))) as first_upload max(eval(if(stage="fetch",_time,null()))) as last_fetch sum(eval(if(stage="upload",1,0))) as uploads sum(eval(if(stage="generate",1,0))) as generates sum(eval(if(stage="fetch",1,0))) as fetches values(status) as http_status by src, host | where uploads>0 | eval csr_generated_same_src=if(generates>0,"yes","no"), fetch_after_upload=if(fetches>0 AND last_fetch>=first_upload,"yes","no") | convert ctime(first_upload) ctime(last_fetch) | table host src uploads generates fetches csr_generated_same_src fetch_after_upload http_status first_upload last_fetch
```

### Microsoft KQL

```kql
CommonSecurityLog
| where TimeGenerated > ago(24h)
| extend Stage = case(
    RequestMethod in~ ("PUT", "POST") and RequestURL has "/backend/settings/csr/generate", "generate",
    RequestMethod in~ ("PUT", "POST") and RequestURL has "/backend/settings/csr/upload", "upload",
    RequestMethod =~ "GET" and RequestURL !has "/backend/" and not(RequestURL matches regex @"\.(js|css|map|png|jpe?g|gif|svg|ico|woff2?|html?)(\?.*)?$"), "fetch",
    "")
| where Stage != ""
| summarize Uploads = countif(Stage == "upload"), Generates = countif(Stage == "generate"), Fetches = countif(Stage == "fetch"), FirstUpload = minif(TimeGenerated, Stage == "upload"), LastFetch = maxif(TimeGenerated, Stage == "fetch"), Urls = make_set(RequestURL, 10) by SourceIP, DestinationIP, DeviceVendor
| where Uploads > 0
| extend CsrGeneratedFromSameSource = Generates > 0, FetchAfterUpload = Fetches > 0 and LastFetch >= FirstUpload
| project FirstUpload, LastFetch, SourceIP, DestinationIP, DeviceVendor, Uploads, Generates, Fetches, CsrGeneratedFromSameSource, FetchAfterUpload, Urls
```

### Sigma

```yaml
title: Cisco CSSM Certificate Upload Endpoint Access (Dirty Cert)
id: 5b0c1e44-6a7d-5c2e-9f10-3a4b8d2e7101
status: experimental
description: Detects PUT requests to /backend/settings/csr/upload on Cisco Smart Software Manager, the entry point for the post-authentication command injection via a malicious intermediate_certificate (Dirty Cert). Exploitation needs an admin session, often obtained with default admin credentials; the uploaded attacker-signed intermediate is stored in the appliance trust store.
references:
    - https://starlabs.sg/blog/2026/09-dirty-cert-cisco-smart-software-managers-silently-patched-rce/
    - https://www.cisco.com/c/en/us/support/docs/csa/cisco-sa-ssm-access-nttb2dhE.html
author: Threadlinqs Team
date: 2026-11-12
tags:
    - attack.initial-access
    - attack.defense-evasion
    - attack.persistence
    - attack.t1190
    - attack.t1078
    - attack.t1078.001
    - attack.t1553.004
logsource:
    category: webserver
detection:
    selection:
        cs-method: 'PUT'
        c-uri|contains: '/backend/settings/csr/upload'
    condition: selection
falsepositives:
    - Legitimate administrator uploading a CA-signed certificate during certificate renewal
    - Authorized vulnerability scans or penetration tests of the CSSM certificate workflow
level: high
```

**Known false positives:**

- Legitimate administrator uploading a CA-signed certificate during planned certificate renewal
- Vulnerability scanners or authorized penetration tests exercising the CSSM certificate workflow
- Admin browsing dynamic UI pages after a certificate change can trip the fetch stage (fetch is only a priority signal; an upload alone already alerts)

**Tuning notes:** Certificate uploads are rare on CSSM, so alert on any upload and raise priority when csr_generated_same_src=yes, fetch_after_upload=yes, or the source is outside the admin network. Scope the search to the CSSM host(s) (host=) to keep the GET branch cheap. Adjust index/sourcetype and field names (uri_path, method, status, src) to your nginx or reverse-proxy ingestion and allowlist change-window admin hosts. Pair with SPL-002 (shell child of the configurator) for confirmation.

### 8 more detection rules (Splunk SPL, Microsoft KQL, Sigma), unlock with TL Creds

- Cisco CSSM Dirty Cert - CSR Generate/Upload Chain With Output Fetch (Exploitation, KQL) (locked: unlock with TL Creds)
- Cisco CSSM Dirty Cert - Shell Injection in nginx_configurator openssl Call (Post-Exploitation, KQL) (locked: unlock with TL Creds)
- Cisco CSSM Dirty Cert - Output File Created in nginx Web Root Then Deleted (KQL) (locked: unlock with TL Creds)
- Cisco CSSM Dirty Cert - Certificate Upload Endpoint Access (Exploitation, Sigma) (locked: unlock with TL Creds)
- Cisco CSSM Dirty Cert - Shell Injection in nginx_configurator openssl Call (Post-Exploitation, Sigma) (locked: unlock with TL Creds)
- Cisco CSSM Dirty Cert - Output Staged in nginx Web Root and Removed (Sigma) (locked: unlock with TL Creds)
- Cisco CSSM Dirty Cert - Shell Injection in nginx_configurator openssl Call (Post-Exploitation) (locked: unlock with TL Creds)
- Cisco CSSM Dirty Cert - Output File Created in nginx Web Root Then Deleted (Output Staging / Cleanup) (locked: unlock with TL Creds)

Sign up free to unlock the detection rules: https://threadlinqs.com/?modal=signup

## Sources

- [Dirty Cert: Cisco Smart Software Manager's Silently Patched RCE (STAR Labs, Yap Yuan Xi)](https://starlabs.sg/blog/2026/09-dirty-cert-cisco-smart-software-managers-silently-patched-rce/)
- [Cisco License (Smart Software Manager) On-Prem Vulnerabilities - cisco-sa-ssm-access-nttb2dhE](https://www.cisco.com/c/en/us/support/docs/csa/cisco-sa-ssm-access-nttb2dhE.html)
- [CVE-2026-76437 - Cisco License On-Prem Command Injection (OpenCVE)](https://app.opencve.io/cve/CVE-2026-76437)
- [Cisco Security Advisory (Cisco Security Center)](https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-ssm-access-nttb2dhE)
- [Cisco Patches Critical Smart Software Manager On-Prem Vulnerabilities (eSecurity Planet)](https://www.esecurityplanet.com/vulnerabilities/news-cisco-smart-software-manager-on-prem-critical-flaws/)
- [RFC 7468 - Textual Encodings of PKIX, PKCS, and CMS Structures](https://www.rfc-editor.org/rfc/rfc7468)

## Full data

The other 8 detection rules (Splunk SPL / Microsoft KQL / Sigma) unlock with TL Creds; a free account includes daily creds: https://threadlinqs.com/?modal=signup
Indicator values unlock with TL Creds, at a lower price on Red and Purple; AI agents can query rules and IOCs through the Threadlinqs MCP server (Purple): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-5812
