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

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

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

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

Проверьте свой сайт на эти уязвимости

Мы вручную протестируем ваше веб-приложение по методологии OWASP и покажем, какие из описанных рисков реально эксплуатируются, с доказательствами и планом устранения.

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

Реальные утечки: цена одной «циферки»

  • First American Financial (2019) — 885 миллионов финансовых документов (сканы паспортов, банковские выписки) лежали по последовательным URL вида /document/000000075. Меняешь номер, читаешь чужой документ. Без пароля, без ничего.
  • USPS Informed Visibility (2018) — API отдавал данные 60 млн пользователей: любой залогиненный мог запросить чужой аккаунт по параметру.
  • Peloton (2021) — API возвращал данные любого пользователя (возраст, вес, локация) по id, даже с приватным профилем.
  • Optus (2022, Австралия) — неаутентифицированный API с перебираемыми id: утекли данные ~9,8 млн клиентов.

Обратите внимание: во всех этих кейсах не было «взлома» в киношном смысле. Не было эксплойтов, вирусов, подбора паролей. Был цикл for id in range(1, 100000000). IDOR — это уязвимость, которую эксплуатирует школьник, а платит за неё компания сотнями миллионов.

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

Личный кабинет магазина. Пользователь открывает свой заказ:

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, и если сервер не проверяет владельца, приходит чужой заказ. Дальше скрипт перебирает диапазон и выкачивает базу целиком (enumeration):

# простейший дампер на bash — так сливают базы
for id in $(seq 1 100000); do
  curl -s -H "Authorization: Bearer $TOKEN" 
    "https://shop.example.com/api/orders/$id" >> dump.jsonl
done

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

  • UUID и хэши. «Непредсказуемо» , но если UUID утекает (в списках, логах, email, реферере, кэше CDN), доступ открыт. UUID это не контроль доступа.
  • Параметры тела и заголовки. {"account_id": 55} в POST, X-User-Id: 55 в заголовке.
  • Кодированные id. id=NTU= — это просто Base64 от «55». Декодируется за секунду.
  • Операции записи. Часто закрывают чтение, но забывают DELETE/PUT: DELETE /api/orders/1042 удаляет чужой заказ.

Как найти IDOR: наша методика на пентесте

Сканеры IDOR почти не находят. Они видят «200 OK» и считают endpoint рабочим, не понимая, что объект чужой. Нужен ручной тест с двумя аккаунтами. Наш рабочий процесс:

  1. Заводим два аккаунта одной роли (user A и user B) и по аккаунту на каждую другую роль.
  2. Логинимся под A, включаем в Burp расширение Autorize с сессией B.
  3. Ходим по приложению под A. Autorize автоматически повторяет каждый запрос с cookie B и подсвечивает: где доступ не заблокирован, там IDOR.
  4. Проверяем все методы (GET/POST/PUT/DELETE) и «второстепенные» ручки: экспорт, повторная отправка, отмена, вебхуки.

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

Защита от IDOR и проверка прав доступа: код, а не пожелания

// ❌ УЯЗВИМО: объект берётся по 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);   // 404, не 403 — не палим существование
  res.json(order);
});
  1. Авторизация на уровне объекта. Проверяйте «имеет ли ОН право на ЭТОТ объект», а не просто «залогинен ли».
  2. Владелец: из сессии, не из запроса. Клиент никогда не должен передавать свой user_id.
  3. Централизуйте контроль доступа (middleware/policy), так вы не забудете закрыть новую ручку.
  4. Deny by default и 404 вместо 403 для чужих объектов.
  5. Логируйте отказы доступа и алертите на всплески — это признак enumeration-атаки в реальном времени.

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

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

Проверим контроль доступа двухаккаунтным тестом на всех ролях, методах и «служебных» ручках, найдём IDOR раньше, чем кто-то запустит цикл по вашим id.

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

Читайте также: Безопасность API (BOLA — это IDOR в API), Пентест SaaS.

Профильные услуги SecurityLab: тестирование на проникновение · пентест веб-приложений · Пентест мобильных приложений.

← назад в блог