
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
doneIDOR прячется не только в числовых 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 рабочим, не понимая, что объект чужой. Нужен ручной тест с двумя аккаунтами. Наш рабочий процесс:
- Заводим два аккаунта одной роли (user A и user B) и по аккаунту на каждую другую роль.
- Логинимся под A, включаем в Burp расширение Autorize с сессией B.
- Ходим по приложению под A. Autorize автоматически повторяет каждый запрос с cookie B и подсвечивает: где доступ не заблокирован, там IDOR.
- Проверяем все методы (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);
});- Авторизация на уровне объекта. Проверяйте «имеет ли ОН право на ЭТОТ объект», а не просто «залогинен ли».
- Владелец: из сессии, не из запроса. Клиент никогда не должен передавать свой
user_id. - Централизуйте контроль доступа (middleware/policy), так вы не забудете закрыть новую ручку.
- Deny by default и 404 вместо 403 для чужих объектов.
- Логируйте отказы доступа и алертите на всплески — это признак enumeration-атаки в реальном времени.
В мульти-арендных (multi-tenant) продуктах IDOR превращается в cross-tenant утечку, один клиент видит данные другого. Это уже не баг в трекере, а инцидент с уведомлением Роскомнадзора по 152-ФЗ и разговором с юристами.
Уверены, что пользователи не видят чужие данные?
Проверим контроль доступа двухаккаунтным тестом на всех ролях, методах и «служебных» ручках, найдём IDOR раньше, чем кто-то запустит цикл по вашим id.
Читайте также: Безопасность API (BOLA — это IDOR в API), Пентест SaaS.
Профильные услуги SecurityLab: тестирование на проникновение · пентест веб-приложений · Пентест мобильных приложений.