
Verificatore sicuro e non autenticato dello stato delle patch per Check Point CPM RCE CVE-2026-93616; sonda il login SOAP di UpgradeSvcRemote su TCP 19009 senza sfruttarlo.
Un controllo non autenticato dello stato delle patch per CVE-2026-93616, il directory
traversal non autenticato nel server Check Point Security Management (CPM) che raggiunge
Runtime.exec(), corretto in
sk1000171 il 2026-09-22. CWE-22,
CVSS 9.8 Critico (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H), sfruttato in
the wild. Check Point è il CNA; il problema è stato identificato dallo sfruttamento
in-the-wild piuttosto che da una segnalazione esterna.
Il server CPM espone servizi web SOAP su TCP 19009. Il metodo di login
loginAsApplicationReadOnlyPublicSession di UpgradeSvcRemote inoltra il suo parametro
targetVersion in un percorso del filesystem passato a Runtime.exec senza validazione,
così un chiamante non autenticato può reindirizzare l'esecuzione verso uno script scelto
dall'attaccante. La correzione aggiunge un pattern di Bean
Validation a targetVersion che rifiuta un separatore di percorso.
Lo script segnala se quella correzione è presente su ciascun target. Invia un singolo
carattere illegale in targetVersion, mai una sequenza di traversal, e non autentica,
non carica un file, né esegue nulla sul target. Un risultato diverso da VULNERABLE non
indica di per sé che un target sia correttamente patchato; vedi
Interpretare i risultati non vulnerabili.
Le build a fine supporto sono gestite esplicitamente. Sui treni precedenti a R81.10 il metodo di login
accetta meno parametri, quindi la sonda primaria viene rifiutata dall'unmarshalling XML prima che lo stato della patch possa essere letto. Quando un server Check Point rifiuta la sonda in quel modo, lo script invia
una chiamata di follow-up nella forma del parametro più vecchia. Se il metodo di login
allora viene dispatchato, il target è una build affetta per cui Check Point non ha mai pubblicato una correzione, e il verdetto è
VULNERABLE con la motivazione affected-eos-no-fix. La chiamata di follow-up non porta alcun mode
né alcun targetVersion, quindi anch'essa non invia nulla da validare e nulla da attraversare. Questo
colma una lacuna in cui un server legacy altrimenti risulterebbe non identificabile.
# single target (port defaults to 19009)
./cve_2026_93616_check.py mgmt.example.com
# explicit port
./cve_2026_93616_check.py mgmt.example.com:19009
# several targets
./cve_2026_93616_check.py mds-a.example.com mds-b.example.com
# scan a list, one target per line ('#' comments allowed), compact output
./cve_2026_93616_check.py -f targets.txt --brief
# machine-readable output for pipelines
./cve_2026_93616_check.py -f targets.txt --json > results.json
Python 3.8+, solo libreria standard — nessun pacchetto di terze parti.
Esegui lo strumento contro i server di gestione (Security Management, Multi-Domain Management, Log, Multi-Domain Log e SmartEvent), non contro i gateway. Il controllo prende di mira il listener SOAP CPM su TCP 19009, che i gateway non eseguono.
| Flag | Descrizione |
|---|---|
TARGET | Uno o più target HOST[:PORT]; la porta predefinita è 19009 |
-f, --targets-file FILE | Legge i target da un file (uno per riga; commenti #) |
-p, --port PORT | Porta predefinita quando un target ne omette una (predefinita: 19009) |
--timeout SECS | Timeout per sonda (predefinito: 15) |
--workers N | Target concorrenti (predefinito: 16); l'output resta nell'ordine di input |
-b, --brief | Una singola riga allineata per target, per scansionare molti host |
--json | Emette JSON strutturato, inclusi i marcatori delle sonde per target |
--no-color | Disabilita l'output colorato (rispetta anche NO_COLOR e non-TTY) |
Server vulnerabile (output predefinito; il marcatore [!] e VULNERABLE sono mostrati in rosso su
un TTY):
$ ./cve_2026_93616_check.py mgmt.example.com
[!] mgmt.example.com:19009: VULNERABLE [dispatched-without-validation]
loginAsApplicationReadOnlyPublicSession accepted an illegal targetVersion and dispatched it; the fix's input validation is absent
Server corretto:
$ ./cve_2026_93616_check.py mgmt-dr.example.com
[+] mgmt-dr.example.com:19009: PATCHED [validation-constraint-present]
the server rejected an illegal targetVersion with the input-validation constraint added by the fix (Jumbo Hotfix R82.10 Take 45 or equivalent)
Un server di gestione Check Point che ha risposto ma non ha dispatchato il metodo di login, quindi lo stato della patch non poteva essere letto:
$ ./cve_2026_93616_check.py log.example.com
[?] log.example.com:19009: INCONCLUSIVE [cpm-no-dispatch]
a Check Point management fault came back, but the UpgradeSvcRemote login method did not dispatch, so patch state could not be read
Target multipli con --brief:
$ ./cve_2026_93616_check.py -f targets.txt --brief; echo "exit: $?"
VULNERABLE mgmt.example.com:19009 dispatched-without-validation
PATCHED mgmt-dr.example.com:19009 validation-constraint-present
INCONCLUSIVE log.example.com:19009 cpm-no-dispatch
UNAFFECTED web.example.com:19009 not-cpm
ERROR offline.example.com:19009 unreachable
exit: 1
Output JSON con --json. I marcatori delle sonde sono inclusi così che il verdetto possa essere verificato
rispetto a ciò che la risposta conteneva effettivamente:
$ ./cve_2026_93616_check.py mgmt.example.com mgmt-dr.example.com --json
[
{
"target": "mgmt.example.com:19009",
"verdict": "VULNERABLE",
"reason": "dispatched-without-validation",
"detail": "loginAsApplicationReadOnlyPublicSession accepted an illegal targetVersion and dispatched it; the fix's input validation is absent",
"http_status": 500,
"probe": {
"http_status": 500,
"saw_validation": false,
"saw_dispatch": true,
"saw_cpm": true,
"note": ""
}
},
{
"target": "mgmt-dr.example.com:19009",
"verdict": "PATCHED",
"reason": "validation-constraint-present",
"detail": "the server rejected an illegal targetVersion with the input-validation constraint added by the fix (Jumbo Hotfix R82.10 Take 45 or equivalent)",
"http_status": 500,
"probe": {
"http_status": 500,
"saw_validation": true,
"saw_dispatch": true,
"saw_cpm": true,
"note": ""
}
}
]
Il controllo è pensato per l'uso contro sistemi di produzione:
!) in targetVersion; quel singolo carattere è sufficiente a far scattare la
validazione della build corretta, e non può uscire da una directory come farebbe un separatore di percorso. La sonda
di follow-up legacy non porta alcun targetVersion.domainId, quindi su un server non corretto
il metodo solleva una NullPointerException mentre costruisce i suoi parametri, prima che
ReflectionUtils raggiunga Runtime.exec. Anche senza questo, il valore della sonda si risolve
in una directory che non esiste, quindi non c'è alcuno script da eseguire. La sonda legacy invia
solo un nome di applicazione e un timeout, quindi non ha nulla da cui costruire un percorso.