// Безопасность / Веб

IDOR на практике: как получают доступ к чужим данным

IDOR — доступ к чужим данным через подмену id

IDOR (Insecure Direct Object Reference, небезопасная прямая ссылка на объект) — это уязвимость, при которой приложение показывает или изменяет данные по идентификатору, но не проверяет, принадлежит ли объект текущему пользователю. Меняем id в запросе — и получаем чужой заказ, документ, счёт или профиль. Звучит примитивно, но именно этот класс годами возглавляет рейтинги: в OWASP Top 10 2021 категория A01: Broken Access Control (куда входит IDOR) вышла на первое место, а по данным OWASP признаки нарушения контроля доступа находят в 94% протестированных приложений. Это одна из самых частых находок и на нашем пентесте веб-приложений.

Как выглядит атака: пошагово

Представим личный кабинет интернет-магазина. Пользователь открывает свой заказ, и браузер отправляет запрос:

GET /api/orders/1043 HTTP/1.1
Host: shop.example.com
Authorization: Bearer eyJhbGciOi...

--- ответ ---
200 OK
{ "order_id": 1043, "user": "alice", "total": 5400, "address": "..." }

Атакующий просто уменьшает номер на единицу — GET /api/orders/1042 — и если сервер не проверяет владельца, в ответ приходит чужой заказ с адресом и суммой. Дальше атака автоматизируется: скрипт перебирает 1..100000 и выкачивает базу заказов целиком. Это называется enumeration (перечисление).

IDOR прячется не только в числовых id

  • UUID и хэши. Кажется безопасным, но если UUID где-то утекает (в списках, логах, реферере) — доступ открыт.
  • Параметры тела и заголовки. {"account_id": 55} в POST, X-User-Id: 55 в заголовке.
  • Имена файлов. /download?file=invoice_1042.pdf.
  • Косвенные ссылки. /api/users/me/cards vs /api/users/55/cards — второй вариант часто забывают закрыть.

Почему сканеры это пропускают

Автоматический сканер видит, что endpoint /api/orders/1042 вернул 200 OK, и считает его «рабочим». Он не понимает бизнес-контекст — что заказ 1042 принадлежит другому пользователю. Чтобы найти IDOR, нужен ручной тест с двумя аккаунтами: заходим под пользователем A, пытаемся обратиться к ресурсам пользователя B. Именно так работаем мы, и именно поэтому IDOR — «ручная» уязвимость.

Экспертное наблюдение: 8 из 10 критичных IDOR, которые мы находим, живут не в основном сценарии, а на «второстепенных» действиях — экспорт в PDF, повторная отправка письма, отмена заказа, вебхуки. Разработчики закрывают доступ на чтение, но забывают про операции записи и служебные ручки.

Инструменты для поиска IDOR

  • Burp Suite + расширение Autorize / AuthMatrix — автоматически повторяет каждый запрос от имени другого пользователя и подсвечивает, где доступ не заблокирован.
  • Burp Intruder — перебор идентификаторов для проверки enumeration.
  • ffuf / turbo intruder — быстрый перебор на больших диапазонах.
  • Двухаккаунтная матрица вручную — самый надёжный метод: таблица «роль × ресурс × действие».

Как защититься: рабочие меры с примерами

Ключевой принцип: проверять владельца на сервере при каждом обращении к объекту, а не полагаться на то, что UI не покажет лишнюю ссылку. Плохой и хороший код:

// ❌ УЯЗВИМО: берём объект по id из запроса без проверки владельца
app.get("/api/orders/:id", (req, res) => {
  const order = db.orders.find(req.params.id);
  res.json(order);            // вернёт ЛЮБОЙ заказ
});

// ✅ БЕЗОПАСНО: объект ищется в scope текущего пользователя
app.get("/api/orders/:id", (req, res) => {
  const order = db.orders.findOne({
    id: req.params.id,
    user_id: req.user.id       // владелец берётся из сессии/токена, НЕ из запроса
  });
  if (!order) return res.sendStatus(404);
  res.json(order);
});
  1. Авторизация на уровне объекта. Проверяйте не «залогинен ли пользователь», а «имеет ли ОН право на ЭТОТ объект».
  2. Владелец — из сессии, а не из запроса. user_id берётся из токена/сессии сервера, клиент не должен его передавать.
  3. Централизуйте контроль доступа. Единый слой (middleware, policy) вместо проверок «руками» в каждом обработчике — так вы не забудете закрыть новую ручку.
  4. Deny by default. Доступ запрещён, пока явно не разрешён.
  5. Возвращайте 404, а не 403, для чужих объектов — не подтверждайте их существование.
  6. Логируйте отказы доступа и алертите на всплески — это признак enumeration-атаки.

Чек-лист самопроверки

  • Может ли пользователь A получить объект пользователя B, поменяв id? (проверьте GET, POST, PUT, DELETE)
  • Закрыты ли экспорт, вебхуки, повторные отправки, отмена — не только основной просмотр?
  • Проверяется ли владелец на API так же строго, как в вебе?
  • Что произойдёт при переборе id скриптом — есть ли rate limit и алерты?

IDOR почти никогда не «висит один»: в мульти-арендных (multi-tenant) продуктах он превращается в cross-tenant утечку — один клиент видит данные другого. Это уже не баг, а инцидент с уведомлением регулятора по 152-ФЗ.

Уверены, что пользователи не видят чужие данные?

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

Заказать пентест веб-приложений →

Читайте также: Пентест API, Пентест SaaS, Безопасность API (OWASP API Top 10).

← назад в блог