Николай Мозговой, старший разработчик и ментор в Sigma Software, в настоящее время занимающийся разработкой облачного бэкенда для климатических систем, опубликовал на DOU.UA статью, посвященную вопросам кибербезопасности. Представляем ее вашему вниманию.
Вопрос кибербезопасности должен быть предметом особого внимания не только для экспертов, но и для рядовых разработчиков. Однако не каждый проект может позволить себе отдельного специалиста по безопасности, поэтому весьма вероятно, что нести это бремя придется вам.
Для таких случаев неплохо иметь напоминание или шпаргалку; поэтому я составил список вопросов, которым нужно уделить внимание. Этот список и не краткий, и не исчерпывающий, но, по крайней мере, он представляется вполне понятным и осуществимым. Должен признаться: на представленный ниже материал меня вдохновил один очень хороший курс, который я проходил несколько лет назад и который рекомендую всем, кого интересует вопрос InfoSec/Cybersecurity. Это курс Software Security от Университета штата Мэриленд, свободно доступный на Coursera.
Особенности безопасности ПО
Безопасность программного обеспечения концептуально отличается от функциональных требований, о которых мы заботимся в первую очередь, и не столь интуитивно понятна. Тем не менее безопасность — это важнейшее свойство программного обеспечения, особенно когда речь идет о машинах с программным управлением, которые могут повлиять на жизнь и здоровье клиентов, или системах, обрабатывающих личные данные.
В то время как желаемое поведение программы зачастую воспринимается как основная цель, в противовес этому главная цель безопасности — предотвратить действия, которые программа делать не должна, другими словами, избегать нежелательного ее поведения.
Свойства безопасности
Существует три основных свойства безопасности программного обеспечения, отсутствия которых мы стремимся предотвратить:
- конфиденциальность (Confidentiality) — означает, что информация не должна передаваться неавторизованным лицам;
- целостность (Integrity) — сохраненная информация не должна быть повреждена вследствие вмешательства неавторизованных лиц или системных сбоев;
- доступность (Availability) — то есть система должна всегда реагировать на запросы (в рамках согласованных требований).
В то время как доступность интуитивно ассоциируется с защитой от DoS-атак, она ими не исчерпывается. Есть задачи не меньшей важности:
- апгрейды приложений;
- продление прав на IP-адрес;
- продление прав на доменное имя;
- обновление сертификатов шифрования и аутентификации.
Каждый раз, когда нарушаются свойства безопасности, программное обеспечение считается уязвимым.
Уязвимость (Vulnerability) — это связанный с безопасностью дефект программного обеспечения, который можно использовать для достижения нежелательного поведения. Если уязвимость вызвана дефектом дизайна, а не кода, она называется изъяном, или брешью (Flaw).
Принципы безопасности
Существует ряд общих принципов, которым нужно следовать при создании защищенного программного обеспечения. В целом эти принципы можно разделить на следующие категории:
- Предотвращение (Prevention) — исчерпывающее устранение дефектов. Например, можно предотвратить целые категории дефектов, используя языки, безопасные для памяти, такие как Java или C# вместо C/C++.
- Смягчение (Mitigation) — уменьшение вреда от эксплуатации неизвестного дефекта. Например, вред от взломанной базы данных можно значительно уменьшить, если зашифровать сохраненные данные. Еще один пример — блокировка учетных записей с подозрительным поведением и требование дополнительного подтверждения для потенциально опасных действий.
- Обнаружение (Detection) — выявление и анализ атаки (то есть мониторинг). Необходимо как можно скорее получать информацию о потенциально вредоносных действиях. В этом случае очень помогает комплексная телеметрия в реальном времени.
- Восстановление (Recovery) — нейтрализация урона. «Быстро поднятое упавшим не считается». Поэтому всегда необходимо иметь резервную копию данных и дополнительные ресурсы, которые будут доступны в случае экстренной необходимости. Кроме того, крайне важно иметь процедуры восстановления взломанных учетных записей.
Ниже приведены основные принципы, которым нужно следовать при разработке, внедрении или обслуживании программного обеспечения.
Отдавайте предпочтение простоте (Favor simplicity — prevention).
- Выбирайте простую архитектуру. «Keep it simple, stupid» — этот известный мем прекрасно работает в этом контексте. Например, подумайте дважды, когда вы выбираете между старомодным монолитом и сверхкрутыми микросервисами. Всегда учитывайте имеющиеся возможности и опыт.
- Применяйте безопасный выбор по умолчанию (fail-safe defaults). Никогда не используйте пароли, выданные по умолчанию, применяйте стандартную криптографию, отдавайте предпочтение белым спискам, а не черным и т. д.
- Не ожидайте продвинутого пользователя. Чем больше возможностей вы даете, ничего не ограничивая, тем выше вероятность злоупотребления ими. Например, установка приложений из ненадежных источников на Android (файлы APK) требует отдельной активации этой функции в настройках устройства.
- Отдавайте предпочтение простому пользовательскому интерфейсу (UI). Повторюсь, сложность — враг безопасности. Сложный UI повышает вероятность ошибки как со стороны разработчика, так и со стороны пользователя.
- Не позволяйте пользователям делать выбор в отношении безопасности. Вы не должны предполагать, что пользователи понимают схемы криптографии или хотя бы правила безопасного поведения в интернете, поэтому не позволяйте им выбирать алгоритмы и ключи шифрования или небезопасные пароли.
Доверяйте с осторожностью (Trust with reluctance — prevention & mitigation).
- Используйте минимальную доверенную вычислительную базу (trusted computing base). Чем больше компонентов — как аппаратных, так и программных — имеет ваша система, тем больше возможных направлений для атак. В этом смысле каждая новая платформа, которую вы собираетесь поддерживать, и каждый сервис, который вы интегрируете, должны рассматриваться как источники риска и опасности.
- Избегайте применения вашей собственной криптографии. Криптография — это настолько нетривиальный предмет, что попытка реализовать ее аспекты самостоятельно не более чем тщеславие, если, конечно, вы не являетесь экспертом. Правильный подход заключается в использовании открытых, стандартных для отрасли протоколов и алгоритмов.
- Максимально ограничивайте полномочия для компонентов и пользователей. Будьте осторожны при предоставлении прав своему приложению и пользователям (даже непрямым образом). Вашему приложению действительно нужен доступ к файловой системе? Точно ли нужно выполнять операции чтения из базы данных под учетной записью с более высоким уровнем доступа?
- Валидация входящих данных. Не скармливайте вашей системе некорректные данные. Четко определите границы корректности данных и проверяйте их, используя белые списки.
- Усиливайте конфиденциальность — ограничивайте доступ к персональным данным.Формальное определение персональных/личных данных может различаться в зависимости от местного законодательства, но общая характеристика личных данных — это прямая или косвенная возможность определить, какому лицу эти данные фактически принадлежат.
- Обособление (compartmentalization) — используйте процессы, контейнеры и «песочницы», чтобы отделить компоненты и даже операции друг от друга.
Защита в глубину (Defense in depth — prevention, mitigation & recovery).
- Безопасность в силу разнообразия (HTTPS + безопасный язык + шифрование данных + VPN). Объедините все механизмы безопасности, имеющиеся в вашем распоряжении. В то же время не используйте инструменты вне своей компетенции, а при необходимости найдите эксперта.
- Используйте стандартные и открытые решения. Избегайте принципа «безопасность через неясность» (security through obscurity). Избавьтесь от мысли, что проприетарное программное обеспечение или протоколы (особенно ваши собственные) обеспечивают защиту лишь на том основании, что они никому не известны. Только общедоступные и изученные инструменты и протоколы могут претендовать на безопасность.
Мониторинг и отслеживание (Monitoring and traceability — prevention & recovery).
- Собирайте логи и телеметрию. Не забывайте установить оповещение при обнаружении опасных/подозрительных событий.
- Создавайте резервные копии / снимки состояния (snapshots). Храните их на отдельных серверах и разрабатывайте механизмы их восстановления.
Конечно, можно вывести большее число подобных принципов, но, как правило, достаточно будет следовать уже определенным.
Безопасный процесс разработки
Чаще всего на проблемы безопасности реагируют реактивно, откладывая их до тех пор, пока они не станут явными и недопустимыми. Это ущербный подход. Безопасный процесс разработки означает, что необходимые действия и практики вводятся для каждого этапа разработки.
Требования:
- Определите требования к безопасности (сценарии нарушения, abuse cases). Сценарий нарушения — противоположность сценарию использования (функционального требования, use case). Он четко определяет, что система не должна делать.
- Определите необходимые свойства безопасности для компонентов системы (то есть конфиденциальность, целостность, доступность). Прямо обозначьте, какие части хранимых данных являются конфиденциальными. Определите, какие роли присутствуют в системе и с какими данными они должны работать. Опишите требования к доступности.
- Определите механизмы безопасности для поддержки этих свойств (аутентификация, авторизация, аудит — три Au). Наличие механизмов этих трех Au считается золотым стандартом безопасности. Система не может быть безопасной, если в ней отсутствует один из них.
- Моделируйте угрозы. Это означает необходимость определения злонамеренного агента и возможных видов атак (например, это может быть сетевой трафик, локальные файлы или даже отображаемые данные и т. д.).
Разработка:
- Архитектура, учитывающая угрозы безопасности (ответ на ранее определенные модели угроз в архитектуре системы).
- Анализ/оценка архитектурных рисков (выявление потенциальных недостатков в архитектуре).
- Применение определенных выше принципов безопасности (предотвращение, смягчение, обнаружение, восстановление).
Реализация:
- Придерживайтесь лучших практик написания кода.
- Проводите обязательные ревью кода.
- Применяйте инструменты автоматизации для обеспечения самого высокого качества кода:
Тестирование:
- Тестирование на основе рисков.Эти тесты нацелены на самые критичные части системы, определенные с помощью моделирования угроз.
- Испытание на проникновение. Специалисты по безопасности играют роль злоумышленника, пытаясь преодолеть механизмы безопасности.
- Фаззинг. Намеренный ввод в систему случайных и некорректных данных часто может помочь обнаружить нежелательное поведение.
Распространенные изъяны проектирования и реализации
Придерживаясь безопасного процесса разработки, всегда помните об ошибках, которые часто допускают разработчики:
- предполагать доверительные отношения вместо того, чтобы явным образом выдавать их;
- использовать механизм аутентификации, который можно обойти;
- авторизовать без достаточного контекста;
- путать данные и управляющие команды.
Именно это является источником пресловутых внедрений SQL-кода, XSS-атак и выполнения удаленного кода.
- не производить валидацию данных;
- неверно использовать криптографию;
- неверно идентифицировать конфиденциальные данные;
- интегрировать внешние компоненты без учета угрозы с их стороны;
- жестко ограничить будущие изменения исходного кода и конфигурации.
OWASP и топ-10 уязвимостей
Open Web Application Security Project (OWASP) — это некоммерческая организация, ориентированная на повышение безопасности программного обеспечения. И вы можете найти отличное применение ее ресурсам. Эта организация предоставляет полезные рекомендации и «шпаргалки» для популярных платформ разработки, таких как .NET и Java.
OWASP в первую очередь известна своими списками «топ-десяток», описывающими наиболее распространенные уязвимости в разных доменах:
Крайне важно хорошо знать распространенные уязвимости своего домена. Предупрежден — значит, вооружен.
Выводы
Учитывайте проблемы безопасности в первую очередь и даже не думайте откладывать их на потом. Планируйте и выполняйте необходимые действия на каждом этапе разработки, чтобы обеспечить безопасность своих клиентов и сохранить свою репутацию.
Надеюсь, эта статья окажется для вас полезной, но имейте в виду, что это всего лишь очень обобщенный список. Чтобы стать компетентным специалистом, нужно много учиться и практиковаться. Вам обязательно надо вкладывать время и ресурсы для утверждения своей компетенции и, возможно, даже сертификации в конкретной, интересующей вас области.
[customscript]techrocks_custom_after_post_html[/customscript]
[customscript]techrocks_custom_script[/customscript]