Нефункциональное тестирование безопасности ПО
Процесс №19 ГОСТ Р 56939-2024 охватывает проверки, не относящиеся к функциональным возможностям ПО, включая тесты, имитирующие действия потенциального нарушителя. Ручной направленный анализ — один из методов наряду с инструментальными проверками работающего ПО, конфигурации, бинарных файлов, протоколов и инфраструктуры.
Граница законного применения. Все техники и кейсы этой лекции предназначены только для разрешенной проверки: в рамках договора, утвержденной программы испытаний, учебного стенда, внутреннего процесса РБПО или согласованной оценки защищенности. Без явного разрешения такие действия могут быть квалифицированы как неправомерный доступ или нарушение правил эксплуатации информационной системы.
Процесс №19: нефункциональное тестирование
Официальное наименование подраздела 5.19 ГОСТ Р 56939-2024 — «Нефункциональное тестирование». Его цели — подтвердить полноту сведений в поверхности атаки, модели угроз и архитектуре ПО и обнаружить недостатки с помощью нефункциональных тестов, в том числе имитирующих действия потенциального нарушителя. Актуальная карточка стандарта опубликована на портале Росстандарта.
Не смешивать процессы. Ручная экспертиза исходного кода выделена в подраздел 5.9, статический анализ — в 5.10, динамический анализ — в 5.11. Они дополняют процесс 5.19, но не являются его синонимами.
Как процесс связан с жизненным циклом
Пункт 4.3 ГОСТ Р 56939-2024 намеренно не связывает процессы РБПО с конкретной моделью жизненного цикла. Поэтому тестирование кандидата в релиз — возможная, но не единственная контрольная точка. Регламент организации должен определять критерии выбора версий и периодичность тестирования с учётом рисков, изменений и модели угроз.
| Пример контрольной точки | Содержание работы | Результат |
|---|---|---|
| После изменения архитектуры или модели угроз | Уточнение целей, интерфейсов и сценариев атак | Обновлённый регламент и набор тестов |
| Для версии, выбранной по критериям регламента | Нефункциональные тесты, включая имитацию действий нарушителя | Отчёт с доказательствами и ограничениями |
| Перед выпуском значимой версии | Риск-ориентированная проверка релизного кандидата | Решение о выпуске и план устранения недостатков |
| После выявления новых фактов | Повторная проверка и анализ расхождений | Корректировка архитектуры, модели угроз и поверхности атаки |
Что требует процесс 5.19
- 5.19.2.2 и 5.19.3.1: разработать регламент с критериями выбора версий и периодичности, методами и средствами, ролями, типовыми сценариями и возможностями нарушителя;
- 5.19.2.3–5.19.2.4: выявлять локальные и сетевые интерфейсы и выполнять нефункциональные тесты, в том числе имитирующие действия потенциального нарушителя;
- 5.19.3.2: подготовить отчёт с целями, последовательностью действий, ограничениями, доказательствами, оценкой опасности и рекомендациями;
- 5.19.2.5 и 5.19.3.3: сопоставить фактические результаты с архитектурой, моделью угроз и поверхностью атаки и при необходимости скорректировать их.
Зачем нужен эксперт, если есть автоматика
SAST использует не только сигнатуры, но и синтаксический, семантический и межпроцедурный анализ потоков данных. DAST и фаззинг исследуют поведение работающего ПО. Эксперт связывает результаты инструментов с бизнес-логикой, моделью угроз, конфигурацией и реальной средой эксплуатации. Эти подходы дополняют друг друга.
Практический смысл: автоматизированный анализ хорошо масштабируется и воспроизводится, а экспертная проверка добавляет контекст. Например, доступность приватного TLS-ключа может выявиться при анализе прав на развёрнутой системе, даже если сам ключ не находится в исходном коде.
Представить себя нарушителем
Главная задача эксперта — представить себя нарушителем и попытаться нарушить безопасность исследуемой системы в рамках разумной модели нарушителя.
Под «разумной моделью нарушителя» обычно понимается:
- непривилегированный локальный пользователь — имеет доступ к рабочему столу, может запускать любые свои программы;
- удалённый неаутентифицированный пользователь — может посылать сетевые запросы по любым открытым портам;
- удалённый аутентифицированный пользователь — имеет валидную учётную запись с минимальными правами;
- инсайдер с доступом к коду — может изучить исходники, бинарники, конфигурации, файлы данных.
Эксперт не пытается «сломать всё подряд». Он принимает модель угроз, договорённую с заказчиком, и систематически проверяет, может ли нарушитель указанного уровня обойти декларируемые механизмы защиты.
Важное замечание докладчика. Все приведённые далее примеры — из реальных случаев исследования ПО. К какому продукту и какому разработчику относится каждый пример, не упоминается; участки скриншотов, раскрывающие эту информацию, замазаны.
Систематический перебор классов уязвимостей
Практическую проверку удобно строить как систематический перебор заранее определённых классов недостатков и участков поверхности атаки. Такой перечень помогает не пропустить типовые сценарии, но не заменяет модель угроз и не ограничивает исследование только известными шаблонами.
Из чего состоит метод
Знание класса
Эксперт держит в голове 11 типовых классов: от обхода аутентификации до некорректной ASLR. Это не словарь сигнатур, а «карта типичных мест».
Знание признака
Для каждого класса — набор быстрых индикаторов: подозрительно короткий хеш, конкатенация в SQL, незакрытое отладочное API, лишнее имя в выводе dbus-send.
Поверхностный осмотр
Начальный осмотр может быть коротким: файлы конфигурации, листинги директорий, вывод ps, ss или netstat, strings, поиск по бинарникам. Время углублённой проверки определяется риском и качеством найденных индикаторов.
Целевой эксперимент
Если поверхностный осмотр зацепил — эксперт пишет короткий PoC: подсовывает кавычку, генерирует «недопустимый» запрос, перехватывает трафик, пробует dbus-send от имени непривилегированного пользователя.
Почему это работает. Многие уязвимости возникают из-за неверных предположений: «клиент валидирует данные», «никто не прочитает приватный ключ», «протокол сервиса неизвестен». Эксперт фиксирует значимые для модели угроз предположения и проверяет их воспроизводимыми сценариями.
Аутентификация
Одна из распространённых категорий. Условно делится на четыре подкласса: возможен обход; применяется неподходящая криптография; криптография применяется неправильно; криптографическая защита отсутствует там, где она необходима.
4.1
Возможности обхода
Типичная ошибка — не проверить на сервере, прошла ли аутентификация. Бывает, что аутентификация реализуется только в клиентской программе, а сервер полагает: «если запрос пришёл — значит, всё в порядке». Бывает, что в протокол добавляют дополнительные защитные параметры, которые затем не проверяются или проверяются неправильно.
Часто обходы заметны при визуальном просмотре исходного текста. Если ПО небольшое — удобнее всего сгенерировать каждый поддерживаемый запрос сторонней программой и посмотреть, что будет. Если ПО большое, а протокол не очень сложный — пишется простой сканер:
for (перебор по параметрам запросов)
{ Send (текущий вариант);
Error = Receive ();
if (Error != NOT_IMPLEMENTED && Error != ACCESS_DENIED)
cout << параметры запроса;
}
Любой ответ, отличный от «не реализовано» или «доступ запрещён», — повод копнуть глубже.
4.2
Применяется не та криптография
Требуемые алгоритмы, режимы, параметры и реализации должны быть однозначно определены в требованиях к продукту и применимых нормативных документах. ГОСТ Р 34.11-2012 задаёт криптографическую хеш-функцию, но быстрый хеш сам по себе не образует безопасную схему хранения паролей: необходима специализированная парольная функция с солью и настраиваемой вычислительной стоимостью либо явно установленная применимыми требованиями схема. Практические рекомендации по выбору и настройке таких функций приведены в OWASP Password Storage Cheat Sheet.
Реальный кейс: в одной отечественной сборке Linux отечественная криптография отсутствовала из-за ошибки при сборке — прилинковали не ту библиотеку.
Что делает эксперт: ищет по исходникам и бинарникам строки наподобие gost, crypt, проверяет версии заимствованных библиотек — могут быть устаревшие, с неустранёнными уязвимостями.
4.3
Криптография применяется неправильно
Слабые быстрые хеш-функции, например MD5, непригодны для хранения паролей. Длина и формат хеша — только индикаторы, а не доказательство алгоритма. Сравнение результатов для двух тестовых учётных записей с одинаковым паролем помогает выявить отсутствие уникальной соли, но окончательный вывод требует проверки формата, параметров и реализации. Реальные пароли, хеши, ключи, подписи и шифртексты нельзя загружать в онлайн-сервисы: используйте утверждённые офлайн-инструменты и несекретные тестовые векторы.
Попадались случаи, когда секретный ключ хранился в общедоступном файле (см. кейс №1 ниже).
Правило безопасности. Не проектируйте собственные криптографические алгоритмы и протоколы без профильной экспертизы. Используйте проверенные стандартизованные протоколы и поддерживаемые криптобиблиотеки из одобренных источников; фиксируйте версии, ведите SBOM/SCA, проверяйте конфигурацию и своевременно устанавливайте обновления. Заимствование библиотеки не снимает ответственности за архитектуру, управление ключами и безопасную интеграцию.
4.4
Криптография не применяется когда надо
Базовые ошибки, которые ловятся одним tcpdump или Wireshark:
- пароль передаётся по сети в открытом виде;
- по сети передают не пароль, а незашифрованный хеш — это позволяет перехватить его и передать повторно (pass-the-hash);
- для идентификации сетевого соединения используется легкоугадываемое значение, например порядковый номер.
Эксперт обязательно перехватывает трафик пары «клиент — сервер» во всех штатных сценариях: вход, выход, смена пароля, восстановление сессии. Странности видны сразу.
Найди уязвимость: шесть кейсов из реальной практики
Шесть фрагментов из реальных проверок: листинг файлов, хеш пароля, сетевой пакет, JWT-токен, окно файлового менеджера, вывод D-Bus. В каждом — характерный признак уязвимости, который опытный эксперт видит за секунды. Прочитайте, попробуйте найти проблему сами, потом раскройте подсказку.
/.../archive/install/unix/Release/bin/cert/:-rw-r--r-- 1 radmin radmin 1266 авг 31 10:21 10.168.250.201.crt
-rw-r--r-- 1 radmin radmin 1018 авг 31 10:21 10.168.250.201.key
-rw-r--r-- 1 radmin radmin 1702 авг 31 10:21 10.168.250.67.crt
-rw-r--r-- 1 radmin radmin 1241 авг 31 10:21 10.168.250.67.csr
-rw-r--r-- 1 radmin radmin 989 авг 31 10:21 10.168.250.67.key
-rw-r--r-- 1 radmin radmin 1675 авг 31 10:21 10.168.253.21.crt
-rw-r--r-- 1 radmin radmin 1316 авг 31 10:21 10.168.253.21.csr
-rw-r--r-- 1 radmin radmin 1058 авг 31 10:21 10.168.253.21.key
-rw-r--r-- 1 radmin radmin 1706 авг 31 10:21 privatekey.txt
-rw-r--r-- 1 radmin radmin 32 авг 31 10:21 rootCA.crt
-rw-r--r-- 1 radmin radmin 1456 авг 31 10:21 rootCA.key
-rw-r--r-- 1 radmin radmin 1702 авг 31 10:21 rootCA.srl
-rw-r--r-- 1 radmin radmin 18 авг 31 10:21 server.crt
-rw-r--r-- 1 radmin radmin 1332 авг 31 10:21 server.csr
-rw-r--r-- 1 radmin radmin 1142 авг 31 10:21 server.key
-rw-r--r-- не только у privatekey.txt, но и у нескольких файлов с расширением .key: они доступны на чтение всем локальным пользователям. Имена файлов ещё не доказывают их содержимое. Если проверка подтверждает, что один из них содержит действующий закрытый ключ подписи JWT или удостоверяющего центра, соответствующий механизм скомпрометирован. В отчёте нужны тип ключа без раскрытия самого секрета, назначение, права, владелец и безопасное сопоставление с открытым ключом либо иной разрешённый тест использования.
Your String → Qwerty-123
MD5 Hash → f7f12464d28bec02951b713dd016cb58
current request user: Администратор
pwd: f7f12464d28bec02951b713dd016cb58
md5("Qwerty-123") = f7f12464d28bec02951b713dd016cb58. Совпадение результатов у разных тестовых пользователей с одинаковым паролем дополнительно указывает на отсутствие уникальной соли. Реальные учётные данные в онлайн-калькуляторы передавать нельзя.
POST /spring-security-jdbc-example/login.html HTTP/1.1
Host: java-srv:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 75
Origin: http://java-srv:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
_csrf=fbd7a3d8-d139-4764-8e23-f12fee9f95e2&username=admin&password=password
password дополнительно требует проверки: это может быть тестовая, стандартная или просто слабая учётная запись; по одному запросу нельзя сделать вывод о политике паролей всей системы.
{
"alg": "HS512",
"typ": "JWT"
}
.
{
"AccessLevel": "0",
"FileCommandId": "1",
"FileId": "346",
"FileSourceVersionId": "0",
"FileVersionId": "1",
"IpAddress": "Слава России!",
"UserGuid": "' or 1=1; drop table",
"iat": "меня заставляют отправлять сетевые пакеты",
"sub": "УПЯЧКА!!!111 ЖЕПЬ ЕБРИЛО! ХЫВТОНЕ ПОЛЯЧСЫ!!!!"
}
iat по RFC 7519 должно быть числом NumericDate; sub должно однозначно идентифицировать субъект в области издателя; для пользовательских полей нужны типы, диапазоны и серверные правила авторизации. Строка с SQL-синтаксисом становится SQL-инъекцией только при небезопасном использовании в запросе. Если изменённый токен был принят без корректной подписи, это отдельный дефект проверки подписи; если он заново подписан скомпрометированным ключом из кейса №1, дополнительно подтверждается компрометация управления ключами.
\..\..\..\..\Resources\Translation.xaml
# А затем посмотрел, куда он попал:
C:\tmp2\Resources\
Translation(1).xaml 14.04.2020
Translation(2).xaml 14.04.2020
Translation.xaml 18.08.2013
C:\tmp2\Resources, но имена Translation(1).xaml и Translation(2).xaml показывают обработку конфликта имён: исходный файл не был перезаписан. Для вывода о перезаписи потребовались бы хеши или иные доказательства изменения оригинала. Риск остаётся существенным, поскольку в другом каталоге политика конфликтов может допустить замену конфигурации, исполняемого файла или файла автозагрузки.
$ dbus-send --print-reply --dest=org.freedesktop.DBus \
/org/freedesktop/DBus \
org.freedesktop.DBus.ListActivatableNames
... ru.hornshooves.app ...
$ dbus-send --print-reply --dest=ru.hornshooves.app / \
org.freedesktop.DBus.Introspectable.Introspect
<node>
<interface name="ru.hornshooves.app">
<method name="Hello">
<arg direction="out" type="s"/>
</method>
<method name="GetSomeName">
<arg direction="in" type="s"/>
<arg direction="in" type="u"/>
<arg direction="out" type="s"/>
</method>
</interface>
</node>
$ dbus-send --print-reply --dest=ru.hornshooves.app / \
ru.hornshooves.app.GetSomeName string:"aaa" uint32:666
Что объединяет все шесть кейсов. Представленные доказательства получены из развёрнутой системы и её данных. Часть первопричин — например, path traversal или небезопасная работа с секретами — современные SAST и secret-scanning инструменты могут обнаружить в коде. Другие свойства требуют динамической проверки, анализа конфигурации и экспертной интерпретации. Поэтому результаты разных методов нужно сопоставлять, а не противопоставлять.
SQL-инъекции
Практическое руководство: OWASP SQL Injection Prevention Cheat Sheet. Проверка должна сочетать анализ кода и контролируемые негативные тесты.
Простой эмпирический тест
Кавычка или апостроф во входных данных могут вызвать диагностическую ошибку и указать на небезопасную обработку или раскрытие сведений о БД. Это повод для дальнейшей проверки, но не доказательство эксплуатируемой SQL-инъекции:
Ошибка! При проверке пользователя обнаружена ошибка: [DBERRCODE(42601)]
ОШИБКА: ошибка синтаксиса (примерное положение: «А»)
СТРОКА 2: state = 'A'
Параллельно потенциальные SQL-инъекции часто видны визуально в коде. Признак — ручная конкатенация строк запроса:
// Java: так делать нельзя — значение попадает в текст SQL:
String sql = "SELECT * FROM users WHERE username = '"
+ username + "'";
ResultSet unsafeResult = connection.createStatement().executeQuery(sql);
// Параметризация запроса + отдельная проверка парольного хеша:
public boolean login(String username, String password)
throws SQLException {
try (PreparedStatement stmt = connection.prepareStatement(
"SELECT id, password_hash FROM users WHERE username = ?")) {
stmt.setString(1, username);
try (ResultSet rs = stmt.executeQuery()) {
return rs.next()
&& passwordHasher.verify(password, rs.getString("password_hash"));
}
}
}
Параметризуйте значения, применяйте разрешающие списки для идентификаторов, которые нельзя связать параметрами, выдавайте учётной записи БД минимальные права и не возвращайте клиенту подробные сообщения СУБД. Пароли проверяйте библиотечной реализацией адаптивной парольной функции; не сравнивайте исходный пароль в SQL.
XSS
Хороший обзор: OWASP Community — XSS. В общем случае ищутся с большим трудом, но иногда их наличие очевидно.
Реальный пример из проверки — параметр back_url на странице авторизации:
// Безобидный вариант:
http://127.0.0.1/login.html?back_url=http://127.0.0.1/
// А что, если подставить javascript:?
http://127.0.0.1/login.html?back_url=javascript:%0Aalert(document.cookie)
В исследованной системе второй URL приводил к выполнению JavaScript в контексте сайта, а document.cookie возвращал доступные скрипту cookie. Это подтверждает XSS и отсутствие HttpOnly у показанного cookie. В общем случае влияние зависит от атрибутов cookie и архитектуры сессии: HttpOnly препятствует чтению cookie, хотя XSS всё ещё может выполнять действия от имени пользователя. Для back_url нужен разрешающий список схем и адресов назначения; значение нельзя напрямую передавать в исполняемый URL-контекст.
Индикатор, не доказательство. Ошибка после специальных символов показывает, что обработчик нештатно реагирует на ввод. Для подтверждения XSS нужно установить конкретный источник, исполняемый контекст и факт выполнения контролируемого безопасного маркера.
Path traversal
В любом месте, где пользователю предлагается указать имя файла, эксперт пробует ввести имя с путём — и смотрит, что получится.
Что подставлять
../— переход на уровень выше;./— ссылка на текущий каталог, полезная для проверки нормализации;\в начале строки — путь от корня текущего диска в Windows; отдельно проверяются UNC-пути вида\\server\share;/etc/shadow,C:\Windows\System32\config\SAM— абсолютные пути к чувствительным файлам;- однократное и двойное URL-кодирование, например
%2e%2e%2fи%252e%252e%252f; - смешанные разделители, завершающие точки и пробелы, зарезервированные имена и длинные пути в пределах документированных ограничений платформы;
- NTFS-потоки данных вида
file.txt:hidden.
Реальный кейс — окно поиска файлов в защищённой системе. Введя \..\..\..\..\..\..\..\..\..\..\etc\shadow в поле поиска, эксперт получил окно, предлагающее «скачать /etc/shadow» (см. также кейс №5 выше — то же самое в формате имени присоединяемого файла).
Проверяйте нормализацию одинарно и двойно кодированных разделителей и сегментов ... Защита не должна сводиться к удалению подстрок: сервер формирует собственное имя либо канонизирует путь один раз и проверяет, что разрешённый итоговый путь остаётся внутри доверенного базового каталога.
Самописные драйверы и модули ядра
Драйверы и модули ядра имеют высокую цену ошибки: дефект может привести к отказу системы, утечке памяти ядра или повышению привилегий. Наличие собственного драйвера повышает требования к ревью, фаззингу и изоляции испытаний, но само по себе не доказывает уязвимость.
9.1
Высокорисковая поверхность атаки
Используйте структурированный фаззер ядра, например syzkaller, с описаниями целевых интерфейсов, корпусом, сбором покрытия и воспроизведением сбоев. Случайный перебор номеров системных вызовов с произвольными аргументами не эквивалентен такому тестированию: он почти не формирует валидные состояния и плохо измеряет покрытие.
Фаззинг ядра проводят только на изолированном стенде или одноразовых виртуальных машинах со снимками, диагностической сборкой и автоматическим восстановлением. Результатом являются воспроизводимые уникальные сбои и покрытие целевого кода, а не обещание «уронить систему за минуты».
9.2
Утечки данных (Heartbleed-паттерн)
Корректный код IOCTL-обработчика выставляет размер выходного буфера после валидации параметров каждой команды:
switch (code)
{ case CODE1:
if (!CheckParameters1 ()) return ошибка;
SetOutBufferSize (как хочет клиент);
return DoRequest1 ();
case CODE2:
if (!CheckParameters2 ()) return ошибка;
SetOutBufferSize (как хочет клиент);
return DoRequest2 ();
default:
return ошибка;
}
На каком-то этапе автор делает «безобидный» рефакторинг — выносит общий вызов SetOutBufferSize наружу. А спустя пару релизов добавляет команду без параметров:
SetOutBufferSize (как хочет клиент);
switch (code)
{ case CODE1: if (!CheckParameters1()) return ошибка; return DoRequest1 ();
case CODE2: if (!CheckParameters2 ()) return ошибка; return DoRequest2 ();
case CODE3_NO_PARAMETERS:
return DoRequest3 (); // нет CheckParameters — буфер уже выставлен!
default: return ошибка;
}
В результате при обработке запроса с кодом CODE3 клиент получает столько байт случайной памяти ядра, сколько попросит. Реальный кейс — драйвер промышленного ПО под Windows отдавал до мегабайта памяти ядра одной командой.
9.3
Недостаточно ограниченные права
Эксперт проверяет доступ непривилегированных пользователей к собственным устройствам. В Linux анализируются владелец, группа, режимы вроде 0666, udev-правила и полномочия вызывающего. В Windows отдельно проверяются DACL объекта устройства и биты требуемого доступа в кодах IOCTL: FILE_ANY_ACCESS означает, что после открытия устройства данный IOCTL не требует дополнительных прав на дескриптор, но не заменяет проверку DACL и серверную авторизацию чувствительной операции.
D-Bus и COM/DCOM
D-Bus, COM и DCOM — штатные механизмы межпроцессного взаимодействия. Риск возникает, когда продукт экспортирует чувствительные операции без политики доступа или без серверной проверки личности и полномочий вызывающего. Происхождение компонента — собственное или заимствованное — само по себе не определяет защищённость интерфейса.
Доступный сервис не равен уязвимому
В Linux-системах могут присутствовать сервисы управления сеансами, например:
org.freedesktop.login1org.freedesktop.ScreenSaver
Критерий оценки. Возможность заблокировать собственный сеанс может быть штатной функцией и контролироваться политикой авторизации. Находкой становится обход требуемой авторизации, воздействие на чужой сеанс или возможность устойчивого отказа в обслуживании в пределах принятой модели угроз.
Стандартный осмотр шины
Получить список сервисов:
# Для системной шины замените --session на --system.
$ dbus-send --session --print-reply --dest=org.freedesktop.DBus \
/org/freedesktop/DBus \
org.freedesktop.DBus.ListNames
$ dbus-send --session --print-reply --dest=org.freedesktop.DBus \
/org/freedesktop/DBus \
org.freedesktop.DBus.ListActivatableNames
Получить список узлов и интерфейсов конкретного сервиса:
$ dbus-send --session --print-reply --dest=сервис /узел \
org.freedesktop.DBus.Introspectable.Introspect
Далее для каждого относящегося к поверхности атаки метода формируется разрешённый тестовый сценарий: ожидаемые роли, допустимые параметры, отказ для непривилегированного вызывающего и наблюдаемый эффект. Системную и пользовательскую шины проверяют отдельно. Интроспекция помогает построить перечень целей, но не доказывает отсутствие авторизации.
Конфиденциальность IPC. Наблюдаемость сообщений зависит от типа шины, её реализации, политики и полномочий наблюдателя. Секреты не следует передавать в открытом виде только в расчёте на недоступность мониторинга. Для COM/DCOM аналогично проверяются ACL, уровень аутентификации, impersonation и серверная авторизация.
Графические интерфейсы
Графический стек — отдельный мир уязвимостей. Сценарии «приложение видит чужие окна», «приложение посылает чужому окну сообщение», «приложение перехватывает клавиатуру» — на разных платформах решаются по-разному.
X Window System
Linux desktop · традиционныйВ традиционном X11 клиенты, подключённые к одному X-серверу с достаточными разрешениями, нередко могут перечислять чужие окна, синтезировать события и наблюдать ввод. Реальная доступность зависит от настроек X-сервера, расширений безопасности, контейнеризации и способа выдачи полномочий, поэтому её нужно подтверждать экспериментом.
Готовые «фокусы» для проверки:
Wayland · Android · Win Vista+
Современные стекиСовременные стеки сокращают часть межклиентских взаимодействий: Wayland изолирует клиентов через compositor, Android использует изоляцию приложений и разрешения, Windows применяет UIPI и разделение уровней целостности. Эти механизмы уменьшают поверхность атаки, но не устраняют ошибки compositor, accessibility-служб, порталов, IPC и неверной конфигурации.
Эксперт проверяет: используется ли уязвимый стек по умолчанию (Astra/RedOS могут поставляться с Xorg), и не открыт ли «X-сервер для совместимости» в рабочих сценариях.
Окна привилегированных приложений на общем рабочем столе
Если непривилегированный пользователь может заставить привилегированный процесс запустить файловый менеджер, консоль или иной произвольный инструмент без понижения прав, это может привести к повышению привилегий. Актуальность зависит от уровня целостности, изоляции рабочего стола и проверки сообщений. Исторический пример класса — Shatter attack.
Что проверяет эксперт. Открывает «Системный монитор» / диспетчер задач, ищет процессы привилегированного ПО, у которых есть видимые окна на общем рабочем столе. Затем смотрит, к какому пользователю эти окна принадлежат, и пробует послать им сообщения от имени непривилегированного пользователя.
Мандатное управление доступом
Мандатное управление доступом (МУД) — отдельный класс защитных механизмов. У него два характерных вида проблем: программа просто не работает в МУД-окружении, либо работает, но позволяет утечки.
12.1. Совместимость с политикой меток
Программа, не проектировавшаяся для мандатного управления доступом, может нарушать правила переноса меток, терять доступ к ресурсам или создавать нежелательные информационные потоки. Результат зависит от архитектуры приложения, конкретной реализации МУД и политики безопасности, поэтому проверяются штатные сценарии, ошибки и восстановление после отказов.
Пример каскадного распространения меток. Если компонент записывает данные высокой категории в общий словарь, индекс или шаблон, политика может повысить метку общего ресурса и сделать его недоступным в сессиях более низкого уровня. Проверяются правила агрегации, временные файлы, откат и восстановление без нарушения целостности.
12.2. Утечки помеченной информации
Эксперт проверяет, не попадает ли информация высокой категории в ресурсы с более низкой меткой. Типовые направления проверки:
Замкнутая программная среда
Замкнутая программная среда разрешает запуск только доверенных объектов по установленной политике. Её эффективность зависит от полноты контроля всех интерпретаторов, загрузчиков, конфигураций и изменяемых пользователем объектов.
13.1. Типичные пути обхода
- Файлы-исключения, доступные для записи непривилегированным пользователям. Очень характерно для «защищённых» надстроек над Windows.
- Скрипты:
$ bash script.txt > for /f "delims=;" %i in (file.txt) do %i - Эксплойт 38473 из ExploitDB — классическая публичная техника обхода.
- Ярлыки на рабочем столе, если запрещено запускать файловый менеджер: ярлык можно создать вручную или подменить чужой.
- Файлы конфигурации, например
~/.bashrc: попадают в нагрузку оболочки и могут содержать произвольные команды. - Перенаправление ввода-вывода, если запрещён доступ к консольным устройствам.
- Журнальные файлы: вывод программы, не получившей доступа к консоли, может оказываться в доступном на чтение журнальном файле.
13.2. Обход через фронтенд
Если фронтенд использует HTML и JavaScript, нужно проверить, входят ли эти ресурсы, их пакеты и механизмы динамической загрузки в контроль целостности и политику доверенного запуска. Возможность изменения зависит от реализации ЗПС и прав доступа, а не от расширения файла.
Запреты на обращения к опасным интерфейсам могут обходиться динамической генерацией интерпретируемого программного кода: даже если запрещён прямой eval, можно собрать строку из частей и передать в безобидно выглядящий обработчик событий.
Проверка применимости. Наряду с обходами тестируются ложные блокировки, производительность, обновление разрешённых компонентов и диагностируемость отказов. Политика должна быть достаточно строгой для модели угроз и при этом поддерживать штатную эксплуатацию.
Средства отладки и защита бинарных файлов
Пункт 5.19.2.1 прямо включает проверку защищённости бинарных файлов. ASLR — только один слой: эксперт также проверяет DEP/NX, защиту стека, укрепление стандартной библиотеки, PIE, RELRO, CFI/CFG и параметры сборки тестовых конфигураций.
14.1. Средства отладки
Отладочные интерфейсы могут использоваться как непосредственно для НСД, так и для преодоления отдельных элементов защиты. Что должно быть:
В Linux-системах
обязательный минимум- Политика
ptraceи доступ к/proc/<pid>/maps,memи дампам соответствуют принятой модели нарушителя. - Yama,
hidepid, разделение UID и другие механизмы применяются там, где они нужны архитектуре защиты.
В Windows-системах
разумный компромиссПрава OpenProcess и OpenThread, DACL объектов процессов, уровни целостности и отладочные привилегии должны соответствовать модели угроз. Полный запрет не является универсальным требованием, но непривилегированный субъект не должен получать права чтения/записи памяти или отладки защищаемого процесса без обоснованного разрешения.
Реальный кейс. Однажды в эксплуатируемом промышленном ПО нашёлся неудалённый стенд отладки веб-интерфейса — позволял отлаживать SQL-инъекции прямо через GET-параметры. Стенд оставался доступен по сети без какой-либо аутентификации.
14.2. ASLR и комплексное укрепление
ASLR затрудняет эксплуатацию части ошибок памяти, но не предотвращает сами ошибки и не должен рассматриваться отдельно от других механизмов. Что проверяется:
- Энтропия и область применения: основной исполняемый файл и библиотеки собраны как позиционно-независимые, а рандомизация действительно включена на целевой платформе.
- Проверка рандомизации: адреса сравниваются между независимыми запусками и, если применимо, перезагрузками с учётом документированной модели платформы. Совпадения в процессах, созданных через
fork, или у разделяемых модулей сами по себе не доказывают дефект. - Отсутствие злоупотребления отключением: средства отключения ASLR для отдельных процессов не должны применяться без необходимости.
- Устойчивость к повторным попыткам: автоматический перезапуск после сбоя, предсказуемая обработка исключений или информационная утечка могут дать нарушителю оракул и снизить эффект ASLR. Проверяются журналирование, ограничения повторов, аварийное восстановление и отсутствие раскрытия адресов.
Пример для GCC/Clang. Для поддерживаемой платформы рассматриваются -O2, -fstack-protector-strong, максимально поддерживаемый совместимой libc и компилятором уровень -D_FORTIFY_SOURCE=3 (либо =2), -fPIE -pie и -Wl,-z,noexecstack,-z,relro,-z,now. FORTIFY требует включённой оптимизации, а фактический эффект флагов проверяется по итоговому бинарному файлу. Для тестовых сборок применяются -fsanitize=address,undefined и -fno-omit-frame-pointer; санитайзеры не заменяют защиту релизной сборки. Общие принципы и проверка параметров сборки приведены в OWASP C-Based Toolchain Hardening Cheat Sheet.
Пример для MSVC. Проверяются /GS, /DYNAMICBASE, /NXCOMPAT, /guard:cf и, при поддержке платформой, /CETCOMPAT. Конкретный набор фиксируется в требованиях к сборке и проверяется по итоговым бинарным файлам.
Чек-лист эксперта: 38 контрольных вопросов
Авторский практический опросник для подготовки сценариев процесса №19. Он помогает разработчику и эксперту, но не заменяет регламент по 5.19.3.1, отчёт по 5.19.3.2 и сопоставление с архитектурой, моделью угроз и поверхностью атаки по 5.19.3.3.
№ 1–4
Аутентификация и протоколы
- Какие запросы к серверу доступны без аутентификации? Достаточно ли ограничен перечень таких запросов? Как это проверялось — визуальным просмотром кода, вводом тестовых запросов вручную, созданием автоматического сканера на основе системы тестов?
- Допустимо ли, если сервер получает пакеты не от штатной клиентской программы, а от сторонней программы? Если нет — каким образом реализуется запрет подключения таких клиентов? Если да — точно ли это не приводит к нарушениям безопасности (например, если функция безопасности реализована не на сервере, а только в клиентской программе)?
- Какой протокол аутентификации применяется? Если самописный — кто его разрабатывал и тестировал? Если стандартный — точно ли он подходит к данной конкретной ситуации?
- Есть ли в протоколе дополнительные параметры, повышающие безопасность (ограничения по адресам подключения, времени подключения, сроку действия ключей и т. п.)? Они точно используются? Как это проверялось?
№ 5–15
Криптография и работа с ключами
- Как сервер устанавливает длины буферов с передаваемыми клиенту данными? Нет ли HeartBleed-подобных уязвимостей?
- Какие криптосистемы применяются? Точно ли реальность соответствует документации? Как это проверялось? Проверялись ли особые случаи (например, в Linux-совместимой ОС самый первый пользователь, создаваемый при установке)? Не применяются ли самописные криптоалгоритмы?
- Какой заимствованный код используется в проекте? Какие в нём известны уязвимости? Проводилась ли работа по анализу заимствованного кода как минимум на уровне мониторинга открытых источников? Проводится ли такая работа на регулярной основе? Какая реакция предусмотрена в случае обнаружения в заимствованной библиотеке критической уязвимости?
- Применяются ли в проекте устаревшие криптосистемы наподобие DES, MD5, RC4? Если да — безопасно ли это?
- Используется ли для хранения паролей специализированная адаптивная парольная функция с уникальной солью и установленными параметрами стоимости? Проверены ли формат хеша, библиотека, параметры, обновление схемы и сравнение результатов для тестовых учётных записей?
- Как вводятся ключи шифрования? Если они хранятся внутри системы — как реализовано это хранение? Кому могут быть доступны эти данные в каких ситуациях?
- Передаются ли пароли по сети в открытом виде? Проверялось ли это перехватом и анализом трафика?
- Передаются ли по сети хеши аутентификации в открытом виде? Проверялось ли это перехватом и анализом трафика?
- Если защита трафика полагается на TLS — как обрабатываются ошибки проверки сертификата, неподдерживаемые версии протокола и невозможность установить защищённое соединение? Исключён ли переход к открытому трафику?
- Как сервер идентифицирует сетевые соединения клиентов? Не используются ли легкоугадываемые идентификаторы (например, порядковые номера), передаваемые прямо в пакете с данными?
- Какие генераторы случайных чисел применяются в проекте? Не применяются ли для криптографических задач линейные рекурренты или другие неподходящие алгоритмы?
№ 16–18
Инъекции и валидация ввода
- Проводились ли проверки кода на наличие SQL-инъекций? Какие средства формирования SQL-запросов применяются в проекте? Не формируются ли SQL-запросы вручную (
sprintfи т. п.)? Если подавать на вход непарные кавычки, апострофы и т. п. — не появляются ли в ответах сервера ошибки SQL? - Проводились ли проверки кода на предмет наличия XSS-уязвимостей? Как сервер реагирует на вручную сформированные пакеты, похожие на штатные, но с необычными заполнениями полей? Как сервер реагирует на команды JavaScript, размещаемые внутри пакета? Может ли нарушитель добиться их некритичного размещения внутри веб-системы? Если имитировать ввод в формы непарных кавычек, апострофов и т. п. — не появляются ли в ответах ошибки веб-интерфейса? Насколько корректно сервер принимает пакеты с текстом в необычных кодировках?
- Как обрабатываются ситуации, когда клиент указывает имя файла вместе с путём? Не пытается ли сервер применить этот путь к своей файловой системе? Как при этом обрабатываются подстроки
.., строки, начинающиеся с\в Windows и т. п.? Если делается санитизация — можно ли её обойти необычными кодировками текста или какими-то другими ухищрениями?
№ 19–25
Драйверы, права доступа, IPC и интерфейсы ОС
- Проверялись ли драйверы и модули ядра структурированным фаззером с описанием целевых интерфейсов, сбором покрытия и воспроизведением сбоев на изолированном стенде?
- Как ограничиваются права доступа к файлам приложения? Что может сделать с файлами приложения непривилегированный пользователь, используя предоставленные права? Если приложение работает в Windows — те же вопросы задаются в отношении ключей реестра и объектов корневой файловой системы (
\??\*и т. п.). - Как ограничиваются права доступа к устройствам, обслуживаемым исследуемым драйвером? Драйвер полностью полагается на права доступа, заданные в ОС, или дополнительно реализует собственные проверки? Что может сделать с драйвером непривилегированный пользователь?
- Как ограничивается доступ к реализованным в проекте сервисам D-Bus или интерфейсам COM/DCOM? Что может делать непривилегированный пользователь, используя предоставленные права?
- Соответствуют ли права на отладочные интерфейсы принятой модели угроз? Может ли непривилегированный субъект читать или изменять память, получать дампы либо отлаживать защищаемый процесс без обоснованного разрешения?
- Принимаются ли в проекте специальные меры, блокирующие доступ сторонних приложений через графический интерфейс операционной системы? Не стоит ли их принять?
- Не создаёт ли анализируемое ПО на общем рабочем столе окна, обслуживаемые высокопривилегированным процессом? Могут ли такие окна создаваться непредумышленно — например, при запуске справки или после аварийного завершения Windows Explorer? Что может сделать непривилегированный пользователь, направляя в эти окна специально подобранные комбинации сообщений? Не стоит ли избавиться от таких окон?
№ 26–38
Защитные механизмы, анализ кода, чувствительные данные
- Поддерживает ли анализируемое ПО мандатное управление доступом? Если да — все ли функции работают в секретных сессиях? Как это проверялось? Возможны ли утечки информации, помеченной как секретная, через поисковые индексы, журнальные файлы, графические интерфейсы, привилегированные системные процессы, внешние накопители информации, другими путями?
- Поддерживает ли анализируемое ПО изолированную (замкнутую) программную среду? Если да — блокированы ли типичные пути обхода через файлы-исключения, скрипты, эксплойт 38473 из ExploitDB, ярлыки на рабочем столе, файлы конфигурации, перенаправление ввода-вывода, журнальные файлы и т. д.? Распространяются ли правила ЗПС на интерпретируемый и динамически генерируемый программный код, COM-подобные интерфейсы и т. д.? Не вызывают ли правила ЗПС сбоев при доступе к принтерам, внешним накопителям, сети и т. д.?
- Какие механизмы укрепления применены к итоговым бинарным файлам: ASLR/PIE, DEP/NX, защита стека, FORTIFY, RELRO, CFI/CFG и платформенные аналоги? Подтверждены ли они анализом релизных бинарных файлов?
- Проводился ли статический анализ исходных текстов проекта? Проводится ли он на регулярной основе? Как организовано реагирование на предупреждения статического анализатора?
- Какие принимаются меры для защиты от переполнений буфера? Используются ли в коде проекта небезопасные функции обработки строк? Присутствуют ли в программе переполнения буферов?
- Какие принимаются меры для защиты от обращений к освобождённой памяти? Присутствуют ли в программе ошибки обращения к освобождённой памяти?
- Какие принимаются меры для защиты от ошибок двойного освобождения памяти? Присутствуют ли в программе ошибки двойного освобождения памяти?
- Используются ли в проекте форматные строки (
printfи т. п.)? Какие принимаются меры для защиты от ошибок в работе с форматными строками? Присутствуют ли в программе ошибки работы с форматными строками? - Какие принимаются меры для защиты от утечек памяти? Присутствуют ли в программе утечки памяти?
- Какие принимаются меры для обеспечения корректной многопоточности (недопущение race conditions и deadlocks)? Присутствуют ли в программе ошибки обеспечения корректной многопоточности?
- Построена ли для приложения поверхность атаки? Предпринимались ли попытки её построить? Полностью ли она покрыта вышеперечисленными вопросами?
- Проводилось ли фаззинг-тестирование приложения? Планируется ли его проводить? Учитывалась ли перспектива проведения фаззинг-тестирования при проектировании архитектуры и в ходе разработки приложения?
- Работает ли приложение с чувствительными данными (пароли, ключи шифрования, идентификаторы банковских счетов и т. п.)? Какими? Проводилось ли для приложения автоматизированное выявление утечек чувствительных данных? Были ли выявлены утечки и какие?
Как пользоваться чек-листом. Разработчику — как контрольный самотест, эксперту — как основа интервью и сценариев. Поводом для исследования является не само слово «нет», а ответ, который противоречит требованиям и модели угроз, не подтверждён доказательствами либо оставляет существенный риск без обоснованного решения.