
Il tuo host Linux è esposto a CVE-2026-98432?
Verifica se un host Linux può essere esposto a CVE-2026-98432, la use-after-free nell'handshake TCP IPv4 del kernel. Parte di shouldipanic.ch.
Un SYN che trasporta opzioni IPv4 (Record Route, Timestamp) raggiunge codice che legge le opzioni dopo che potrebbero essere già state liberate. È sufficiente qualsiasi porta TCP IPv4 aperta, nessun login necessario. È presente in ogni kernel dalla 4.4 (2016) fino alla release corretta di ciascun ramo: 5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10, 7.3. Il CNA del kernel la valuta 9.8; è stato segnalato un exploit funzionante per root remoto contro server con listener MPTCP (non pubblicato). La correzione è invisibile sul filo: un kernel corretto risponde esattamente come uno non corretto.
Questo determina ciò che ciascuna modalità può dire:
--on-host legge il kernel in esecuzione sulla macchina stessa: la sua versione,
il changelog del pacchetto e se un kernel più recente attende un riavvio.Server e mostra se quella distribuzione
ha già rilasciato un kernel corretto. È un forte indizio, non un verdetto: dietro un
reverse proxy o all'interno di un container il kernel appartiene a un'altra macchina.kernel98scan è disponibile in due forme:
kernel98scan.py: un singolo file Python senza dipendenze. Su un host,
--on-host fornisce il verdetto reale; puntato a indirizzi esegue il fingerprinting della distribuzione
su intervalli IP, con una scansione delle porte e il rilevamento dei vhost.
curl -LO https://github.com/akaihigurashi/kernel98scan/releases/latest/download/kernel98scan.py
python3 kernel98scan.py --on-host # real verdict for THIS machine
Python 3.8 o successivo, nessuna installazione necessaria. Esempi:
python3 kernel98scan.py --on-host # read the running kernel
python3 kernel98scan.py 203.0.113.10 # outside: distribution + fix status
python3 kernel98scan.py 203.0.113.0/24 # a whole range from outside
python3 kernel98scan.py 203.0.113.10 --ip-options # + do IP-options packets get through?
python3 kernel98scan.py 203.0.113.10 -o out.csv # CSV output
python3 kernel98scan.py -h # all options
Sull'host (--on-host, codice di uscita 2 / 1 / 0 / 3):
| Stato | Significato |
|---|---|
VULNERABLE | Nulla mostra la correzione nel kernel in esecuzione |
CHECK | È installato un kernel corretto, ma quello vecchio è ancora in esecuzione: riavviare |
FIXED | Il changelog del kernel nomina la CVE, oppure un kernel upstream semplice è alla versione corretta |
I kernel dei vendor (Ubuntu, RHEL, Proxmox) applicano le correzioni tramite backport su numeri di versione vecchi, quindi
per essi conta solo il changelog. Mostra anche se MPTCP è attivo (l'exploit
segnalato passa attraverso i listener MPTCP) e tcp_migrate_req.
Dall'esterno:
| Stato | Significato |
|---|---|
POSSIBLY VULNERABLE | Il banner mostra una distribuzione Linux: o non ha ancora un kernel corretto (Ubuntu, RHEL e le loro ricompilazioni oggi) oppure ne ha uno, che deve essere installato e avviato |
UNKNOWN | La distribuzione non è visibile, oppure risponde un proxy/CDN |
NOT LINUX | L'header Server punta a un host non Linux |
VULNERABLE e PATCHED non vengono mai segnalati dall'esterno. Lo stato della correzione per
distribuzione è una tabella in check.py (FIX_STATUS, FIXED_TABLE),
aggiornata con ogni rilascio dei vendor.
| Opzione | Cosa fa |
|---|---|
--on-host | Legge il kernel in esecuzione su questa macchina e fornisce un verdetto reale |
--ip-options | Una connessione il cui SYN trasporta un'opzione IP Record-Route (vedi sotto) |
-o FILE | Scrive inoltre tutti i risultati in CSV |
-a / -v | Mostra i risultati nascosti / mostra le prove |
-d | Debug: ogni richiesta, header e corrispondenza |
-q | Nessun banner (per gli script) |
-V | Stampa la versione |
-h | Tutte le opzioni |
--ip-options (opt-in, solo da riga di comando)Apre una connessione normale e una il cui SYN trasporta un'opzione IP Record-Route
vuota, e segnala se tali pacchetti raggiungono l'host (reach), vengono scartati
lungo il percorso (filtered) oppure la porta è chiusa (noport). È la forma di pacchetto
attraverso cui si raggiunge il bug, quindi è disattivata per impostazione predefinita e non viene mai eseguita sulla
pagina web: usala sui tuoi host, ad esempio per confermare che il tuo firewall
scarta le opzioni IP. Una singola connessione non può vincere la race condition di cui necessita il bug, e un
risultato filtered può essere dovuto a qualsiasi rete intermedia.
nft add table ip cve98432
nft add chain ip cve98432 pre '{ type filter hook prerouting priority -300; }'
nft add rule ip cve98432 pre meta l4proto tcp ip hdrlength != 5 drop
sysctl -w net.mptcp.enabled=0 # if you don't need MPTCP
Elimina i pacchetti TCP IPv4 che trasportano qualsiasi opzione IP. Non è persistente dopo i riavvii e non sostituisce il kernel corretto.
docker run -d --name kernel98scan --restart unless-stopped \
-p 127.0.0.1:8092:8092 \
-e PANIC_ORIGIN=https://kernel98scan.example.ch \
-v kernel98scan-data:/data \
ghcr.io/akaihigurashi/kernel98scan:latest
Oppure con Compose: scarica docker-compose.yml, imposta
PANIC_ORIGIN, poi esegui docker compose up -d. Il container è in ascolto solo su localhost;
metti davanti ad esso un reverse proxy con TLS
(esempio nginx).
| Variabile | Predefinito | Scopo |
|---|---|---|
PANIC_ORIGIN | – | Indirizzo pubblico. Le richieste provenienti da altre origini vengono rifiutate. Impostala. |
PANIC_OPERATOR / PANIC_CONTACT | – | Sezione di contatto opzionale in fondo alla pagina |
PANIC_IMPRINT_URL | – | Link opzionale a un'impronta esistente |
PANIC_TRUSTED_PROXY | 127.0.0.1,::1 | Proxy di cui è attendibile l'header X-Real-IP |
PANIC_DENY_HOSTS / PANIC_DENY_IPS | – | Domini / indirizzi da non controllare mai |
PANIC_AUDIT_DIR | /data/audit | File di log di audit giornalieri |
PANIC_RETENTION_DAYS | 30 | I file di audit più vecchi di questo valore vengono eliminati |