ё ёPRSTCON // LOC B Магистраль
ARTICLE 09 / 04:29:10 / 57:17

От уязвимости к недопустимому: повторяющиеся паттерны в 150+ нуликов

Кирилл Полегаев, Роман Малов и СОК товарищи

Доклад Кирилла Полегаева, Романа Малова и СОК товарищей устроен не как подборка красивых багов, а как попытка посмотреть на внешний периметр через накопленную практику: что именно повторяется, какие классы уязвимостей чаще всего дают атакующему реальный результат и почему отдельный «нестрашный» баг иногда превращается в недопустимое событие. Главная мысль звучит прагматично: критичные инциденты редко рождаются из одной магической уязвимости. Чаще это цепочка из слабого контроля доступа, плохой парольной политики, лишних привилегий, публикации критичных систем наружу и избыточного раскрытия информации. Внешний нарушитель не обязательно начинает с RCE. Иногда ему достаточно собрать пользователей, подобрать один пароль, найти забытый эндпоинт или воспользоваться тем, что объект защищён только знанием GUID.

SLIDE
Контекст исследования 150+ zero-day уязвимостей
MATERIALS видео, субтитры и вычитанный транскрипт
VISUAL CONTEXT ключевые слайды и кадры из середины записи
SLIDE
Статистика и повторяющиеся паттерны
SLIDE
Один из кейсов перехода от уязвимости к недопустимому событию
SLIDE
Контроли и практические выводы
VIDEO
Кадр из середины выступления: доклад в зале, не технический start/end

Доклад Кирилла Полегаева, Романа Малова и СОК товарищей устроен не как подборка красивых багов, а как попытка посмотреть на внешний периметр через накопленную практику: что именно повторяется, какие классы уязвимостей чаще всего дают атакующему реальный результат и почему отдельный «нестрашный» баг иногда превращается в недопустимое событие.

Главная мысль звучит прагматично: критичные инциденты редко рождаются из одной магической уязвимости. Чаще это цепочка из слабого контроля доступа, плохой парольной политики, лишних привилегий, публикации критичных систем наружу и избыточного раскрытия информации. Внешний нарушитель не обязательно начинает с RCE. Иногда ему достаточно собрать пользователей, подобрать один пароль, найти забытый эндпоинт или воспользоваться тем, что объект защищён только знанием GUID.

Dataset и границы исследования

В основе доклада лежит dataset команды, которая занимается непрерывным тестированием внешнего периметра. Масштаб для такой практической выборки заметный: 50+ проектов, 150+ опубликованных 0-day и 250+ уязвимостей в общей модели, куда вошли проектные находки, 0-day research и связанные записи.

Важно, что это не статистика «всех уязвимостей в интернете». Авторы прямо ограничивают область:

Каждая запись в dataset классифицировалась несколькими способами. На верхнем уровне использовалась категория OWASP 2025. Ниже добавлялся vulnerability type в формате CWE-like: не абстрактный номер, а человекочитаемый тип вроде SQL injection, XSS, IDOR или user enumeration. Отдельно фиксировались тип ПО, potential impact, confirmed impact и защитные меры, которые могли бы разорвать цепочку.

Разделение на potential impact и confirmed impact здесь принципиально. XSS может иметь potential impact уровня account takeover, но в конкретном проекте важно, удалось ли этот impact подтвердить. Такой подход сдвигает разговор от «какой CVSS поставить» к вопросу «что внешний нарушитель реально сделал или мог сделать в этой системе».

Что показала статистика по OWASP 2025

По классификации OWASP 2025 самый большой пласт находок пришёлся на Broken Access Control. По словам докладчиков, это почти половина всех найденных уязвимостей. Если добавить Authentication Failures и Injection, три категории вместе дают более 90% того, что команда находит в своём dataset.

На уровне детальных CWE-like типов картина становится менее монолитной. Внутри крупных OWASP-категорий появляются привычные, но по-прежнему результативные паттерны: XSS, IDOR, disclosure, user enumeration, SQL injection, SSRF, local file read, file upload и другие. Такая детализация полезнее для практической защиты: Broken Access Control как зонтик слишком широк, а вот IDOR/BOLA, отсутствие object level authorization или неавторизованный доступ к dashboard уже можно превращать в конкретные проверки.

По типам ПО больше половины находок пришлись на бизнесовые веб-приложения и CMS. Это ожидаемо для dataset, где почти нет «готовых» известных CVE и сканерных misconfiguration: новые уязвимости часто живут в бизнес-логике, интеграциях, самописных модулях и интерфейсах, которые не укладываются в стандартный шаблон.

Отдельно в статистике выделились два наблюдения. Для CMS характерен широкий набор проблем, в том числе CSRF и IDOR. Для платформ мониторинга особенно заметен SSRF: сама природа такого ПО связана с data source, dashboard, отчётами и запросами к другим системам. Ещё один яркий, но ограниченный по частоте вывод: 1С Enterprise, выставленная во внешний периметр, в опыте команды приводила к недопустимому событию в 87% случаев, хотя встречалась наружу редко.

Почему доминируют Broken Access Control, Authentication Failures и Injection

Эти три категории доминируют не потому, что разработчики не знают слов «авторизация», «пароль» и «инъекция». Проблема в том, что на внешнем периметре они почти всегда соединяются с бизнес-контекстом.

Broken Access Control часто выглядит как локальная ошибка: пользователь видит чужой объект, эндпоинт не проверяет роль, файл отдаётся по прямой ссылке, низкопривилегированный аккаунт может дёрнуть административную ручку. Но во внешнем периметре такая ошибка быстро становится входом в данные, роли, идентификаторы, документы, персональную информацию и дальнейшую бизнес-логику. Именно поэтому IDOR и BOLA нельзя оценивать только по тому, насколько легко перебирается идентификатор. Критичен сам факт отсутствия object level authorization.

Authentication Failures опасны дешевизной атаки. User enumeration, отсутствие rate limit, отсутствие lockout и слабая password policy сами по себе могут выглядеть как «не RCE». Но если внешний нарушитель получает список реальных учётных записей, а затем спокойно проводит password spray, он уже работает не с абстрактной уязвимостью, а с доступом в конкретные системы: почту, VPN, порталы, LDAP-интеграции, административные интерфейсы.

Injection остаётся в верхушке не из-за новизны, а из-за фактических последствий. SQL injection может закончиться не только выгрузкой таблицы. Если рядом лежит идентификатор, обходящий парольную проверку, это компрометация аккаунтов. Если у пользователя СУБД лишние права, например sysadmin, а включён опасный механизм выполнения команд, цепочка доходит до RCE. В этом смысле Injection часто показывает не одну ошибку в параметре, а состояние всей системы: как хранятся секреты, какие права у сервисного пользователя, есть ли сегментация, насколько WAF является последней надеждой.

User enumeration: «маленькая» утечка, которая открывает периметр

Первый большой кейс доклада посвящён user enumeration и слабой парольной политике. Авторы отдельно подчёркивают: некоторые компании и вендоры не считают user enumeration полноценной уязвимостью. Формально ведь не утек пароль, не выполнен код, не прочитана база. Но на практике раскрытие существующих пользователей часто становится первым шагом к пробиву.

Паттерн повторяется в облаках, почтовых шлюзах, прикладных интеграциях, самописном ПО и LDAP-связках. Если приложение не использует нормальную доменную интеграцию или не защищает попытки входа, атакующий строит карту учётных записей, а затем пробует top-100, top-1000 или top-10000 паролей. Чем слабее password policy и чем меньше ограничений на попытки, тем дешевле атака.

В докладе рядом с user enumeration постоянно идут одни и те же недостающие защитные меры:

В одном кейсе команда собрала пользователей и по реальному паролю попала в критичный актив. В другом был выполнен enumeration в Exchange, собраны учётные записи, затем проведен password spray, и одна учётная запись сработала. Дальнейшие детали в транскрипте повреждены, поэтому точную систему и состав доступа авторы статьи не восстанавливают, но итоговая логика понятна: дешёвая атака снаружи дала пробив внешнего периметра.

Ещё один пример связан с LDAP. Перед исследователями была фактически только форма входа, но LDAP оказался достаточно «разговорчивым», чтобы по ответам отличать успешные и неуспешные состояния. Это позволило собрать список доменных учётных записей и примерно к сотне из них подобрать пароль. С технической стороны атака не выглядела сложной. По последствиям она привела к доступу, который уже можно использовать для движения к критичным сегментам контроля, управления или администрирования.

Практический вывод жёсткий: user enumeration нельзя оценивать изолированно. В связке с password policy, rate limit, lockout и доменными учётками это не косметическая утечка, а сырье для password spray, phishing campaigns и первичного доступа.

IDOR/BOLA и ловушка «секретного GUID»

Следующий повторяющийся паттерн — IDOR, BOLA и безопасность, построенная на знании идентификатора. Классический IDOR все знают: есть числовой ID объекта, пользователь меняет 123 на 124 и получает чужие данные. Стандартная рекомендация обычно двойная: использовать неперебираемые идентификаторы и обязательно проверять право субъекта на объект.

На практике, по словам докладчиков, часто реализуют только первую половину: «давайте поставим GUID, его же не перебрать». Это проще, чем строить полноценную ролевую модель и object level authorization. Но GUID решает только задачу перебора. Он не решает задачу авторизации.

В одном из кейсов приложение работало с крайне чувствительной информацией и использовало аутентификацию через ЕСИА — по сути, делегированный OAuth/OIDC-контур входа. Снаружи всё выглядело неплохо. Но при изучении фронтенда обнаружился JavaScript-эндпоинт с признаками внутренней регистрации и ролями, представленными как GUID.

Дальше выяснилось, что отдельная ручка может выдавать валидный токен сессии даже без передачи идентификаторов, которые, судя по логике API, должны были привязывать токен к конкретной сущности. Затем удалось раскрыть схему ролей: какой GUID соответствует какой роли. В результате токен можно было получить с нужной ролью и ходить по системе уже не как обычный внешний пользователь.

Цепочка развилась через бизнес-логику: исследователи повысились до роли работника системы и получили доступ к чувствительной информации о прикрепленных пользователях, файлам и даже ссылкам на видеоконференции. Отдельная деталь особенно показательна: для получения файла роль местами была вообще не нужна, потому что файл защищался только знанием секретного идентификатора. Как только предыдущие ошибки раскрыли эти идентификаторы, защита исчезла.

Недопустимое событие в этом сценарии — массовое раскрытие персональных данных и чувствительной информации, возможность включаться в видеоконференции и влиять на расписание работников системы. И всё это при наличии GUID. Поэтому корректная контрольная мера здесь не «поставить UUID», а object level authorization: каждый доступ к объекту должен проверять, имеет ли текущий субъект право именно на этот объект.

1С во внешнем периметре: редкий, но болезненный класс

Общий паттерн в докладе хорошо читается: когда 1С Enterprise или связанные портальные механизмы оказываются во внешнем периметре, ошибки в публикации, правах и серверной проверке могут быстро приводить к критичным последствиям.

В одном из описанных эпизодов низкопривилегированный пользователь мог манипулировать параметрами, связанными с отрисовкой форм, и получать нелегитимную форму внутри легитимного функционала. Затем через тот же механизм открывался доступ к спискам файлов, персональным данным сотрудников, контрагентам и другой чувствительной информации. В транскрипте отдельно упоминаются контакты поставщиков, правила и другие данные.

Ещё важнее, что ограничения были реализованы на уровне интерфейсных кнопок, а не на уровне серверной проверки действий. Исследователи смогли через манипуляцию ответом сервера отрисовать кнопки, которые формировали легитимные события. Так низкопривилегированный пользователь получил возможность выполнить действия, которые интерфейс ему не показывал, но backend не запрещал. Итогом стала эскалация до администратора портала и доступ к более широкому набору данных, включая персональные данные и коммерческую тайну.

Этот блок хорошо иллюстрирует разницу между UI-ограничением и проверкой авторизации. Если пользователь не видит кнопку, это не значит, что он не может отправить событие. Если роль не проверяется на сервере, внешний нарушитель или низкопривилегированный аккаунт рано или поздно найдёт способ сформировать нужный запрос.

Платформы мониторинга: dashboard, data source и SSRF

Платформы мониторинга в докладе выделены как класс ПО с предрасположенностью к SSRF и смежным ошибкам. Причина в архитектуре: такие системы подключают data source, строят dashboard, генерируют отчёты и часто умеют ходить к другим внутренним или внешним адресам.

Первый кейс был даже не SSRF, а неавторизованный доступ к dashboard и data source. Если data source — база данных, то возможность настраивать отображаемые данные фактически становится возможностью выполнять запросы к этой базе. В описанном случае одним из источников была MySQL-база Asterisk, системы IP-телефонии.

Через такой доступ можно было не просто посмотреть готовые графики, а формировать SQL-запросы, выводить пользователей, пароли, имена и другие данные. Дальше исследователи смогли читать файлы. Критичный ущерб оказался связан с записями разговоров IP-телефонии: были доступны внутренние и внешние разговоры, то есть чувствительная внутренняя информация.

Во втором кейсе в функциональности создания отчётов параметр link, задуманный как путь к локальным файлам, позволял добиться SSRF через символ @. Когда исследователи отправили запрос на свой interactsh-сервер, уязвимый сервер пришёл с заголовком Authorization, где в Basic были учётные данные. Эти credentials подошли к SSL VPN-порталу и оказались доменными.

Один запрос дал доступ во внутреннюю сеть. Это и есть недопустимое событие из позиции внешнего нарушителя: не потому, что SSRF сама по себе красива, а потому, что реализация протащила наружу пригодные доменные учётные данные. Дополнительно SSRF давала account takeover: если ссылку нажимал пользователь системы, запрос приходил с username и password в GET-параметрах.

Controls для такого класса систем должны учитывать не только «запретить SSRF». Нужны изоляция data source, запрет неавторизованного доступа к dashboard, аккуратная работа с Authorization-заголовками, ограничения на исходящие запросы, сегментация и принцип least privilege для учётных данных, которыми мониторинговая платформа пользуется.

Injection: старый класс, новый confirmed impact

SQL injection в докладе разбирается не как технический трюк, а как пример расхождения между названием уязвимости и фактическим confirmed impact.

В первом кейсе в параметре была найдена SQL injection. В базе лежали логины и пароли, причем пароли были хешированы современным алгоритмом и не поддавались обратному восстановлению. На этом история могла бы остановиться: данные есть, но пароли не извлечь. Однако рядом в другой таблице находился идентификатор пользователя, который обходил парольную проверку и безопасное хранение пароля. Через него удалось получить доступ и менять пароли.

Такой сценарий показывает, что правильное хранение паролей само по себе не спасает, если рядом в бизнес-логике есть альтернативный ключ к аккаунту. Защитная мера должна учитывать на весь путь аутентификации и восстановления доступа, а не только на алгоритм хеширования.

Во втором кейсе путь дошел до RCE. После обхода специфической защиты и WAF через URL-encoding исследователи установили, что используется Microsoft SQL Server. Пользователь базы обладал правами sysadmin, а xp_cmdshell был включён. Несколько запросов — и SQL injection превратилась в выполнение произвольных команд на хосте.

Здесь особенно важен принцип least privilege. Уязвимость в параметре опасна сама по себе, но до RCE она дошла потому, что сервисный пользователь имел избыточные права, а опасный механизм был доступен. Если убрать sysadmin и отключить ненужное выполнение команд, цепочка ломается даже при наличии первичной injection.

CMS и модули: когда движок крепче расширений

CMS в dataset выделяются из-за своей модульной природы. Сам движок может быть относительно зрелым, но вокруг него живут модули, самописные плагины, формы, импорт-экспорт, временные каталоги и интеграции. Именно там часто появляются простые, но критичные ошибки.

В одном примере обычный file upload позволял прикрепить PHP-файл, найти его в каталоге вроде tmp-upload и выполнить. RCE получалось одним действием. На этом недопустимое событие уже можно было фиксировать, но последствия оказались шире: на хосте нашли таблицу с персональными данными более чем 400 тысяч человек, а сам хост был связан с внутренним периметром компании.

Во втором примере модуль CMS для импорта-экспорта файлов позволял указать path file. В путь можно было подставить /etc/passwd, после чего система формировала ссылку и отдавала файл. Это local file read, но на практике такие уязвимости редко остаются только «прочитали passwd»: они помогают искать конфиги, ключи, учётные данные, исходники и другие материалы для развития атаки.

Вывод по CMS не в том, что CMS плохи как класс. Проблема в экосистеме расширений и в том, что модуль часто получает доступ к критичным данным и файловой системе, но не проходит такой же контроль, как ядро продукта.

Документация, source maps и разведка, которую недооценивают

Отдельный блок доклада посвящён не уязвимостям в строгом смысле, а источникам разведки: документации, Web Archive, source maps и техническим артефактам.

Когда внешнее приложение не ломается «в лоб», документация помогает понять топологию, API, скрытые функции, роли и административные возможности. Для администраторов хорошая документация полезна. Для внешнего нарушителя — тоже. В одном из примеров документация указывала на функции в админке, которые потенциально могли привести к RCE; точная техническая формулировка в транскрипте повреждена, поэтому её не стоит превращать в конкретный факт, но направление риска понятно.

Отдельный класс — default credentials. Если в документации описаны высокопривилегированные дефолтные учётные записи, а в реальной инсталляции их забыли отключить или сменить, атакующему иногда достаточно определить продукт и попробовать известную комбинацию.

Когда официальная документация исчезает, остаётся Web Archive. По словам докладчиков, архивы иногда сохраняют информацию, которая всё ещё оказывается правдой для развёрнутой системы.

Source maps — ещё один частый источник. Они предназначены для отладки, но могут раскрывать структуру фронтенда, ручки, имена внутренних сущностей и даже credentials. В описанном кейсе в map-файле от stand-сервера лежали учётные данные. Через proxy удалось проверить доступ, после чего появились критичные активы, персональные данные и документы.

Практический урок простой: разведка — часть внешнего периметра. Нельзя проверять только открытые порты и известные CVE, игнорируя документацию, фронтенд-артефакты и тестовые следы, которые попали в production-контур.

Как отдельные баги становятся недопустимыми событиями

Во всех кейсах повторяется одна схема: первичная уязвимость редко выглядит максимальной по критичности, но окружение делает её опасной.

User enumeration становится пробивом, если рядом слабая password policy, нет rate limit и lockout, а найденная учётная запись подходит к Exchange, LDAP, VPN или другому внешнему сервису.

IDOR/BOLA становится массовой утечкой, если объект защищён только GUID, роли раскрываются во фронтенде, token issuance работает без нужной привязки, а файлы отдаются по знанию идентификатора.

SSRF становится доступом во внутреннюю сеть, если сервер добавляет Authorization-заголовок с пригодными credentials, а эти учётные данные имеют доступ к SSL VPN.

SQL injection становится RCE, если сервисный пользователь базы обладает sysadmin, а опасные механизмы выполнения команд включены.

File upload становится пробивом, если PHP-файл можно положить в исполняемый каталог, а на хосте лежат персональные данные и есть связь с внутренним периметром.

Во всех случаях недопустимое событие возникает не из названия уязвимости, а из связки: уязвимость плюс архитектурный контекст плюс права плюс опубликованность системы наружу.

Контрольные меры, которые ломают цепочки

Докладчики предлагают смотреть на контрольные меры как на человекочитаемый способ связать уязвимости с защитными действиями. Это не жёсткая метрика и не замена threat modeling, а практическая рамка: какие меры чаще всего разрывают цепочки от внешней уязвимости к недопустимому событию.

Первая контрольная мера — object level authorization. Низкопривилегированный пользователь не должен получать данные высокопривилегированного или соседнего пользователя. Неаутентифицированный внешний нарушитель не должен получать данные там, где требуется аутентификация. Это базовая защита от IDOR, BOLA, горизонтальных перемещений и доступа по прямой ссылке. GUID может быть полезен, но он не заменяет проверку права на объект.

Вторая контрольная мера — централизованная авторизация. Критичный функционал лучше держать за SSO, вторым фактором и единым контуром проверки, а не публиковать прямые обходные эндпоинты. Если критичная система доступна снаружи без сильной аутентификации, внешний нарушитель получает слишком короткий путь к ущербу.

Третья контрольная мера — least privilege. Пользователь приложения, сервисная учётная запись базы, модуль CMS, мониторинговая платформа и интеграция с data source должны иметь только те права, которые им нужны. SQL injection не должна автоматически превращаться в RCE. Низкопривилегированный пользователь не должен вызывать административные функции. Data source мониторинга не должен быть ключом ко всему внутреннему контуру.

Четвёртая контрольная мера — rate limit. Такое ограничение закрывает не только brute force, но и OTP-перебор, password spray, массовый user enumeration и часть DoS-сценариев. В докладе rate limit подаётся как дешёвая защита против дешёвой атаки: если атакующий собрал пользователей, но не может быстро и безопасно spray-ить пароли, цепочка может остановиться.

Эти контрольные меры хорошо соотносятся с OWASP ASVS: проверка авторизации на уровне объекта, централизованное управление доступом, безопасная аутентификация, ограничения попыток и минимизация привилегий не являются экзотикой. Но доклад показывает, что именно их отсутствие снова и снова превращает рядовые баги в недопустимые события.

Что это значит для внешнего периметра

Для внешнего периметра главный вывод не в том, что нужно «искать больше уязвимостей». Нужно иначе смотреть на связность уже известных классов проблем.

Инвентаризация должна отвечать не только на вопрос «что опубликовано», но и на вопрос «что из опубликованного является критичной системой, административным интерфейсом, мониторингом, 1С, CMS с модулями, LDAP/Exchange/VPN-точкой или источником доменных учётных данных».

AppSec должен проверять не только наличие ролей в интерфейсе, но и серверную проверку прав: object level authorization, запрет прямого доступа к файлам, невозможность подставить роль, невозможность получить token без привязки к субъекту, отсутствие BOLA в API.

Инфраструктурные команды должны смотреть на публикацию систем наружу, MFA, SSO, сегментацию, egress для серверов, права сервисных учёток, связь CMS-хостов с внутренним периметром и учётные данные, которыми пользуются мониторинговые платформы.

Команды разработки должны отдельно обрабатывать Authentication Failures: user enumeration, rate limit, lockout, password policy, реакцию LDAP и других backend на ошибки, защиту от password spray и поведение восстановления доступа.

А приоритизация не должна слепо упираться в CVSS. Как отмечают докладчики, на многие рассмотренные уязвимости можно формально повесить PR:High и успокоиться. Но если confirmed impact показывает массовое раскрытие персональных данных, доступ к VPN, RCE или компрометацию критичного портала, фактическая критичность становится совсем другой.

Вывод

Dataset из 50+ проектов, 150+ 0-day и 250+ уязвимостей показывает не уникальные «звездные» баги, а повторяющиеся паттерны. Broken Access Control, Authentication Failures и Injection доминируют потому, что они хорошо цепляются за реальную архитектуру внешнего периметра: роли, учётные записи, data source, модули, GUID, LDAP, Exchange, CMS, мониторинг и забытые технические артефакты.

Недопустимое событие почти всегда рождается из комплекса: один баг даёт вход, другой раскрывает идентификаторы, третий добавляет лишние права, четвёртый снимает ограничения на перебор, а опубликованная наружу критичная система превращает это в бизнес-ущерб.

Практический ответ тоже комплексный, но не бесконечный: object level authorization, централизованная авторизация, least privilege и rate limit закрывают значительную часть описанных цепочек. Их нужно не просто декларировать, а тестировать с позиции внешнего нарушителя и низкопривилегированного пользователя. Именно там чаще всего видно, где защита существует только в интерфейсе, документации или надежде на «секретный» идентификатор.