Статья IDOR эскалация привилегий: горизонтальная и вертикальная эксплуатация с обходом UUID

Рабочий стол из светлого ясеня с планшетом, отображающим два HTTP-запроса с UUID-параметрами. Рядом перьевая ручка на бумаге со схемой атаки, мягкий дневной свет из окна.


На последнем пентесте API финтех-сервиса одна подмена параметра account_id в запросе GET /api/v2/transactions раскрыла историю транзакций чужого счёта - с реквизитами карты и суммами переводов. Разработчики были уверены: UUID v4 - достаточная защита от перебора. UUID утёк через эндпоинт поиска пользователей в поле id каждого результата. Два запроса, ноль WAF-алертов, severity P1.

Это типичный IDOR - Insecure Direct Object Reference, он же BOLA (Broken Object Level Authorization, первая позиция в OWASP API Security Top 10, API1:2023). По CWE - CWE-639: Authorization Bypass Through User-Controlled Key. По данным OWASP Top 10 2021, 94% протестированных приложений содержат ту или иную форму broken access control (A01:2021). IDOR - самый массовый подтип этой категории, и причина простая: одна пропущенная проверка авторизации на уровне объекта раскрывает каждую запись в базе. Масштабируется моментально.

Дальше - конкретные паттерны горизонтальной и вертикальной IDOR-эскалации, техники обхода UUID и непрямых ссылок на объекты, разбор с реальными HTTP-запросами и workflow в Burp Suite.

Место IDOR-эскалации в цепочке атаки на API​

1782735239489.webp

IDOR - не самодостаточная атака. Понимание её позиции в kill chain определяет и стратегию эксплуатации, и оценку импакта в репорте.

Initial Access -> Аутентификация -> IDOR Exploitation -> Data Collection / Privilege Escalation -> Impact

На этапе initial access атакующий получает легитимную сессию: регистрация аккаунта, OAuth-авторизация, украденный токен. IDOR эксплуатируется уже после аутентификации. Проблема не в том, кто вы, а в том, что приложение не проверяет ваше право запрашивать конкретный объект. Вы уже внутри - и это принципиальное отличие от injection-атак или XSS.

Бизнес-логика атаки: атакующий регистрирует бесплатный аккаунт, находит IDOR в API заказов и за час выгружает полную базу клиентов с платёжными данными. Финансовый импакт - штрафы за утечку ПД, репутация в минус, прямой ущерб клиентам. Или: через вертикальный IDOR атакующий повышает свою роль до администратора и получает контроль над всей платформой.

В терминологии MITRE ATT&CK IDOR-эксплуатация маппится на несколько техник в зависимости от результата:

Действие через IDORТехника ATT&CKТактика
Перечисление пользователей через подмену IDAccount Discovery (T1087)Discovery
Массовое вытягивание данныхData from Information Repositories (T1213)Collection
Модификация чужих данных (email, phone)Data Manipulation (T1565)Impact
Эскалация до admin через role_idValid Accounts (T1078)Privilege Escalation

[Применимо: внешний и внутренний пентест] IDOR работает и на public API, и на internal microservices. Разница существенная: на внешнем пентесте вы ограничены public-facing endpoints и rate limiting-ом; на внутреннем - часто получаете доступ к internal API без ограничений и с минимальным логированием. Массовая эксплуатация на внутреннем API - дело десяти минут.

Горизонтальная и вертикальная эскалация IDOR: паттерны эксплуатации​

Русскоязычные источники обычно останавливаются на определении: горизонтальная - тот же уровень привилегий, вертикальная - переход выше. На практике различие глубже: разные точки входа, разные эндпоинты, разный подход к эксплуатации.

Горизонтальная эскалация привилегий: где живёт IDOR в современных API​

Очевидные GET /api/users/123 разработчики давно закрыли. Уязвимость переместилась в менее заметные места. Паттерны, которые реально встречаются на bug bounty:

Тело POST/PUT-запросов. Эндпоинт PUT /api/profile принимает JSON с полем "user_id": 4521. Сервер берёт user_id из тела запроса вместо сессии. Меняете на 4522 - обновляете чужой профиль. Подтверждение: зайдите под Victim и проверьте, что данные реально изменились.

Составные ключи в query-параметрах. Запрос GET /api/org/15/team/3/member/42 проверяет принадлежность к организации 15 и команде 3, но не проверяет, что member 42 - это вы. Подмена последнего параметра раскрывает данные другого участника.

HTTP-заголовки. Некоторые API-шлюзы передают identity через X-User-Id или X-Account-Id. Если backend доверяет заголовку без перепроверки токена сессии - прямой IDOR через подмену заголовка. На одном проекте мы именно так вытянули данные 12 000 аккаунтов - API Gateway проксировал X-Account-Id "как есть".

Файловые пути. URL вида /uploads/user_4521/passport.pdf - замена 4521 на 4522 отдаёт чужой документ. Это IDOR, скомбинированный с path traversal. По описанию PortSwigger, IDOR с прямыми ссылками на статические файлы - частый вектор при доступе к чат-логам, документам и конфигурациям.

GraphQL-переменные. В GraphQL идентификатор передаётся как переменная, а вложенность объектов создаёт дополнительные точки подмены:
Код:
query {
  user(id: "victim-uuid") {
    email
    orders { id, total, shippingAddress }
  }
}
Если сервер проверяет авторизацию на уровне user, но не на уровне вложенного orders, атакующий получает заказы жертвы. Batched queries в GraphQL позволяют отправить десятки запросов с разными ID в одном HTTP-запросе, обходя per-request rate limiting.

[Ограничение: GraphQL-интроспекция отключена в продакшене у зрелых команд. Если __schema возвращает ошибку - поиск IDOR-точек требует ручного анализа клиентского JS-кода]

Ключевой сигнал при тестировании: сравнивайте не только статус-код, но и размер response body. Если запрос с несуществующим ID возвращает body одного размера, а с существующим чужим ID - другого, данные утекают, даже если визуально ответ похож на generic error. Этот приём сэкономит часы.

Вертикальная эскалация через IDOR: role_id и admin-эндпоинты​

Вертикальный IDOR встречается реже, но его severity всегда P1. Типичные паттерны:

Числовой role_id в запросе обновления. Запрос PUT /api/users/me принимает "role_id": 2 (обычный пользователь). Замена на "role_id": 1 (admin) повышает привилегии, если сервер не валидирует право пользователя менять свою роль. Это частный случай BOPLA - Broken Object Property Level Authorization (API3:2023 в OWASP API Security Top 10), где приложение позволяет модифицировать свойства объекта, к которым у пользователя не должно быть доступа.

Подмена user_id на ID администратора. Если admin-аккаунт имеет ID 1 (auto-increment - встречается постоянно), запрос GET /api/admin/dashboard?user_id=1 может вернуть админские данные обычному пользователю. Вертикальный IDOR часто живёт именно в admin-эндпоинтах, где проверка авторизации реализована на уровне UI (кнопка скрыта), а на уровне API - пусто.

JWT payload с role claim. Приложения, хранящие role в JWT payload без серверной перепроверки, уязвимы к модификации токена. При слабом алгоритме подписи (alg: none, HMAC вместо RSA) атакующий меняет "role": "user" на "role": "admin". Пересечение с техникой Valid Accounts (T1078, Privilege Escalation).

[Применимо: внешний и внутренний пентест. На внутреннем пентесте вертикальный IDOR чаще обнаруживается в internal admin API, которые разработчики считают "скрытыми" за VPN и не защищают проверками авторизации]

Обход UUID и непрямых ссылок на объекты​

1782735388423.webp

Разработчики регулярно считают UUID v4 защитой от IDOR. Пространство UUID v4 - 2^122 значений, перебор невозможен. Но IDOR - не атака перебором. Как точно формулирует Zeriflow: "UUIDs reduce discoverability - an attacker can't guess the next ID. But if the application still doesn't check authorization, a UUID endpoint is still vulnerable.""UUID уменьшает исследовательность - атакующие не могут указать следующий ID. Но если приложение всё ещё не проверяет авторизацию, UUID всё ещё уязвим."

UUID - это замок на стеклянной двери. Красиво, но бесполезно, если ключ валяется рядом.

Где утекают UUID на реальных пентестах​

  1. Response body других эндпоинтов. Поисковый запрос GET /api/users/search?q=john возвращает список пользователей с UUID в поле id. Атакующий использует полученный UUID в GET /api/users/{uuid}/documents. Два запроса - один легитимный (поиск), второй с подменой контекста.
  2. Referer-заголовки. Страница профиля с UUID в URL (/profile/3f5c2e8a-...) при наличии внешних ресурсов (аналитика, CDN, пиксели ретаргетинга) утекает через Referer в логи третьих сторон. На одном из пентестов UUID пользователей утекал через Google Analytics - профиль содержал embed-скрипт, и вся "защита через непредсказуемость" пошла к чертям.
  3. Публичные ссылки и функции sharing. Функция "поделиться документом" генерирует ссылку с UUID документа. Этот UUID далее используется для прямого доступа через API без проверки авторизации - разработчик предполагал, что "ссылку знает только тот, кому отправили". Знакомая логика?
  4. Verbose error messages. Stack trace или debug-вывод может раскрыть UUID объектов. Подпадает под Security Misconfiguration (A05:2021) и часто встречается в staging-окружениях, доступных из интернета.
Отдельный случай - UUID v1, содержащий timestamp и MAC-адрес генерирующей машины. UUID v1 частично предсказуем: зная один UUID и приблизительное время генерации, можно вычислить соседние значения. В современных приложениях встречается редко, но legacy-системы с UUID v1 - не исключение.

Обход indirect object reference maps​

Indirect reference map - защитный паттерн, при котором клиент получает не реальный database ID, а сессионный маппинг. Вместо GET /api/orders/5291 клиент видит GET /api/orders/a8f3e2b1, а сервер внутри сессии маппит a8f3e2b1 на реальный ID.

Обход возможен в нескольких сценариях:
  • Маппинг общий, а не per-session. Если a8f3e2b1 разрешается в 5291 для всех пользователей, атакующий получает чужой маппинг через другой эндпоинт.
  • Маппинг детерминистический. Если indirect reference вычисляется как md5(user_id + object_id) - при знании алгоритма маппинг воспроизводится. Видел такое в продакшене дважды.
  • Маппинг утекает. Та же проблема, что с UUID: indirect reference может появиться в search-эндпоинтах, email-нотификациях, response body.
Правильно реализованный per-session indirect reference map действительно останавливает IDOR. Проблема в том, что реализация требует серверного состояния для каждой сессии, и разработчики упрощают схему до уязвимой. По документам - per-session. На практике - глобальный хеш.

Практическая эксплуатация IDOR: workflow и ограничения​

📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме

Scope query в ORM. Фреймворки вроде Django REST Framework с django-guardian проверяют ownership на уровне SQL-запроса: WHERE id = ? AND user_id = ?. Подмена ID в параметрах возвращает пустой результат. Это правильный подход - и он убивает IDOR на корню.

Server-side identity resolution. Если сервер полностью игнорирует user_id из запроса и берёт его из JWT/session - подмена бессмысленна.

Anomaly detection. Массовый перебор ID генерирует характерный паттерн: один пользователь запрашивает сотни объектов за короткий период. В SigmaHQ есть правило web_multiple_susp_resp_codes_single_source.yml, детектирующее множественные подозрительные коды ответа от одного источника - косвенный индикатор IDOR-перебора. С точки зрения D3FEND, защита строится через Access Modeling (D3-AM) и Network Resource Access Mediation (D3-NRAM).

Большинство IDOR-репортов на HackerOne содержат одну и ту же ошибку: хантер показывает подмену ID и останавливается. Триажер ставит P3, выплата минимальная.

Реальная ценность IDOR-находки - не в факте подмены, а в цепочке. Горизонтальный IDOR на чтение email позволяет инициировать password reset на подконтрольный ящик - и вот у вас account takeover. Вертикальный IDOR через подмену role_id открывает admin API и массовый экспорт данных. Один изолированный IDOR - P3 за минимальную выплату. Цепочка IDOR -> ATO - P1.

Индустрия продолжает учить IDOR как "замени число в URL", а не как точку входа в атаку на бизнес-логику. Пока разработчики надеются на UUID вместо серверной авторизации, а хантеры останавливаются на первом подтверждении вместо построения цепочки - обе стороны недорабатывают. API-first архитектуры сделают BOLA-уязвимости ещё массовее, и application-layer authorization станет таким же обязательным элементом, как TLS. Те, кто сейчас тренируется строить цепочки от единичного IDOR до full compromise, будут задавать стандарт пентестов. Если хотите отработать эту связку - на курсе WAPT цепочку IDOR -> ATO разбирают в отдельном модуле с лабами.
 
Последнее редактирование модератором:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🧭 Навигатор · ИБ 2026
Не знаешь, какой трек твой?
5 направлений ИБ, реальные зарплаты и точка входа для каждого — в одном треде.
JuniorSenior+
100K → 600K+ ₽ /мес
Открыть навигатор →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab