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

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

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

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

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

Категории

Все категории
Loading categories
enforcement-coverage — Находит маршруты API с более слабой авторизацией, чем у их соседних маршрутов. Восстановлен CVE-2026-45316 из исходного кода. Включает отрицательные результаты. | Kitploit
Инструменты/GitHubGitHub/arian-gogani/enforcement-coverage
Статический анализ кода (SAST)Анализ уязвимостейАнализ КодаТестирование на ПроникновениеDevSecOpsБезопасность API
GitHubarian-gogani/enforcement-coverage

enforcement-coverage

Находит маршруты API с более слабой авторизацией, чем у их соседних маршрутов. Восстановлен CVE-2026-45316 из исходного кода. Включает отрицательные результаты.

Популярное

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

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

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

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

Смотреть все инструменты →
Поделиться
Репозиторий
15 ч 48 мин назадЕщё не проверено

Покрытие контроля

Находит API-маршруты, которые несут более слабый контроль авторизации, чем их соседние маршруты.

Он нашёл CVE-2026-45316 в Open WebUI по одному только исходному коду, без сведений из бюллетеней безопасности:

root@kitploit:~
[MISMATCH] POST /notes/{id}/pin  (notes.py:pin_note_by_id)
  3/3 comparable write operations on note require has_access(write);
  this route requires only has_access(read)

    POST   /notes/{id}/update          has_access(write)
    POST   /notes/{id}/access/update   has_access(write)
    DELETE /notes/{id}/delete          has_access(write)

На 2 568 маршрутах в пяти продакшен-кодовых базах он выдал 4 находки. Две из них были реальными. Этот README объясняет обе цифры.

Идея

Большой класс ошибок авторизации — это не сломанная проверка. Это отсутствующая или ослабленная проверка на маршруте, у которого все соседние маршруты выполнены правильно.

Portainer авторизовал четыре соседних endpoint'а шаблонов, но не пятый. Signal K ограничивал частоту HTTP-логина, но не WebSocket-логина. Маршрут закрепления заметки в Open WebUI изменял заметку, проверяя разрешение на чтение, тогда как все остальные операции изменения заметки проверяли запись.

Всегда одна и та же форма:

root@kitploit:~
✓ ✓ ✓ ✓ ✗

Репозиторий уже содержит правило. Один маршрут его нарушил. Поэтому восстановите правило из кода и сообщите об исключении. Никаких policy-файлов, конфигов и аннотаций. Доказательная база — сами соседние маршруты.

Запуск

root@kitploit:~
python3 enforcement_coverage.py /path/to/repo
python3 enforcement_coverage.py /path/to/repo --density
python3 enforcement_coverage.py /path/to/repo --json

Python 3.10+, без зависимостей. Только FastAPI.

Вердикты: MISSING, MISMATCH, PRESERVED, UNKNOWN. UNKNOWN воздерживается и никогда не сообщается.

Что он делает

Извлечение. Разрешает контроли из сигнатуры Depends(), декоратора dependencies=[], зависимостей уровня роутера, тел функций, функций-обёрток и списков классов разрешений.

Извлечение из тела функции критически важно. В Open WebUI 216 из 608 обработчиков несут решающую проверку внутри функции:

root@kitploit:~
if user.role != 'admin' and not await AccessGrants.has_access(
    user_id=user.id, resource_type='note',
    resource_id=note.id, permission='write', db=db,
):
    raise HTTPException(status_code=403)

Класс операции определяется тем, что обработчик делает с ресурсом, а не HTTP-глаголом. POST /notes/{id}/chat — это POST, который читает заметку.

Классификация словаря. Два значения в одном семействе контролей не обязательно образуют шкалу силы:

root@kitploit:~
has_access             {read, write}                      LEVEL
ensure_flow_permission {create,delete,execute,read,write}  ACTION
has_permission         {features.notes, workspace.tools}   SCOPE

Только словари LEVEL поддерживают сравнение силы. Сравнение FlowAction.CREATE с доминирующим WRITE давало шесть ложных срабатываний в Langflow, пока это не исправили.

Фильтр направления. Сообщается только об отклонениях в сторону менее ограничивающего контроля. Более строгий, чем прецедент, контроль — это не уязвимость.

Что он нашёл

Два истинно положительных результата.

POST /notes/{id}/pin в Open WebUI — CVE-2026-45316.

Ещё одна находка — асимметрия разрешений в Netflix Dispatch: POST /{incident_id}/resources использует IncidentViewPermission, тогда как шесть соседних операций записи используют IncidentEditPermission. IncidentViewPermission возвращает True для любого неограниченного инцидента; IncidentEditPermission требует прав администратора, командира или репортёра. Обработчик ставит в очередь создание тикета и группы без дополнительной проверки.

Не сообщено, потому что сообщить некуда: репозиторий был заархивирован Netflix 3 сентября 2025 года и доступен только для чтения, в нём нет SECURITY.md, приватное сообщение об уязвимостях отключено для заархивированных репозиториев, а Dispatch явно указан как вне зоны действия программы bug bounty Netflix. Публикация здесь — единственный оставшийся канал раскрытия. Уязвимость имеет низкую степень серьёзности — она требует аутентифицированного участника организации и затрагивает только неограниченные инциденты — а проект больше не поддерживается.

Два ложных срабатывания. POST /tools/{id}/valves/user/update записывает собственные настройки клапанов пользователя и обоснованно требует только чтения инструмента — цель изменения является другой сущностью, чем субъект авторизации. А также маршрут базы знаний в Langflow, где соседняя защита не требуется.

Почему в основном это не работает

Это полезная часть.

Плотность не предсказывает находки

У Danswer 95,9% покрытия контролей и ноль находок при 80,7% UNKNOWN. Его словарь — require_permission('basic_access'), ('manage_connectors') — это пространство имён возможностей, а не шкала силы. Нельзя сказать, что manage_connectors слабее, чем read_connectors.

Находки предсказывает вызов разрешения с областью действия ресурса и упорядоченным аргументом силы, например has_access(resource, read|write). Такое было в одной кодовой базе из пяти.

Для каждой кодовой базы требовалось своё извлечение

Пять идиом в пяти репозиториях. Для каждой требовалась работа экстрактора, прежде чем анализ вообще мог запуститься.

UNKNOWN никогда не опускался ниже 72%

В любом репозитории и при любой конфигурации. Большинство маршрутов не принадлежат соседнему семейству из трёх и более маршрутов с согласованным контролем.

Дефекты, обнаруженные при запуске на реальном коде

Ни один из них не был предвиден заранее.

  1. авторизация находится в телах функций, а не в Depends()
  2. маршруты несут сразу несколько семейств контролей
  3. HTTP-глагол — это не класс операции
  4. идиомы авторизации различаются от репозитория к репозиторию
  5. словари действий — это не шкалы силы
  6. более строгий, чем прецедент, контроль — не уязвимость
  7. словарь, классифицированный только по прецедентам, скрывает семейства с одним значением
  8. хелперы валидации, выбрасывающие 422, — это не авторизация
  9. функции-обёртки скрывают реальный контроль
  10. идиомы со списком классов разрешений требуют разбиения имён
  11. ослабление соседних семейств увеличило число находок в 7,5 раза и снизило точность с 50% до 13%
  12. маршрут с другим достаточным контролем не является маршрутом с отсутствующим контролем
  13. эквивалентная проверка, реализованная инлайн, а не как зависимость — не решено

Дефект 13 — самый интересный. Маршруты рекомендации тегов в Dispatch не имеют CaseViewPermission, который есть у соседних маршрутов. Но это разрешение возвращает True для любого неограниченного кейса, а сервис уже проверяет visibility == restricted инлайн. Пути эквивалентны. Для обнаружения этого нужен анализ семантической эквивалентности, а не структуры.

Честная оценка

Механизм работает. Он восстановил опубликованный CVE и один несообщённый пробел в авторизации из исходного кода, с проверяемыми наборами доказательств, используя только информацию, доступную до слияния уязвимого коммита.

Выход — примерно одна находка на 1 000 маршрутов, и для этого нужна архитектура, которая была у одной из пяти крупных кодовых баз.

Полезен как инструмент аудита для кодовой базы со словарём разрешений в области ресурсов. На основании этих данных — не универсальный сканер.

Предшествующие работы

Статическое обнаружение уязвимостей контроля доступа путём вывода неявных предположений восходит к USENIX Security 2011. ACMiner извлекал проверки авторизации в промежуточном ПО Android. Semgrep поставляет обнаружение на основе ИИ, нацеленное на отсутствующую авторизацию, и сообщило о точности 61% в одной оценке заказчика. OWASP публикует шпаргалку по регрессионному тестированию авторизации, рекомендуемый подход которой — ведение матрицы Actor × Resource × Action вручную.

Это узкий, детерминированный подход: восстанавливать только то, что доказывают соседние маршруты, в остальном воздерживаться.

Под лицензией MIT.

Скачать инструмент
репозиториймаршрутыпод контролемнаходки
LiteLLM80887.1%0
Danswer / Onyx65395.9%0
Open WebUI52997.2%2
Netflix Dispatch29136.1%1
Langflow28747.4%1
репозиторийидиома
Open WebUIAccessGrants.has_access(resource_type=, permission=)
Langflowensure_<resource>_permission(user, Action.X)
LiteLLMrole compare on user_api_key_dict.user_role
Netflix DispatchDepends(PermissionsDependency([CaseEditPermission]))
Danswerrequire_permission('basic_access')