
SSRF tramite socket TCP grezzi di smtplib che bypassano la blocklist HTTP in AutoGPT SendEmailBlock
CVE-2026-33234 | Moderato 5.0 | GHSA-4jwj-6mg5-wrwf Autore: Pavan Nallamothu
Stavo mappando ogni input controllato dall'utente che toccava la rete nella piattaforma AutoGPT. Il livello HTTP era bloccato saldamente. Gli intervalli IP privati (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), il loopback, gli endpoint di metadata cloud — tutti in blocklist. Ho confermato il gate HTTP da più angolazioni. Nulla passava.
Poi ho aperto lo schema di configurazione di SendEmailBlock.
Il campo del server SMTP era un input a testo libero. Non una credenziale amministrativa. Non una configurazione bloccata impostata una volta al deployment. Un campo che qualsiasi utente autenticato poteva compilare con ciò che voleva. Ho tracciato il percorso del codice e ho scoperto che smtplib.SMTP() apre un socket TCP grezzo. Quella connessione non passa mai attraverso il percorso HTTP dove risiede la blocklist degli IP. Nella piattaforma esistevano due percorsi in uscita. Solo uno era protetto.
Ho puntato il server SMTP su localhost:22.
Il banner SSH è tornato nel messaggio di errore. smtplib si connette a qualunque cosa gli si fornisca, tenta di leggere un saluto SMTP 220, e quando riceve qualcos'altro, avvolge i byte grezzi in un SMTPConnectError. Quell'eccezione si propaga attraverso il framework di esecuzione di AutoGPT e emerge chiaramente nell'output del blocco. Stavo guardando la stringa di versione SSH del target senza mai toccare il livello HTTP.
Questo è ciò che lo ha reso interessante. smtplib non è solo un client email. È un banner grabber TCP con segnalazione degli errori strutturata. Puntalo sulla porta 6379 e ottieni la firma del protocollo di Redis. Puntalo su una porta chiusa e ConnectionRefusedError ti dice che l'host è vivo ma la porta è giù. Puntalo su 169.254.169.254:80 e confermi che l'endpoint di metadata cloud è raggiungibile. Ogni tentativo di connessione restituisce un errore diverso e informativo. SSRF non cieco attraverso una funzionalità che doveva inviare email.
Il design di SMTPConfig aggrava il problema. In un'architettura sicura, l'indirizzo del server SMTP sarebbe una credenziale controllata dall'amministratore — impostata una volta, bloccata, mai esposta agli utenti. Invece, è un input per singola esecuzione. Ogni utente autenticato controlla dove la piattaforma apre connessioni TCP.
# Configurazione di SendEmailBlock - imposta il server SMTP su target interni
# Scansione SSH
smtp_server = "10.0.0.5"
smtp_port = 22
# L'errore rivela: "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6"
# Scansione Redis
smtp_server = "10.0.0.5"
smtp_port = 6379
# L'errore rivela: "-ERR unknown command ..."
# Scansione porta chiusa
smtp_server = "10.0.0.5"
smtp_port = 9999
# L'errore rivela: "ConnectionRefusedError" (porta chiusa, host vivo)
# Colpisci i metadata cloud
smtp_server = "169.254.169.254"
smtp_port = 80
# Conferma la raggiungibilità dell'endpoint di metadata
Ho verificato l'intera catena attraverso l'API di esecuzione dei blocchi:
# Test diretto equivalente contro l'API di esecuzione dei blocchi
curl -X POST https://autogpt-platform/api/blocks/execute \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"block_id": "send_email_block",
"inputs": {
"smtp_server": "10.0.0.5",
"smtp_port": 22,
"to": "[email protected]",
"subject": "test",
"body": "test"
}
}'
# La risposta contiene SMTPConnectError con il banner SSH
graph LR
A[L'attaccante imposta il server SMTP su un IP interno] --> B[SendEmailBlock chiama smtplib.SMTP]
B --> C[Connessione TCP grezza a target:porta]
C --> D{Il servizio risponde?}
D -->|Sì| E[Il banner viene letto come saluto SMTP]
E --> F[SMTPConnectError con dati del banner]
F --> G[L'errore si propaga all'output del blocco]
D -->|No| H[ConnectionRefused = porta chiusa]
G --> I[L'attaccante legge la versione del servizio]La superficie d'attacco che questo apre è significativa. I banner SSH rivelano versioni esatte (OpenSSH_8.9p1 Ubuntu-3ubuntu0.6). Redis perde la sua firma di protocollo. MySQL invia la sua stringa di versione. Ogni banner è una ricerca CVE in attesa di accadere. Un attaccante mappa la rete interna, identifica ogni servizio in esecuzione e la sua versione esatta, poi prende di mira il più debole. Tutto da un campo di testo etichettato "SMTP Server."
Tre controlli mancanti hanno creato tutto questo: nessuna validazione IP sul percorso SMTP, nessuna restrizione sulle porte, nessuna sanificazione delle eccezioni. La piattaforma proteggeva ogni porta in uscita tranne quella etichettata "posta in uscita."
Ho segnalato il problema a Significant Gravitas. Hanno compreso immediatamente il divario architetturale.
Corretto in: autogpt-platform-backend 0.6.52 (aggiunta la validazione del server SMTP all'applicazione della blocklist, applicate le restrizioni sulle porte)