
Questo documento presenta l'analisi della vulnerabilità CVE-2025-2825, che colpisce il componente server di CrushFTP, una soluzione commerciale per la gestione e il trasferimento di file (FTP, SFTP, HTTP/S, interfacce simili a S3, ecc.).
Il difetto è classificato come authentication bypass (bypass dell'autenticazione) che consente a un attaccante remoto non autenticato di ottenere privilegi di amministratore. Lo sfruttamento riuscito garantisce accesso con privilegi crushadmin, visualizzazione e modifica dei file, gestione degli account ed esecuzione di operazioni amministrative tramite l'interfaccia web e l'API di CrushFTP.
Versioni interessate segnalate (secondo advisory pubblici e report dei ricercatori):
⚠️ Nota: in alcune pubblicazioni si trovano duplicati e sovrapposizioni degli identificativi CVE (ad esempio, CVE-2025-31161).
Analizzare passo dopo passo la vulnerabilità e dimostrare l'intero ciclo di ricerca, che include:
Secondo i report pubblici, la vulnerabilità presenta un rischio critico:
Sono critiche le istanze con queste caratteristiche:
CrushFTP (qualsiasi edizione con interfaccia web).CrushFTP implementa il supporto a un'API simile a S3. Per l'autenticazione viene utilizzato l'header Authorization nella forma:
Authorization: AWS4-HMAC-SHA256 Credential=<AccessKey>/<Date>/<Region>/s3/aws4_request, SignedHeaders=<Headers>, Signature=<Signature>
Il server estrae l'AccessKey dalla sezione Credential e dovrebbe verificare la firma. Tuttavia, nel codice è stato commesso un errore nella gestione del flag lookup_user_pass.
// ServerSessionHTTP.java, metodo loginCheckHeaderAuth()
if (this.headerLookup.containsKey("AUTHORIZATION") &&
this.headerLookup.getProperty("AUTHORIZATION").trim().startsWith("AWS4-HMAC")) {
boolean lookup_user_pass = true; // ← errore critico
if (s3_username3.indexOf("~") >= 0) {
user_pass = user_name.substring(user_name.indexOf("~") + 1);
user_name = user_name.substring(0, user_name.indexOf("~"));
lookup_user_pass = false;
}
if (this.thisSession.login_user_pass(
lookup_user_pass,
false,
user_name,
lookup_user_pass ? "" : user_pass)) {
// Autenticazione riuscita
}
}
Il flag lookup_user_pass viene passato direttamente come anyPass:
if (anyPass && user.getProperty("username").equalsIgnoreCase(the_user)) {
return user; // autenticazione senza verifica della password
}
In sintesi:
Se il nome utente è specificato senza il simbolo ~, il flag rimane true.
La verifica della password non viene eseguita.
Un attaccante può autenticarsi indicando solo un nome utente esistente (ad esempio, crushadmin).
Insieme a un cookie CrushAuth formalmente valido e al parametro c2f, ciò consente di bypassare l'autenticazione e ottenere accesso amministrativo.
Nella versione 11.3.1 e successive, gli sviluppatori:
Hanno aggiunto il parametro s3_auth_lookup_password_supported (impostato di default su false), che blocca lo scenario vulnerabile.
Hanno introdotto controlli anticipati sul nome utente con ~.
Hanno separato la logica dei flag, eliminando la sostituzione lookup_user_pass → anyPass.
Raccomandazione: aggiornare immediatamente CrushFTP alla versione 11.3.1+ oppure applicare la soluzione alternativa disabilitando s3_auth_lookup_password_supported.
Lo sfruttamento di CVE-2025-2825 è piuttosto semplice e non richiede una preparazione complessa. L'attaccante deve solo inviare una richiesta HTTP appositamente predisposta contenente due elementi chiave:
Authorization in formato AWS S3, con un nome utente esistente corretto (campo Credential con AccessKey/username).CrushAuth nel formato atteso e parametro c2f nell'URL/nel corpo della richiesta, i cui valori corrispondono logicamente (il formato del cookie deve corrispondere alla struttura prevista dal server).Se il server è vulnerabile (versione compresa tra 10.0.0—10.8.3 o 11.0.0—11.3.0 e patch correttiva non applicata), questa combinazione fa sì che il gestore dell'autenticazione segua il percorso vulnerabile, in cui il flag di ricerca della password (lookup_user_pass) viene interpretato come "qualsiasi password è accettata" e l'utente viene autenticato solo tramite il nome, senza verifica della password.
Nota importante:
Lo sfruttamento di questa vulnerabilità richiede in genere l'invio di due richieste consecutive. La prima, la cosiddetta richiesta di "riscaldamento" (warm-up), avvia il processo di autenticazione vulnerabile sul server. Un segno caratteristico che il server è entrato nello stato desiderato è la ricezione di un errore
502 Bad Gatewayo semplicemente il superamento del timeout. Subito dopo viene inviata la seconda richiesta, quella principale, che esegue l'azione utile (ad esempio, la creazione di un utente) mentre il server si trova nello stato vulnerabile all'attacco.
GET /WebInterface/function/?command=getUserList&serverGroup=MainUsers&c2f=1111 HTTP/1.1
Host: target-server:8080
Cookie: CrushAuth=1743113839553_vD96EZ70ONL6xAd1DAJhXMZYMn1111
Authorization: AWS4-HMAC-SHA256 Credential=crushadmin/
Per il test ho utilizzato il lab recentemente pubblicato su HTB — Soulmate, che richiede appunto lo sfruttamento di CrushFTP.

Grazie a questa vulnerabilità, è possibile aggiungere un nuovo utente con privilegi di amministratore tramite il comando setUserItem. A tale scopo, eseguire new_user.py
python3 new_user.py --target_host http://ftp.soulmate.htb/ --port 80 --target_user crushadmin --new_user literide --password literide
Parsing dell'header Authorization: Quando il server vede un header di autorizzazione in formato simile a S3 (AWS4-HMAC...), estrae dal campo Credential l'identificativo del client (AccessKey / username). In questa fase il server ottiene una stringa che considera come nome utente — un valore identificativo utilizzato successivamente nella logica di autenticazione.
Il flag lookup_user_pass e il suo ruolo:
Nel codice esiste un flag booleano lookup_user_pass che dovrebbe indicare da dove prendere la password durante la verifica:
Nello scenario normale, il flag aiuta a decidere: usare la password passata nella richiesta oppure recuperarla dall'archivio utenti;
Tuttavia, a causa di un errore di implementazione, questo stesso flag viene passato successivamente alla funzione di verifica e lì interpretato in modo diverso — come un segnale che consente di saltare la verifica della password (in pratica: "anyPass").
Passaggio del flag lungo la catena di chiamate:
Percorso approssimativo: ServerSessionHTTP.loginCheckHeaderAuth() → Session.login_user_pass(...) → UserTools.ut.verify_user(...). In ingresso il flag determina il comportamento, e in verify_user porta a un ritorno anticipato dell'oggetto utente trovato senza confronto della password, se il nome coincide. Questo produce il bypass del controllo di autenticazione: il server "riconosce" l'utente dal nome e lo considera autenticato.
Elementi correlati (cookie / c2f):
Nelle analisi pubbliche è stato indicato che il gestore si aspetta un formato corretto di cookie/parametri per associare la richiesta alla sessione/contesto. Tuttavia, il difetto chiave risiede nell'errore logico di gestione di lookup_user_pass; gli altri elementi servono solo ad aiutare la richiesta a superare i rami standard di elaborazione.
Causa principale
Credential, ciò faceva sì che la presenza di un nome utente corretto fosse sufficiente per ottenere le credenziali dell'utente senza verifica della password.Template passivo:
Poiché nella maggior parte dei servizi web non è possibile determinare la versione esatta di CrushFTP, questo template verifica semplicemente se il servizio utilizza CrushFTP.
È preferibile usarlo in combinazione con il template attivo
Template attivo:
Il template attivo verifica se è possibile eseguire il comando getUserList.

Script multithread
Lo script funziona in modo simile al template attivo, ma è molto più veloce e supporta la verifica di più host contemporaneamente.
python3 scan.py -t http://ftp.soulmate.htb/ -p 80 -u crushadmin

Per ridurre i rischi associati a CVE-2025-31161, si raccomanda di adottare le seguenti misure:
Aggiornamento immediato:
Applicazione della soluzione alternativa (se l'aggiornamento non è possibile):
s3_auth_lookup_password_supported su false. Questo disattiva la logica di autenticazione vulnerabile senza aggiornare l'intero prodotto.Misure di compensazione del rischio:
AWS4-HMAC-SHA256 nell'header Authorization, soprattutto se non si utilizza l'integrazione S3.Authorization anomali verso endpoint non destinati all'API S3.