
Всем привет! Меня зовут Саша Симоненко, и я операционный директор кибербез компании Xilant. Эта статья родилась из моего сентябрьского выступления на конференции KazHackStan 2025 в Алматы, где рассказывал, как качественные бизнес-требования помогают избежать проблем с безопасностью.
В первой части статьи разберем, как неточные формулировки превращаются в реальные инциденты и где в процессе теряется безопасность.
Все начинается с формулировки
Рассмотрим типичную ситуацию — в проекте появляется требование:
«Быстрая интеграция с партнером»
На первый взгляд требование логично — нужно ускорить процесс обмена данными, чтобы запустить совместный сервис в срок.
На совещании это звучало как разумный компромисс: партнер надежный, зачем тратить время на избыточные проверки. Разработчики восприняли формулировку буквально — убрали валидацию входящих данных, сократили аутентификацию и упростили обработку ключей API.
На уровне кода все было корректно — логика работала, данные приходили, тесты проходили. Но в проде партнерский сервис отправил поврежденный payload, и система безоговорочно его приняла. В результате произошла утечка персональных данных и компрометация ключей доступа. Пришлось откатывать релиз.
Но как вы понимаете, проблема была не в коде — разработчики сделали ровно то, что было написано. Проблема в словах: требование поставило скорость выше безопасности, не уточнив, что именно можно оптимизировать, а что должно остаться неизменным.
Еще пример
Или возьмем другую ситуацию — требование «пользователь может сбрасывать пароль через email». Звучит стандартно, правда? Но в формулировке нет ни слова о сроке действия ссылки, количестве попыток, ограничении по IP или одноразовости токена.
В реальных проектах из-за таких упущений возникали уязвимости, когда токен сброса можно было использовать повторно или передавать другим пользователям. Функция работала «как задумано», тесты проходили, но система была уязвима с самого начала.
Это не единичные случаи. Это паттерн, который повторяется в проектах снова и снова. Уязвимости закладываются не в коде — они рождаются в момент, когда мы формулируем задачу.
Баг не в коде, а в словах
В обоих примерах проблема возникла не в разработке. Она появилась раньше, на этапе формулировки требования. Оба требования оставляли слишком много свободы: что можно убрать, что можно упростить, где границы допустимого. И команда сделала выбор по умолчанию — почти всегда не в пользу безопасности.
Например, требование «удобная авторизация» может привести к тому, что в системе появится авто-логин без MFA, потому что так действительно «удобнее». Или «гибкая настройка ролей» превратится в возможность администратору менять права без дополнительного подтверждения.
Часто эти формулировки звучат безобидно:
«данные должны быть доступны»
«партнер должен иметь полный доступ к API»
«пользователь должен быстро восстанавливать пароль»
Но именно в таких словах кроются риски. За каждой фразой — десяток невысказанных вопросов:
«Доступны» — кому? на каких условиях?
«Полный доступ» — к каким именно сущностям и операциям?
«Быстро» — это две секунды или две минуты?
Когда контекст не зафиксирован, каждый участник проекта понимает по-своему. В итоге система реализует противоречивую или небезопасную логику.
Почему требования = уязвимости
Все эти примеры — про одно и то же: уязвимости зарождаются задолго до написания кода. Они появляются там, где требования звучат расплывчато, где остается место для интерпретаций и компромиссов.
Так почему же требования и становятся уязвимостями?
Потому что именно на этом уровне определяются границы того, как будет работать продукт, как его проверят и что в итоге посчитают нормой.
Требования задают границы реализации, тестов и приемки.
Если эти границы размыты, команда неизбежно делает допущения.
Неоднозначные формулировки ведут к разным инженерным интерпретациям.
Для одного «быстро» — это оптимизация запросов, для другого — снятие проверок ради скорости.
Пропуски в нефункциональных требованиях означают отсутствие защиты по умолчанию.
Если не сказано, что данные должны шифроваться, скорее всего, они не будут шифроваться вовсе.
Незаметные, но опасные элементы требований
Есть детали, которые кажутся второстепенными, но могут стать корнем серьезных проблем:
Неформализованные сроки хранения («вести логи») без указания retention-периода — по факту означает «хранить всё вечно».
Требования вроде «максимальная доступность» без уточнения про rate-limit или резервное MFA.
Конфликтующие требования: «удобный вход через соцсети» и «минимизация передачи данных третьим лицам».
Полное отсутствие упоминания о шифровании, аудитах и контроле доступа. Молчание в требованиях — это тоже формулировка, только негативная: она означает, что безопасность никем не предусмотрена.
На первый взгляд такие вещи не вызывают тревоги. Но именно они превращаются в уязвимости, когда система попадает в прод и начинает взаимодействовать с реальными данными и пользователями.
Что делает требование опасным
Чек-лист: как распознать слабое требование

Почему логика не спасает от риска
Даже грамотно построенное требование может быть опасным, если в нём отсутствуют критерии безопасности. Скажем, «пользователь может редактировать свои данные» — абсолютно логичное правило. Но если не уточнить, что речь идет только о собственных данных, и только о конкретных полях, появляется риск вертикальной или горизонтальной эскалации — IDOR, инъекция, подмена параметров.
Код будет идеальным, тесты зеленые, а проблема - уже внутри.
Роль негативных сценариев
Большинство требований описывают «позитивные сценарии»: что должно произойти, когда все работает правильно. Но системы ломаются именно в «негативных» сценариях - когда данные некорректны, пользователь ведет себя нетипично или кто-то пытается использовать фичу не по назначению.
Поэтому важно формулировать «misuse-cases»: что если пользователь попытается загрузить слишком большой файл? Что если партнер отправит пустое поле? Что если токен доступа будет повторно использован?
Такие сценарии часто не прописываются, потому что считаются «техническими деталями». Но именно они позволяют предотвратить уязвимости ещё на бумаге, до написания первой строки кода.
Когда не хватает нефункциональных деталей
Нефункциональные требования (NFR) для безопасности — не украшение спецификации, а ее система координат. Если в них не указано, как шифруются данные, где хранятся ключи, какие аудит-события фиксируются, то разработчики действуют по умолчанию. А по умолчанию обычно - никак.
В итоге защита превращается в импровизацию: кто-то включит шифрование, кто-то забудет, кто-то поставит логирование только в dev-среде. И вся архитектура превращается в мозаику из частных решений.
Где в процессе появляются уязвимости
Слабые требования — не ошибка одного этапа, а следствие того, как меняется фокус на разных шагах разработки.

Этап 1: Сбор — потеря контекста
На этапе discovery-встреч и первых согласований большинство идей формулируются устно: «надо интегрироваться с партнером», «нужно, чтобы клиенту было удобно». Эти фразы потом превращаются в короткие user-stories без деталей.
И уже при передаче от бизнеса к аналитикам, от аналитиков к разработчикам теряется контекст: кто именно партнер, какие данные пересылаются, какие проверки нужны. То, что изначально было очевидно на словах, перестает существовать в документации.
Этап 2: Формализация — выпадают security-критерии
На практике безопасность чаще всего теряется здесь — в переходе между аналитикой и разработкой. Когда документ с требованиями уже утвержден, но еще не переведен в технические задачи.
Обычно это происходит по двум причинам.
Первая — нехватка времени: «потом добавим». Но «потом» обычно не наступает.
Вторая — отсутствие шаблонов и практик. Если у бизнес-аналитика нет готовой структуры security-acceptance, он физически не знает, куда вставить требование про шифрование или аудит.
В итоге в Jira остаются задачи без критериев безопасности, без описания нефункциональных требований и негативных сценариев. Приоритизируется функциональность — «чтобы работало», а не «чтобы было безопасно».
Этап 3: Оценка и разработка — пропуск security-review
Когда фича не проходит через AppSec-ревью, а тесты ограничиваются «счастливыми путями», уязвимости становятся невидимыми. В коде все работает, QA доволен, а в проде — SQL-инъекция или уязвимость авторизации.
Негативное тестирование и security-ревью нужны не для галочки — это способ увидеть, как система поведет себя, когда что-то пойдет не так.
Этап 4: Приемка — отсутствие security-gate
При приемке важно не просто убедиться, что требование реализовано функционально («кнопка нажимается», «данные сохраняются»), а проверить, что оно безопасно реализовано. Шифруются ли поля? Есть ли аудит действий? Отрабатывает ли MFA?
Подобные проверки должны быть частью чек-листа приемки, наряду с UI- и UX-тестами. Без этого security-gate превращается в чистую формальность.
Разработчик не видит требований по безопасности, тестировщик не знает, что проверять — и уязвимость уходит в прод.
Как это исправить
Чтобы показать масштаб проблемы, возьмем два примера посмотрим, что с ним не так — и как должно быть.
Плохо: «Система должна защищать персональные данные»
Как исправить: Уточнить scope (какие поля), добавить шифрование at-rest/in-transit, RBAC, логирование и retention, ротацию ключей, measurable acceptance.
Хорошо: Система должна хранить персональные данные пользователей (name, email, phone, passport_number) зашифрованными at-rest (AES‑256‑GCM с per‑record IV). Транспорт — TLS 1.3. Доступ — только роли 'admin' и 'data-processor'. Логи доступа сохранять 365 дней. Ключи ротируются каждые 90 дней.
Acceptance: автотест шифрования и CI-симуляция ротации ключей
Еще пример
Плохо: «Логировать подозрительную активность»
Как исправить: Перечислить события (auth failures, admin actions), поля логов (user, IP, timestamp, reason), alert thresholds, формат и retention, интеграцию с SIEM.
Хорошо: Логировать authentication failures, privilege escalations и admin actions с полями user, IP, timestamp, action, reason. Alert при >10 failures/min с одного IP. Логи отправляются в SIEM, retention 365 дней.
Acceptance: тест записи и оповещений в тестовом SIEM
Неточные требования — не просто неудобство. Это прямой путь к уязвимостям в продакшне. Мы показали механику: как слова превращаются в проблемы, где теряется контекст, почему команды принимают решения не в пользу безопасности.
Теперь вопрос — как это предотвратить?
В следующей части разберем конкретные инструменты: чек-листы, шаблоны и техники для написания требований, которые закрывают риски еще до разработки.
А пока - делитесь в комментариях своими историями с плохо сформулированными требованиями! Спасибо, что дочитали, также в качестве рекомендаций хочу попросить вас подписаться на мой канал "Крупицы знаний" (там я периодически публикую интересные статьи и ролики), а также на канал Xilant. Увидимся в следующей части!
Что еще почитать от Xilant:
Этот WSUS убьёт вашу корпоративную сеть. Разбор CVE-2025-59287
Как работает Blind LDAP Injection — на примере реального CTF-задания
Комментарии (7)

LinkToOS
05.11.2025 10:49Рассмотрим типичную ситуацию — в проекте появляется требование:На совещании это звучало как разумный компромисс:
разработчики сделали ровно то, что было написано."Разработчики" - это команда. Поэтому надо всю цепочку формулировок приводить, как исходное требование проходило от руководителя до кодера, и где случился фейл.
На совещании озвучивается концепция. Все технические детали прорабатываются на более низком уровне. Проработка занимает время, и требует наличие обратной связи. Это же не армия где все быстро и просто - "Приказываю захватить!", "Дивизия вперед!", перегруппировка, отступление, капитуляция.На практике безопасность чаще всего теряется здесь — в переходе между аналитикой и разработкой.
Слишком упрощенная схема. Не видно слабого звена, которое недоработало. Всегда есть конкретный человек, с компетенциями и зоной ответственности, который совершил ошибку.

senkora Автор
05.11.2025 10:49Слишком упрощенная схема. Не видно слабого звена, которое недоработало. Всегда есть конкретный человек, с компетенциями и зоной ответственности, который совершил ошибку.
Я согласен, что схема упрощенная, более детально эти аспекты будут раскрыты в следующих статьях этой серии.

sasha_solo
05.11.2025 10:49Такое ощущение, что разработчики тут как злой коварный джин, который специально неправильно понимает желание хозяина, как в фильме кино wishmaster.

senkora Автор
05.11.2025 10:49Интересное замечание, но на самом деле совсем наоборот, разработчики в 99% случаев оказываются крайними, вместе с QA если вдруг произойдет инцидент. И всё по причине того, что фича нужна уже "завтра" и дедлайн близко.
Daemonis
Может, потому что одноразовость, срок действия и количество попыток - это стандартные требования?
inspectornaix
Да, это стандартно... для безопасности. К сожалению, стандартом для бизнес-требований часто является "сделай быстрее и чтобы работало". Пока кто-то явно не скажет "и безопасно", эти "стандартные" вещи благополучно выносятся за скобки.
senkora Автор
Я вполне согласен, что это стандартное требование, но как мне кажется оно таким становится на определенном уровне зрелости специалистов, команды и бизнеса в целом.
Но номинально, стандарт может быть разный в зависимости от компании, сферы деятельности или нормативной базы в рамках которой создается продукт. Поэтому я и пытаюсь донести, что стоит сразу формулировать требования достаточно конкретными.