
CVE-2026-20251 — Splunk Secure Gateway jsonpickle-Deserialisierung RCE (CVSS 8.8) | ReactiveZero Security Research
Forscher: Fady Oueslati · ReactiveZero Security Research
Referenz: 2026FO-SPLUNK-20251
CVSS: 8.8 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)
Status: Offen — Patch verfügbar
Ein niedrig privilegierter authentifizierter Benutzer kann auf einem Splunk-Host Remote Code Execution erreichen, indem er ein manipuliertes Dokument im KV-Store (mobile_alerts-Collection) speichert. Splunk Secure Gateway (SSG) liest dieses Dokument später und übergibt es direkt an jsonpickle.decode(), wodurch beliebige Python-Objekte rekonstruiert werden – einschließlich solcher, die Betriebssystembefehle ausführen.
Der Aufruf setzt safe=True, aber dieses Flag schützt nur den Legacy-Pfad py/repr. Die Tags py/reduce, , , und sind nicht betroffen und vollständig ausnutzbar.
py/objectpy/typepy/functionpy/moduleEin separater Validator (check_alert_data_valid_json) soll gefährliche Tags blockieren, bricht aber bei der ersten erkannten Taste ab: Jedes Dokument, dessen erster Top-Level-Key ein erlaubtes py/object ist (Wert beginnt mit spacebridgeapp), gibt sofort True zurück, ohne benachbarte Keys – einschließlich eines bösartigen py/reduce-Gadgets – zu überprüfen.
| Branch | Behoben in |
|---|---|
| Splunk Secure Gateway 3.9.x | 3.9.20 |
| Splunk Secure Gateway 3.10.x | 3.10.6 |
| Splunk Secure Gateway 3.8.x | 3.8.67 |
| Splunk Enterprise | 10.0.7 / 10.2.4 / 10.4.0+ |
Getestete Instanz: SSG 3.9.19 unter Splunk Enterprise 10.0.6 (macOS x86_64).
Schritt 0 Ein Angreifer mit niedrigen Rechten schreibt ein manipuliertes
Bypass-Dokument in die KV-Store-Collection 'mobile_alerts' über die
Splunk-REST-API. Es wird keine Admin- oder Power-Rolle benötigt.
Schritt 1 SSG verarbeitet eine Alarmabrufanforderung.
alerts_request_processor.py liest das Dokument und übergibt es an
check_alert_data_valid_json().
→ Der Validator sieht "py/object": "spacebridgeapp..." als ERSTEN Key,
gibt True zurück und prüft nie den benachbarten "notification"-Key,
der das py/reduce-Gadget trägt.
Schritt 2 Das (jetzt validierte) Dokument wird an
jsonpickle.decode(..., safe=True) übergeben.
jsonpickle loadclass()t das Lockvogel-Alert-Objekt, instanziiert es,
iteriert dann seine gespeicherten Attribute. Wenn es den
"notification"-Wert erreicht, feuert _restore_reduce():
stage1 = f(*args) # unpickler.py ~Zeile 526
safe=True hat auf diesen Codepfad keinen Einfluss.
Ergebnis Beliebige Codeausführung als Splunk-Dienstkonto.
Erfordert nur einen gültigen, niedrig privilegierten Splunk-Login.
{
"py/object": "spacebridgeapp.data.alert_data.Alert",
"notification": {
"py/reduce": [
{"py/function": "subprocess.check_output"},
{"py/tuple": [["uname", "-a"]]}
]
}
}
Der Validator prüft py/object zuerst (erlaubt), gibt True zurück und erreicht notification nie.
poc_cve_2026_20251.py demonstriert die beiden Bedingungen, die die vollständige Exploit-Kette bilden:
| Unterbeweis | Was es zeigt |
|---|---|
| A — Validator-Umgehung | check_alert_data_valid_json() gibt für das Bypass-Dokument True zurück, ohne das py/reduce-Gadget im benachbarten Wert zu überprüfen |
| B — py/reduce-Ausführung | jsonpickle.decode(..., safe=True) führt subprocess.check_output(['uname', '-a']) aus und beweist damit, dass safe=True diesen Codepfad nicht sperrt |
Das Payload ist bewusst harmlos (schreibgeschütztes uname -a). Dies ist kein weaponisierter Exploit.
jsonpickle (geladen von /Applications/Splunk/etc/apps/splunk_secure_gateway/lib)python3 poc_cve_2026_20251.py -h 127.0.0.1
Nicht gegen Produktionssysteme oder Systeme ausführen, die Sie nicht besitzen und für die Sie keine ausdrückliche schriftliche Genehmigung zum Testen haben.
Datei: bin/spacebridgeapp/request/alerts_request_processor.py
alert_json = await response.json()
if not check_alert_data_valid_json(alert_json[0]):
raise SpacebridgeApiRequestError("alert_data is not valid", ...)
alert = jsonpickle.decode(json.dumps(alert_json[0]), safe=True) # ← Senke
Datei: bin/spacebridgeapp/rest/devices/alert_helper.py
# Validator bricht beim ersten 'py'-präfixierten Key ab:
for key, value in data.items():
if key.startswith("py"):
if key == "py/id":
return value.isinstance(int)
elif key == "py/object":
return value.startswith("spacebridgeapp") # ← gibt sofort zurück
else:
return False
# ... benachbarte Keys werden nie erreicht
Primär: Aktualisieren Sie Splunk Secure Gateway auf eine behobene Version (3.9.20+, 3.10.6+ oder 3.8.67+) und Splunk Enterprise auf 10.0.7+ / 10.2.4+ / 10.4.0+.
Kurzfristige Maßnahmen (falls ein Patchen nicht sofort möglich ist):
mobile_alertsDefensives Engineering-Muster: Rekonstruieren Sie niemals beliebige Typen aus extern beeinflussten gespeicherten Daten. Ersetzen Sie jsonpickle.decode() bei angreiferreichbaren Eingaben durch einen strikten, schemavalidierenden Parser oder geben Sie eine explizite classes=-Whitelist an decode() weiter. Stellen Sie sicher, dass Validierungsroutinen verschachtelte Strukturen vollständig durchlaufen, anstatt beim ersten erkannten Key abzubrechen.
Dieselbe Beratungsumgebung umfasst CVE-2026-20253 (CVSS 9.8, nicht authentifizierte beliebige Dateierstellung über einen PostgreSQL-Seitenwagen-Endpunkt). Diese Schwachstelle war nicht vorhanden auf der getesteten macOS x86_64-Build von Splunk Enterprise 10.0.6: Die PostgreSQL-Seitenwagen-Komponente wird auf dieser Plattform nicht ausgeliefert, es existieren keine Seitenwagen-Binärdateien oder -Prozesse, und es wurde kein entsprechender Port beobachtet.
Dies veranschaulicht ein wichtiges Sicherheitsprinzip: Eine betroffene Versionszeichenfolge ist eine notwendige, aber nicht hinreichende Bedingung für die Ausnutzbarkeit. Die komponentenbezogene Überprüfung verändert das reale Risikobild erheblich.
| Feld | Wert |
|---|---|
| Engagement-Referenz | 2026FO-SPLUNK-20251 |
| Testtyp | White-Box-Schwachstellenverifizierung (Statische Codeanalyse) |
| Datum | 26. Juni 2026 |
| Umfang | Lokale Splunk Enterprise 10.0.6-Forschungsinstanz (127.0.0.1:8089) |
| Klassifizierung | Vertraulich |
ReactiveZero Security Research