Vérificateur d'état de correctif sûr et non authentifié pour Check Point CPM RCE CVE-2026-93616 ; sonde la connexion SOAP UpgradeSvcRemote sur TCP 19009 sans exploitation.
Une vérification non authentifiée de l'état de correctif pour CVE-2026-93616, la traversée
de répertoire non authentifiée dans le serveur Check Point Security Management (CPM) qui
atteint Runtime.exec(), corrigée dans
sk1000171 le 2026-09-22. CWE-22,
CVSS 9.8 Critique (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H), exploitée en
conditions réelles. Check Point est le CNA ; le problème a été identifié à partir d'une
exploitation en conditions réelles plutôt que d'un rapport externe.
Le serveur CPM expose des services web SOAP sur TCP 19009. La méthode de connexion
UpgradeSvcRemote loginAsApplicationReadOnlyPublicSession transmet son paramètre
targetVersion dans un chemin de système de fichiers passé à Runtime.exec sans
validation, de sorte qu'un appelant non authentifié peut rediriger l'exécution vers un
script choisi par l'attaquant. Le correctif ajoute un motif Bean Validation à
targetVersion qui rejette un séparateur de chemin.
Le script indique si ce correctif est présent sur chaque cible. Il envoie un seul caractère
illégal dans targetVersion, jamais une séquence de traversée, et ne s'authentifie pas, ne
téléverse pas de fichier et n'exécute rien sur la cible. Un résultat autre que VULNERABLE
n'indique pas à lui seul qu'une cible est corrigée ; voir
Interprétation des résultats non vulnérables.
Les versions en fin de support sont traitées explicitement. Sur les trains antérieurs à
R81.10, la méthode de connexion prend moins de paramètres, de sorte que la sonde principale
est rejetée par le démarshalling XML avant que l'état du correctif puisse être lu. Lorsqu'un
serveur Check Point rejette la sonde de cette manière, le script envoie un appel de suivi
avec l'ancienne forme de paramètres. Si la méthode de connexion répond alors, la cible est
une version affectée pour laquelle Check Point n'a jamais publié de correctif, et le verdict
est VULNERABLE avec la raison affected-eos-no-fix. L'appel de suivi ne contient ni
mode ni targetVersion, donc lui non plus n'envoie rien à valider ni rien à traverser.
Cela comble une lacune dans laquelle un serveur hérité serait autrement lu comme non
identifiable.
# 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+, bibliothèque standard uniquement — aucun paquet tiers.
Exécutez l'outil contre les serveurs de management (Security Management, Multi-Domain Management, Log, Multi-Domain Log et SmartEvent), pas contre les passerelles. La vérification cible l'écouteur SOAP CPM sur TCP 19009, que les passerelles n'exécutent pas.
| Flag | Description |
|---|---|
TARGET | One or more HOST[:PORT] targets; the port defaults to 19009 |
-f, --targets-file FILE | Read targets from a file (one per line; # comments) |
-p, --port PORT | Default port when a target omits one (default: 19009) |
--timeout SECS | Per-probe timeout (default: 15) |
--workers N | Concurrent targets (default: 16); output stays in input order |
-b, --brief | Single aligned line per target, for scanning many hosts |
--json | Emit structured JSON, including the probe markers per target |
--no-color | Disable coloured output (also honours NO_COLOR and non-TTY) |
Serveur vulnérable (sortie par défaut ; le marqueur [!] et VULNERABLE sont affichés en
rouge sur 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
Serveur corrigé :
$ ./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 serveur de management Check Point qui a répondu mais n'a pas traité la méthode de connexion, de sorte que l'état du correctif n'a pas pu être lu :
$ ./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
Plusieurs cibles avec --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
Sortie JSON avec --json. Les marqueurs de sonde sont inclus afin que le verdict puisse
être vérifié par rapport à ce que la réponse contenait réellement :
$ ./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": ""
}
}
]
La vérification est destinée à être utilisée contre des systèmes de production :
!) dans targetVersion ; ce seul caractère suffit à déclencher la
validation de la version corrigée, et il ne peut pas s'échapper d'un répertoire comme le
ferait un séparateur de chemin. La sonde de suivi héritée ne contient aucun
targetVersion du tout.domainId, de sorte que sur un
serveur non corrigé la méthode lève une NullPointerException lors de la construction de
ses paramètres, avant que ReflectionUtils n'atteigne Runtime.exec. Même sans cela, la
valeur de la sonde se résout en un répertoire qui n'existe pas, donc il n'y a aucun script
à exécuter. La sonde héritée n'envoie qu'un nom d'application et un délai d'attente, elle
n'a donc rien à partir de quoi construire un chemin.