
Erkennungs-, Mitigations- und Reverse-Engineering-Werkzeuge für CVE-2026-41940 (SessionScribe): die nicht authentifizierte Session-Forgery-Schwachstelle in cPanel/WHM, offengelegt am 28.04.2026. Aktiver Defense-in-Depth-Mitigation-Shim, ModSec-Regelpaket, Remote-Sonde, On-Host-IOC-Scanner und RE-Snapshot-Collector pro Ebene. GPL v2.
Kritischer nicht authentifizierter RCE in cPanel & WHM. Vier HTTP-Anfragen schmieden eine Root-Sitzung mittels CRLF-Injection in das Passwortfeld einer Preauth-Sitzung. Keine Authentifizierung, keine Voraussetzungen, jede unterstützte Stufe betroffen. Offengelegt am 28.04.2026 von Sina Kheirkhah / watchTowr Labs.
Schnellstart · ioc-scan · mitigate · remote-probe · Betroffene Builds ·
[!IMPORTANT] Die Tiers 112, 114, 116, 120, 122, 128 haben keinen Hersteller-Patch. Jeder Build auf diesen Tiers ist verwundbar; ein Upgrade oder eine Migration ist die einzige dauerhafte Lösung. Bis dahin: Firewall TCP/2082, 2083, 2086, 2087, 2095, 2096 auf Management-CIDRs beschränken (
mitigate.sh --applyerledigt das) und die verbleibende Angriffsfläche mit dem ModSec-Regelpaket absichern.
Drei Einzeiler, in Operator-Prioritätsreihenfolge:```bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --apply
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh | bash -s -- --target HOST
Exitcodes sind für die Flottenautomatisierung ausgelegt: `ioc-scan` beendet mit `4` bei
COMPROMISED, mit `1` bei VULNERABLE; `mitigate` beendet mit `0` sauber / `1` angewendet
/ `2` manuell / `3` Tool-Fehler; `remote-probe` beendet mit `2`, wenn irgendein
Ziel VULN ist.
---
## Tools
In der Reihenfolge der operativen Priorität. Jedes Artefakt erzeugt strukturierte Ausgabe
(`--json` / `--jsonl` / `--csv`) geschlüsselt nach `host`, `os`, `cpanel_version`,
`ts` für das Flotten-Roll-up.
| Tool | Rolle | Ausführungsort |
|---|---|---|
| **[`sessionscribe-ioc-scan.sh`](#sessionscribe-ioc-scansh---ioc-ladder--kill-chain)** | Erstklassige Triage. IOC ladder, Code-State- und Host-State-Bewertungen, Kill-Chain-Rekonstruktion, IR-Bundle. | auf dem cPanel-Host |
| **[`sessionscribe-mitigate.sh`](#sessionscribe-mitigatesh---mitigation-orchestrator)** | Das Zeitfenster schließen. Phasenweise Mitigation: Patch-Check, Firewall, proxysub, ModSec. | auf dem cPanel-Host |
| **[`sessionscribe-remote-probe.sh`](#sessionscribe-remote-probesh---non-destructive-fleet-probe)** | Begleitmaterial. Nicht-destruktive 4-stufige Prüfung → VULN/SAFE pro Host. | überall mit `curl` |
| [`modsec-sessionscribe.conf`](#supporting-collateral) | ModSec-Regelpaket, bereitgestellt von `mitigate`. | Apache-Frontend |
| [`sessionscribe-revsnap.sh`](#supporting-collateral) | RE-Snapshot-Sammler pro Stufe für Binärdiffing. | auf dem cPanel-Host, rund um `upcp` |
GPL v2. Alle Artefakte sind über die obigen Raw-URLs per `curl` abrufbar.
---
## `sessionscribe-ioc-scan.sh` - IOC ladder + kill-chain
**Führen Sie dies zuerst aus.** Standardmäßig nur Erkennung (schnell, flottenfreundlich);
fügen Sie `--full` hinzu, um die forensischen Phasen inline auszuführen (Defense-Timeline, Offense-Ingest,
Abgleich, Kill-Chain-Renderer, IR-Bundle).```bash
# fast triage (detection only)
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash
# full kill-chain reconstruction inline
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash -s -- --full
# full + ship IR bundle to intake
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash -s -- --full --upload
# JSONL for SIEM ingest
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash -s -- --jsonl --quiet > host.jsonl
# host IOCs only - periodic post-patch sweep, last 7 days
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash -s -- --ioc-only --since 7
# replay forensic phases against a saved envelope (no re-scan)
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash -s -- --replay /var/cpanel/sessionscribe-ioc/<run_id>.json
Zwei Achsen berichten unabhängig voneinander. code_verdict (PATCHED /
VULNERABLE / INCONCLUSIVE) stammt aus Version, Perl-Quellcode-Mustern
und dem cpsrvd-Binär-Fingerabdruck. host_verdict (CLEAN /
SUSPICIOUS / COMPROMISED) ergibt sich aus der IOC-Leiter der
Sitzungsdateien, dem Zugriffsprotokoll-Scan und den Zerstörungs-Sonden der
Muster A–G. Ein gepatchter Host kann den Exit-Code 4 dennoch liefern,
wenn eine frühere Ausnutzung IOCs auf der Festplatte hinterlassen hat.
| Exit | Code-state | Host-state | Triage-Aktion |
|---|---|---|---|
| 0 | CLEAN/PATCHED | CLEAN | keine |
| 1 | VULNERABLE | (beliebig) | cpsrvd patchen |
| 2 | INCONCLUSIVE | (beliebig) | manuelle Prüfung des Code-Zustands (auch: Tool-Fehler) |
| 3 | (beliebig) | SUSPICIOUS | Sitzungs-/Zugriffsprotokolle prüfen |
| 4 | (beliebig) | COMPROMISED | vollständige IR; Bündeln + Hochladen |
Sitzungen, die mit nxesec_canary_<nonce> markiert sind (von der
Remote-Sonde hinterlassen), werden als PROBE_ARTIFACT eingestuft und
nicht auf COMPROMISED hochgestuft.
--full stellt jedes IOC den Verteidigungsaktivierungen gegenüber und
klassifiziert jedes als PRE-DEFENSE, POST-DEFENSE, POST-PARTIAL
oder UNDEFENDED und fasst dann mit Bewertung und Schlagzeile zur
Verteidigungsverzögerung zusammen.
PRE-DEFENSE = der Host war für den Exploit offen, als der Indikator eintraf;
POST-DEFENSE = Kollateralschaden oder Rauschen vor der Schadensbegrenzung.```
+-- CVE-2026-41940 / IC-5790 --------------------------------------------
| host cpanel.example.com ()
| cpanel unknown os unknown
| verdict COMPROMISED score 315 ioc-scan v2.5.0
| defenses patch x absent modsec + up csf + clean mitigate + ran
+------------------------------------------------------------------------
| -- PRE-DEFENSE (32 events) -- | 2026-03-25T09:43:19Z ! pattern X ioc_attacker_ip_2xx_on_cpsess 57 hit(s) (last 90d) from IC-5790 IPs returned 2xx on /cpsess/ paths - real exploitation | 2026-04-28T14:35:56Z ! pattern X ioc_cve_2026_41940_crlf_access_chain 15 CRLF-bypass chain(s) — POST /login 401 then GET /cpsess 2xx as root within 2s | 2026-04-28T16:38:45Z ! pattern E ioc_pattern_e_websocket_shell_hits 45 external IP(s) reached /cpsess*/websocket/Shell with 2xx | 2026-04-29T08:41:22Z ! pattern F ioc_pattern_f_smark_envelope S_MARK/E_MARK harvester envelope in /root/.bash_history | 2026-04-29T16:41:24Z ! pattern A ioc_pattern_a_ransom_readme /home/user1/README.md | … (22 more Pattern A ransom_readme events across customer homedirs) | 2026-04-29T16:42:09Z ! pattern A ioc_pattern_a_sorry_files_present 608 .sorry-encrypted files present | 2026-04-29T17:52:58Z ! pattern D ioc_pattern_d_acctlog_encrypted /var/cpanel/accounting.log.sorry
| -- DEFENSES -- | 2026-04-29T23:48:21Z + DEFENSE mitigate_first sessionscribe-mitigate.sh first run | 2026-04-29T23:48:21Z + DEFENSE csf csf.conf cpsrvd ports stripped | 2026-04-29T23:48:46Z + DEFENSE modsec modsec rule 1500030 installed
| -- POST-PARTIAL (1 event) -- | 2026-04-30T12:23:42Z ! pattern E ioc_pattern_e_handoff_burst_present 3 distinct external IPs each minted cpsess + reached websocket Shell within 15-min window
| HEADLINE | verdict COMPROMISED (score 315) | defense lag 37d 9h LATE (first IOC 2026-03-25T09:43:19Z, defense up 37d 9h later)
<details>
<summary><b>Prüfungsreferenz + forensische Phasen + Bundle-Struktur</b> (klicken zum Erweitern)</summary>
| Check | Was es tut |
|---|---|
| `version` | `cpanel -V` vs. die veröffentlichte Liste gepatchter Builds - steuert `code_verdict` |
| `static-pattern` | Durchsucht `Cpanel/Session/*.pm` nach Post-Patch-Sentinel-Mustern (`no-ob:`-Decode-Zweig) |
| `cpsrvd-fingerprint` | Inspektion der cpsrvd-Binärdatei gegen Signaturen gepatchter Builds |
| `access-log` | Apache- und cpsrvd-Logs auf Exploit-Verkehrsmuster (`--no-logs` zum Überspringen) |
| `session-store` | `/var/cpanel/sessions/raw/`-Durchlauf: Anbieter-IOCs + 4-Wege-Kookkurrenz + Heuristik für gefälschte Zeitstempel (`--no-sessions` zum Überspringen) |
| `destruction` | Sonden für Muster A–G: `/root/sshd`-Verschlüsseler, MySQL-Wipe, BTC-Index, `nuclear.x86`, `sptadm`-Reseller, `__S_MARK__`-Harvester, verdächtige SSH-Schlüssel (`--no-destruction-iocs` zum Überspringen) |
| `probe` (opt-in) | Einzelner Marker-GET an `127.0.0.1:2087` - bestätigt, dass cpsrvd antwortet. Versucht den Bypass **nicht** |
**`--full`-forensische Phasen** (inline nach Erkennung ausgeführt):
| Phase | Was es tut |
|---|---|
| `defense` | Versieht jede umgesetzte Verteidigungsschicht mit einem Zeitstempel: cpanel-Patch, cpsrvd-Neustart nach Patch, Mitigate-Läufe, ModSec-Regeln, CSF/APF-Portschließungen, proxysub, `upcp`-Zusammenfassung |
| `offense` | Versieht jeden beobachteten Kompromittierungsindikator mit einem Zeitstempel (Muster A–G + Muster-X-CRLF-Bypass-Kette) |
| `reconcile` | Pro Indikator: War die relevante Verteidigung aktiv, als er zum ersten Mal auftrat? PRE-DEFENSE / POST-DEFENSE / POST-PARTIAL / UNDEFENDED + Zeitdifferenz |
| `bundle` | Tarball der Rohartefakte unter `/root/.ic5790-forensic/<TS>-<RUN_ID>/`, Modus `0700` |
**Bundle-Struktur** (`/root/.ic5790-forensic/<TS>-<RUN_ID>/`):```
manifest.txt host/uid/cpv/run_id/window/cap
sessions.tgz /var/cpanel/sessions/{raw,preauth} (filtered)
access-logs.tgz cpsrvd access + incoming_http_requests + error_log
+ global Apache access/error (NO domlogs)
system-logs.tgz /var/log/{secure,messages,audit/audit.log,auth.log}*
cpanel-state.tgz accounting.log + resellers + cpanel.config + api_tokens_v2
cpanel-users.tgz /var/cpanel/users/ (split out, per-account state)
persistence.tgz ssh keys + all cron tiers + systemd/init.d/profile.d
+ rc.local + root histories + passwd/group + sudoers
defense-state.tgz mitigate backups + csf/apf/modsec configs + updatelogs
ps.txt / connections.txt / iptables.txt
pattern-a-binary-metadata.txt only if /root/sshd present (metadata; binary NOT bundled)
user-histories/ per-user .bash_history (gated on --no-history)
Typisches Bundle auf einem stark ausgelasteten Host mit dem 90-Tage-Fenster: ~250 MB – 2 GB komprimiert.
Das 2-GB-Limit pro Tarball (--max-bundle-mb) verwirft übermäßig große Kandidaten einzeln.
Ein Laufprotokoll wird standardmäßig in /var/cpanel/sessionscribe-ioc/ geschrieben
(--no-ledger zum Deaktivieren). --chain-forensic / --chain-on-critical /
--chain-upload bleiben als v1.x-Kompatibilitätsaliase erhalten.
Snapshot-Test-Overrides für Offline-Forensik auf extrahierten Tarballs:
--root DIR, --version-string S, --cpsrvd-path P. Siehe --help für
die vollständige Flag-Liste.
sessionscribe-mitigate.sh - Mitigations-OrchestratorStandardmäßig schreibgeschützt (--check). Mit --apply wird der Zustand geändert.
Idempotent: Eine erneute Ausführung auf einem gesunden Host ist ein No-op. Mutationen schreiben
zeitgestempelte Sicherungen unter /var/cpanel/sessionscribe-mitigation/,
bevor sie eine Datei anfassen.```bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --apply
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --apply --only modsec --probe curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --only patch,preflight # pre-upcp gate
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --csv > host.csv curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --jsonl > host.jsonl
| Phase | Was es tut |
|---|---|
| `patch` | `cpanel -V` gegen die veröffentlichte Liste gepatchter Builds (inkl. EL6 11.86.0.41, EL6/CL6 110.0.103, Tier 124, WP² 136.1.7) |
| `preflight` | Entfernt `/etc/yum.repos.d/threatdown.repo`; stellt `epel-release` sicher; deaktiviert defekte Nicht-Basis-Repos, damit `upcp` nicht mittendrin abbricht |
| `upcp` | Falls ungepatcht, startet `/scripts/upcp --force --bg` |
| `proxysub` | Aktiviert `proxysubdomains` + die Variante für neue Konten; erstellt die httpd-Konfiguration neu |
| `csf` / `apf` / `runfw` | Entfernt cpsrvd-Ports (2082/2083/2086/2087/2095/2096) aus `TCP_IN`/`TCP6_IN`/`IG_TCP_CPORTS`; prüft die aktive iptables-INPUT-Kette |
| `apache` | `httpd` läuft + `security2_module` geladen |
| `modsec` | `modsec2.user.conf` enthält die Regeln `1500030` + `1500031`; stellt sie, falls fehlend, bereit (mit Zeitstempel versehenes Backup, `httpd -t`-Validierung, Graceful Reload) |
| `probe` (opt-in) | Führt `sessionscribe-remote-probe.sh` gegen `127.0.0.1` aus, um die Ablehnungen in der Praxis zu bestätigen |
CentOS / Alma / Rocky base/appstream/extras/updates/powertools-Repos
werden von `preflight` **niemals** deaktiviert, selbst wenn sie derzeit nicht erreichbar sind.
### Exit-Codes
| Exit | Bedeutung |
|---|---|
| 0 | sauber - gepatcht + Sicherheitslage ok, keine Aktion erforderlich |
| 1 | Behebung erfolgreich angewendet (`--apply` hat Änderungen vorgenommen) |
| 2 | manuelles Eingreifen erforderlich (warnt bei `--check`, schlägt fehl bei `--apply`) |
| 3 | Tool-Fehler (ungültige Argumente, fehlende Abhängigkeiten, bei `--apply` nicht root) |
Phasenauswahl: `--only LIST`, `--no-PHASE`, `--no-fw` (Abkürzung für
`--no-csf --no-apf --no-runfw`). Ausgabe: `--json` / `--jsonl` / `--csv`,
`-o FILE`. Siehe `--help` für die vollständige Liste der Flags.
### 60-Sekunden-Smoke-Check```bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --list-phases # surface the phase API
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --check # safe read-only audit
echo "exit=$?" # 0 on a non-cPanel host
Der Orchestrator erkennt einen Nicht-cPanel-Host und beendet sich sauber – was Idempotenz beweist, ohne dass ein Labor benötigt wird.
sessionscribe-remote-probe.sh - nicht-destruktive Fleet-ProbeUnterstützendes Begleitmaterial. Führt die vierstufige Kette nicht-destruktiv gegen ein Ziel aus: Preauth erzeugen → CRLF injizieren → raw→cache propagieren → über /json-api/version verifizieren und meldet sich dann aktiv ab. Das entscheidende Signal für den Befund ist der HTTP-Code in Stufe 4: 200 oder 5xx mit einem Lizenz-Body bedeutet VULN; 401 oder 403 bedeutet SAFE.
Jede Testsitzung wird mit einem nxesec_canary_<nonce>-Attribut für die forensische Bereinigung versehen, und es werden keine zustandsändernden API-Aufrufe durchgeführt. Gefälschte Sitzungen sind zwischen Stufe 3 und dem Logout in Stufe 5 für ~1–3s root-äquivalent – siehe Skript-Header für das vollständige Sicherheitsmodell.```bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh | bash -s -- --target 1.2.3.4
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh | bash -s -- --target 1.2.3.4 --proxy example.com
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh
| bash -s -- --csv $(awk '{print "--target "$1}' fleet.txt) > fleet.csv
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh | bash -s -- --target 1.2.3.4 --fingerprint-only
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh | bash -s -- --cleanup
Ausgabemodi: pretty (Standard), `-q`/`--quiet`, `--oneline`, `--csv`,
`--json`. Exit-Codes: `0` keine VULN gefunden, `1` nur nicht eindeutig, `2`
eine oder mehrere VULN. Siehe `--help` für die vollständige Flagliste einschließlich
der Semantik von `--auto-host-discover`, `--all`, `--fingerprint-only` und
des nur für Stufe 2 gedachten `--no-verify`-Modus (Legacy, erzeugt FPs auf gepatchten
Hosts).
---
## Begleitmaterial
### `modsec-sessionscribe.conf` - ModSecurity-Regelpaket
Wird automatisch von `mitigate.sh --apply --only modsec` bereitgestellt. Manuelle Installation:```bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/modsec-sessionscribe.conf \
| sudo tee /etc/apache2/conf.d/modsec/modsec2.user.conf >/dev/null
sudo apachectl -t && sudo /usr/local/cpanel/scripts/restartsrv_httpd
| Regel | Oberfläche | Aktion |
|---|---|---|
1500030 | CRLF innerhalb des dekodierten Authorization: Basic-Payloads | deny, alle Quellen, alle Pfade |
1500031 | whostmgrsession-Cookie ohne gültiges ,OBHEX-Suffix | deny (Defense-in-Depth) |
1500010 | Authorization: WHM auf /json-api/, /execute/, /acctxfer*/ | deny, wenn Quelle nicht in der Vertrauensliste |
1500020 | Authorization: WHM auf WebSocket-Dispatch-Familie | deny, wenn Quelle nicht in der Vertrauensliste |
1500021 | Authorization: WHM auf SSE-Dispatch-Pfad | deny, wenn Quelle nicht in der Vertrauensliste |
ID-Bereich reserviert: 1500000–1500099. WHM-Token-Regeln verwenden @ipMatch
gegen eine vom Betreiber definierte Vertrauensliste — bearbeiten Sie die CIDRs oben in
der Datei vor der Bereitstellung.
[!IMPORTANT] Diese Regeln laufen innerhalb von Apache.
cpsrvdlauscht direkt auf 2082/2083/2086/2087/2095/2096 und ist unabhängig von Apache erreichbar. Kombinieren Sie das Regelpaket mit Firewall-Regeln, die die cpsrvd-Ports auf Management-CIDRs beschränken.
sessionscribe-revsnap.sh - RE-Snapshot-SammlerErfasst einen Tarball pro Stufe (Binaries, Strings, Dynsym, Disasm, Perl-
Module, Laufzeit-Layout) für Binary-Diffing über cPanel-Upgrades hinweg.
Basiert auf upcp, um Pre-/Post-Patch-Paare zu erfassen.```bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-revsnap.sh | bash
/scripts/upcp --force curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-revsnap.sh | bash
Generalisiert über SessionScribe hinaus: Jede zukünftige cpsrvd-CVE landet auf ungefähr derselben Angriffsfläche, und ein Tarball-Paar für den Pre-Patch- und den gepatchten Build ist der Unterschied zwischen Stunden und Tagen an Analyse. Siehe den [Forschungsartikel](https://rfxn.com/research/cpanel-sessionscribe-cve-2026-41940) für den vollständigen RE-Walkthrough.
---
## Flotten-Nutzung
> [!TIP]
> Jedes Artefakt erzeugt strukturierte Ausgabe (`--json`, `--jsonl`, `--csv`)
> mit `host`, `os`, `cpanel_version`, `ts` in jedem Datensatz. Entwickelt
> für das `pdsh | jq`- oder `ansible -m script`-Roll-up über Hunderte von
> Hosts in einem Durchgang.
Dieselbe curl-piped-bash-Grundtechnik — lass jeden Host das neueste Skript direkt holen und ausführen:```bash
IOC=https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh
MIT=https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh
PRB=https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh
# IOC scan across fleet, JSONL to SIEM
for h in $(cat fleet.txt); do
ssh "$h" "curl -fsSL $IOC | bash -s -- --jsonl --quiet"
done | jq -c '.' > fleet-ioc.jsonl
# kill-chain reconciliation across fleet (no bundles on broad sweep)
ansible -i hosts cpanel -m shell \
-a "curl -fsSL $IOC | bash -s -- --full --no-bundle --jsonl" > fleet-forensic.jsonl
jq -r 'select(.phase=="summary" and .key=="verdict"
and .note=="COMPROMISED_PRE_DEFENSE") | .host' \
fleet-forensic.jsonl > pre-defense-hosts.txt
# bundle collection on the pre-defense subset
ansible -i pre-defense-hosts.txt all -m shell \
-a "curl -fsSL $IOC | bash -s -- --full --jsonl --bundle-dir /root/.ic5790-forensic"
# mitigation posture roll-up
pdsh -w cpanel-fleet "curl -fsSL $MIT | bash -s -- --jsonl --quiet" \
| jq -c 'select(.severity != "info")' > fleet-mitigate.jsonl
# remote probe sweep - exit 2 on any VULN (run from operator workstation)
curl -fsSL $PRB | bash -s -- --csv --quiet \
$(awk '{print "--target "$1}' fleet.txt) > fleet-probe.csv
Die Sonde ist unabhängig flottensicher (Canary-getaggte Sitzungen, aktives
Abmelden, keine zustandsändernden API-Aufrufe). Die On-Host-Skripte respektieren
--quiet + structured-output-Flags, sodass stdout parser-sauber ist.
Vier HTTP-Anfragen, kein Auth, keine Voraussetzungen:```mermaid sequenceDiagram autonumber actor A as attacker participant C as cpsrvd participant S as session file A->>C: POST /login/?login_only=1 with user=root, pass=wrong C-->>A: Set-Cookie · whostmgrsession=NAME,OBHEX A->>C: GET / · Authorization Basic b64(root:x + CRLF payload) · Cookie minus OBHEX C->>S: writes pass=x, user=root, hasroot=1, ... (CRLFs land verbatim) C-->>A: HTTP 307 · Location /cpsess[10digits]/ A->>C: GET /scripts2/listaccts · cookie only C->>S: propagate raw to cache · forged keys now readable C-->>A: 401 token denied (side-effect already done) A->>C: GET /cpsess[token]/json-api/version C-->>A: 200 OK means VULN · 403 means SAFE
Das Verdikt ist der HTTP-Code bei Anfrage 4. Die Sitzungsdatei auf der Festplatte unter
`/var/cpanel/sessions/raw/<sessname>` ist das einzige forensische Artefakt
nach der Tat. Die vollständige Primitive (die beiden zusammensetzenden Asymmetrien —
`filter_sessiondata` nicht auf jedem Schreibpfad, der Encoder bricht bei
fehlendem `ob_part` vorzeitig ab) und das architektonische Argument für die Durchsetzung
am Proxy-Endpunkt finden sich im
[Forschungsartikel](https://rfxn.com/research/cpanel-sessionscribe-cve-2026-41940).
---
## Indikatoren für eine Kompromittierung
Form der gefälschten Sitzungsdatei (`/var/cpanel/sessions/raw/<sessname>` nach der
Ausnutzung):```
local_port=2087
hasroot=1
hulk_registered=1
pass=x
origin_as_string=address=127.0.0.1,app=whostmgrd,method=badpass
token_denied=1
local_ip_address=127.0.0.1
external_validation_token=cS9C19OfV0hCA4uD
cp_security_token=/cpsess6844364556
ip_address=127.0.0.1
user=root
tfa_verified=1
successful_internal_auth_with_timestamp=9999999999
port=39040
login_theme=cpanel
Eine normale Preauth-Sitzung enthält niemals pass=, hasroot=1,
user=root, tfa_verified=1 oder
successful_internal_auth_with_timestamp=. Jede dieser Kombinationen zusammen mit
origin_as_string=…method=badpass ist diagnostisch. Ein gefälschter Zeitstempelwert
jenseits von now+365d (z. B. 9999999999) ist unabhängig davon diagnostisch.```bash
for f in /var/cpanel/sessions/raw/*; do
[ -f "$f" ] || continue
if grep -q '^token_denied=' "$f"
&& grep -q '^cp_security_token=' "$f"
&& grep -q '^origin_as_string=.*method=badpass' "$f"; then
echo "IOC0 hit: $f"
fi
done
Access-log-Signal: erfolgreiche `200`/`302`/`307`-Antworten auf
`/json-api/`, `/execute/` oder `/scripts2/`-Pfaden von Nicht-Baseline-
Quell-IPs ohne vorheriges `/login/` 200 im selben Sitzungsfenster.
---
## Betroffene Builds```
11.86.0.41 (EL6/CL7) 11.110.0.97 11.118.0.63 11.124.0.35
11.126.0.54 11.130.0.19 11.132.0.29 11.134.0.20
11.136.0.5 110.0.103 (EL6/CL6 from .50)
WP Squared: 136.1.7
Von der Hersteller-Patchliste ausgeschlossene Tiers haben keinen In-Place-Fix: 112, 114, 116, 120, 122, 128. Hosts auf diesen Tiers müssen auf eine gepatchte Hauptserie aktualisiert oder migriert werden, oder ihre cpsrvd-Listener müssen bis dahin per Firewall abgeschottet werden.
11.86.0.41 (EL6/CL7) wurde in der Advisory-Revision 04/29 hinzugefügt; 11.130
wurde in derselben Revision von .18 auf .19 angehoben. Eine spätere
Revision fügte 11.124.0.35 hinzu (womit die bisherige Lücke auf Tier 124 geschlossen wurde) und
110.0.103 als direktes Upgrade-Ziel für EL6/CL6-Hosts, die sich noch auf
v110.0.50 befinden.
Sofort
sessionscribe-ioc-scan.sh flottenweit aus. Ein gepatchter Host kann
trotzdem kompromittiert sein.Weiterführend
modsec-sessionscribe.conf in modsec2.user.conf bereit, wobei die
@ipMatch-Vertrauensliste gesetzt ist.Das architektonische Argument für die Proxy-Endpoint-Durchsetzung ist das abschließende Drittel des Forschungsartikels.
cpsrvd, cpsrvd.so oder
Cpanel/Session/*.pm nicht. Der von cPanel herausgegebene Backport für Ihren Tier ist
der eigentliche Fix.proxysub- und Firewall-Phasen des Orchestrators sowie das
ModSec-Regelpaket reduzieren den Blast-Radius; Upgrade oder Migration ist die einzige
dauerhafte Antwort.nxesec_canary_<nonce>-Attribut
zur Bereinigung und meldet sich aktiv ab.ioc-scan findet Artefakte früherer
Ausnutzung; es behebt sie nicht. Behandeln Sie sein COMPROMISED-Urteil
als Auslöser für eine vollständige IR, nicht als Abschluss.[!TIP] Einen Fehler gefunden, IOC übersehen, False Positive oder Betriebs-Feedback? GitHub-Issue eröffnen - Bugmeldungen, in freier Wildbahn gesehene IOC-Varianten, Erkennungslücken auf gepatchten/ungepatchten Hosts, False Positives der ModSec-Regeln und allgemeines Operator-Feedback sind alle willkommen.
Vertrauliche Offenlegungen (Live-Exploitation-Beweise, Kundendaten, neuartige, noch nicht öffentliche Exploit-Ketten) sollten über Keybase oder E-Mail erfolgen, nicht über GH-Issues.
GPL v2. Siehe die einzelnen Dateiköpfe.
Erstellt während der SessionScribe-Incident-Response - Ryan MacDonald, R-fx Networks.