Уязвимости контроля доступа
Нарушения авторизации на уровне приложения — IDOR, контроль доступа к объектам и функциям, обход каталога, open redirect, логические и TOCTOU-ошибки, изоляция арендаторов.
13 вопросов
JuniorТеорияОчень частоЧто такое небезопасная прямая ссылка на объект (IDOR) и почему последовательные id — это признак?
Что такое небезопасная прямая ссылка на объект (IDOR) и почему последовательные id — это признак?
IDOR — запрос, называющий объект, который сервер отдаёт, не проверив право вызывающего. Последовательные id — признак, ведь соседнее значение легко угадать. Дефект — отсутствие проверки владения.
Типичные ошибки
- ✗Считать случайные или непрозрачные id самостоятельным механизмом контроля доступа
- ✗Считать аутентификацию достаточной и пропускать проверку по объекту
- ✗Полагать, что изъян реален только при последовательных идентификаторах
Уточняющие вопросы
- →Какой HTTP-статус вернуть на запрос чужого объекта и почему?
- →Как написать автотест, доказывающий, что проверка владения выполняется?
JuniorТеорияЧастоГде должна жить проверка авторизации — на шлюзе, в сервисе или у объекта — и что такое deny-by-default?
Где должна жить проверка авторизации — на шлюзе, в сервисе или у объекта — и что такое deny-by-default?
Шлюз применяет грубые правила, но лишь сервис, загружающий объект, знает владельца, поэтому решение по объекту принадлежит ему. Deny-by-default значит отказ, пока правило не выдаст доступ.
Типичные ошибки
- ✗Полагать, что правило на шлюзе способно выразить владение объектом
- ✗Разбрасывать разрозненные проверки по обработчикам без общей позиции
- ✗Понимать deny-by-default лишь как настройку логирования или аудита
Уточняющие вопросы
- →Что происходит, когда новый эндпоинт выходит без разметки авторизации?
- →Как проверить тестом, что позиция по умолчанию действительно запрещающая?
JuniorТеорияЧастоЧто такое нарушение авторизации на уровне функций и как forced browsing вскрывает admin-маршруты?
Что такое нарушение авторизации на уровне функций и как forced browsing вскрывает admin-маршруты?
Это маршрут с привилегированным действием, проверяющий лишь вход вызывающего, а не его роль. Forced browsing обращается к нему напрямую, минуя интерфейс. Скрытый пункт меню — не контроль.
Типичные ошибки
- ✗Путать аутентификацию с авторизацией на привилегированных маршрутах
- ✗Считать неупомянутый или неочевидный путь контролем доступа
- ✗Проверять роль на уровне интерфейса, а не в самом обработчике
Уточняющие вопросы
- →Как собрать полный перечень маршрутов кодовой базы при security-ревью?
- →Почему старые версии API часто сохраняют незащищённые admin-обработчики?
JuniorТеорияЧастоЧто такое open redirect и чем он опасен для фишинга и для фреймворка авторизации OAuth2?
Что такое open redirect и чем он опасен для фишинга и для фреймворка авторизации OAuth2?
Open redirect — эндпоинт, отправляющий браузер на цель из запроса без проверки. Он одалживает домен фишинговой ссылке, а в OAuth2 может унести authorization code. Сверяйте цель с allowlist.
Типичные ошибки
- ✗Проверять цель по подстроке или префиксу вместо точного allowlist
- ✗Считать open redirect косметикой, раз пользователь видит итоговый URL
- ✗Забывать, что обработка
redirect_uriв OAuth2 — тот же самый изъян
Уточняющие вопросы
- →Почему сопоставление хоста по префиксу — слабый allowlist?
- →Как серверное сопоставление короткого ключа с URL убирает изъян?
MiddleТеорияЧастоЧто такое нарушение авторизации на уровне объектов (BOLA) и почему надо проверять каждый HTTP-метод?
Что такое нарушение авторизации на уровне объектов (BOLA) и почему надо проверять каждый HTTP-метод?
BOLA — API-форма IDOR, где обработчик действует над id объекта без проверки владения. Команды закрывают GET, но забывают PUT и DELETE, поэтому тест повторяет его по всем методам со второго аккаунта.
Типичные ошибки
- ✗Проверять только чтение, полагая, что запись наследует ту же политику
- ✗Считать id владельца в URL доказательством владения
- ✗Путать rate limiting с контролем авторизации
Уточняющие вопросы
- →Почему на чужой объект иногда предпочитают 404, а не 403?
- →Как поддерживать честность такого набора тестов при появлении эндпоинтов?
MiddleТеорияЧастоПочему UUID — это не авторизация и как выглядит проверка владения на каждом запросе?
Почему UUID — это не авторизация и как выглядит проверка владения на каждом запросе?
UUID лишь делает id трудно угадываемым; увидевший его в логе, в referrer или в ссылке может его повторить. Контроль — проверка на каждом запросе, сверяющая владельца объекта с субъектом сессии.
Типичные ошибки
- ✗Считать неугадываемые идентификаторы механизмом контроля доступа
- ✗Доверять id владельца из запроса вместо взятого из сессии
- ✗Проверять владение один раз при входе, а не на каждом запросе
Уточняющие вопросы
- →Где идентификаторы объектов обычно утекают за пределы приложения?
- →Как ограничение запроса по владельцу в SQL сужает поверхность?
JuniorТеорияИногдаЧто такое обход каталога и как канонизация пути и проверка базовой директории его останавливают?
Что такое обход каталога и как канонизация пути и проверка базовой директории его останавливают?
Обход каталога — пользовательский ввод в пути к файлу, из-за чего сегменты .. выводят за пределы папки. Сначала приведите путь к канонической форме, затем проверьте, что он в базовой директории.
Типичные ошибки
- ✗Блокировать
..по подстроке вместо приведения пути к канонической форме - ✗Проверять путь до канонизации, из-за чего кодированный обход проходит
- ✗Полагаться на права процесса вместо явной проверки базовой директории
Уточняющие вопросы
- →Почему allowlist имён файлов сильнее, чем санитизация ввода?
- →Как отдача файлов по непрозрачному id полностью убирает поверхность обхода?
MiddleТеорияИногдаПочему отрицательные суммы, повторный купон и переполнение количества проходят валидацию и что их остановит?
Почему отрицательные суммы, повторный купон и переполнение количества проходят валидацию и что их остановит?
Каждый запрос корректен, и валидация схемы проходит; нарушается бизнес-инвариант, а не формат. Применяйте его на сервере там, где меняется состояние — границы сумм и количеств, атомарное погашение.
Типичные ошибки
- ✗Полагать, что валидация схемы покрывает и бизнес-инварианты
- ✗Проверять инвариант при чтении, но не там, где меняется состояние
- ✗Ожидать, что firewall выведет правила, специфичные для приложения
Уточняющие вопросы
- →Почему одноразовое погашение купона надо записывать атомарно?
- →Как выразить эти инварианты тестами, а не замечаниями на ревью?
MiddleДебаггингИногдаВ логе доступа одна сессия читает три id счетов подряд — найдите и исправьте дефект обработчика
В логе доступа одна сессия читает три id счетов подряд — найдите и исправьте дефект обработчика
Обработчик аутентифицирует, но не авторизует — он загружает счёт по id, поэтому вошедший читает чужую запись. Ограничьте выборку владельцем из сессии и отвечайте 404 при расхождении.
Открыть задачу →Типичные ошибки
- ✗Принимать
requireLoginза проверку авторизации, а не аутентификации - ✗Чинить формат идентификатора вместо добавления ограничения по владельцу
- ✗Отвечать 403 на чужой объект, подтверждая тем самым его существование
Уточняющие вопросы
- →Почему ограничение запроса безопаснее загрузки с последующей сверкой?
- →Какой тест докажет, что маршрут закрыт для второго аккаунта?
SeniorТеорияИногдаКак mass assignment повышает роль и почему привязка по allowlist — это исправление?
Как mass assignment повышает роль и почему привязка по allowlist — это исправление?
Обработчик привязывает всё тело запроса к доменному объекту, поэтому лишнее поле, отсутствующее на форме — role, isAdmin — попадает в хранилище. Привязывайте allowlist редактируемых полей.
Типичные ошибки
- ✗Использовать denylist, молча пропускающий вновь добавленные поля
- ✗Полагать, что неотрисованное интерфейсом поле нельзя отправить
- ✗Привязывать тела запросов напрямую к сущностям хранилища
Уточняющие вопросы
- →Почему отдельный входной тип лучше аннотаций на сущности хранилища?
- →Как тест поймает вновь добавленную привилегированную колонку?
SeniorТеорияИногдаКак гонка time-of-check to time-of-use (TOCTOU) опустошает баланс и что её закрывает?
Как гонка time-of-check to time-of-use (TOCTOU) опустошает баланс и что её закрывает?
Баланс читается, признан достаточным и списывается отдельным шагом; параллельные запросы проходят проверку по одному устаревшему значению. Сделайте проверку и списание атомарной операцией.
Типичные ошибки
- ✗Считать окно проблемой задержки, а не проблемой атомарности
- ✗Полагать, что idempotency key сам по себе предотвращает разные списания
- ✗Добавлять проверку на клиенте, которую прямой запрос попросту игнорирует
Уточняющие вопросы
- →Чем условное обновление отличается от повторного чтения внутри транзакции?
- →Что логировать, чтобы обнаружить эту гонку постфактум?
SeniorДизайнРедкоВам достаётся платформа из 40 сервисов, где каждый обработчик принимает решение об авторизации сам, прямо в коде. Два инцидента за квартал произошли из-за нового эндпоинта, вышедшего вообще без проверки, а аудит не может ответить, кому доступна конкретная запись. Спроектируйте централизованную авторизацию — точку принятия решения, к которой обращаются сервисы, с правилами в виде данных, а не разбросанных условий. Ограничения — запрос не должен прибавлять более 10 мс; платформа обязана продолжать работу при кратковременной недоступности сервиса политик; владение объектом по-прежнему зависит от данных, которые есть только у владеющего сервиса; около 300 эндпоинтов надо перевести без заморозки релизов; аудиторам нужна устойчивая запись каждого решения. Опишите, где стоит точка решения, как выражаются и распространяются политики, как гарантируется deny-by-default для новых эндпоинтов, как данные об объекте доходят до решения и как вы мигрируете постепенно и доказываете покрытие.
Вам достаётся платформа из 40 сервисов, где каждый обработчик принимает решение об авторизации сам, прямо в коде. Два инцидента за квартал произошли из-за нового эндпоинта, вышедшего вообще без проверки, а аудит не может ответить, кому доступна конкретная запись. Спроектируйте централизованную авторизацию — точку принятия решения, к которой обращаются сервисы, с правилами в виде данных, а не разбросанных условий. Ограничения — запрос не должен прибавлять более 10 мс; платформа обязана продолжать работу при кратковременной недоступности сервиса политик; владение объектом по-прежнему зависит от данных, которые есть только у владеющего сервиса; около 300 эндпоинтов надо перевести без заморозки релизов; аудиторам нужна устойчивая запись каждого решения. Опишите, где стоит точка решения, как выражаются и распространяются политики, как гарантируется deny-by-default для новых эндпоинтов, как данные об объекте доходят до решения и как вы мигрируете постепенно и доказываете покрытие.
Разделите решение и применение — сервис встраивает точку применения, спрашивающую точку решения о субъекте, действии и ресурсе. Политики — версионированные данные с кэшем, а неразмеченные эндпоинты запрещены.
Типичные ошибки
- ✗Полагать, что шлюз определит владение объектом, которого он не видит
- ✗Централизовать политику без запрещающей позиции для новых эндпоинтов
- ✗Делать точку решения жёсткой зависимостью рантайма без локального кэша
Уточняющие вопросы
- →Как доказать, что все 300 эндпоинтов действительно покрыты?
- →Когда платформе стоит открываться при сбое, а не закрываться?
SeniorТеорияРедкоПочему в мультиарендной системе tenant id должен браться из токена, а не из запроса?
Почему в мультиарендной системе tenant id должен браться из токена, а не из запроса?
Всё присланное клиентом можно изменить, поэтому tenant id в пути, теле, заголовке выбран атакующим. Берите его из проверенного токена и привязывайте в слое хранения, чтобы запросы ограничивались сами.
Типичные ошибки
- ✗Доверять tenant id из пути, тела запроса или заголовка Host
- ✗Ограничивать запросы в каждом месте вызова вместо централизованного
- ✗Молча исправлять расхождение вместо отказа в запросе
Уточняющие вопросы
- →Как row-level security в базе дополняет ограничение на уровне приложения?
- →Какой тест доказывает невозможность чтения между арендаторами?