О разработке безопасных программ...

Когда я пришёл в Microsoft, команда, ответственная за ядро Dynamics AX (тогда ещё Axapta), куда я собственно и попал, как раз работала над повышением безопасности ядра. Сразу после старта мне «повезло» окунуться в этот процесс с головой. Как выяснилось, этот процесс совсем непрост, как могло показаться со стороны. Оказалось, что он отнимает массу времени, сил и вообще может надолго отбить желание писать надёжные программы. Я так думаю, что если бы мне пришлось участвовать в дискуссии про то «как Microsoft выпускает дырявые программы» в тот период, я бы не удержался в рамках приличия. :-)

Сегодня я хотел немного рассказать о методиках разработки безопасных приложений, которые мне довелось испробовать на себе.

1. Моделирование опасностей (threat modeling) – это процесс анализа приложения (или какой-либо его части, вплоть до отдельных функций) на наличие уязвимостей. Сам процесс хорошо описан и формализован вот в этой книге. Моделирование требует значительных затрат времени разработчиков. Оно легко может увеличить время проектирования вдвое. Но результат стоит того.

Анализ начинается с составления диаграммы потоков данных (data flow diagram, DFD). Такая диаграмма хорошо описывает каким образом данные попадают в приложение, как и кем они обрабатываются и где хранятся. Тем самым выявляются все возможные точки атаки – ведь фактически, все возможные способы взлома (за исключением физического проникновения) завязаны на данные: либо поведение приложения зависит от поступающих данных, либо данные интересны само по себе.

На втором этапе, к списку точек атаки добавляются списки всех сценариев использования приложения, списки уровней привилегий пользователей, списки защищаемых ценностей (assets).

На третьем этапе для каждой точки атаки придумываются возможные сценарии взлома, которые затем классифицируются (по STRIDE) и оцениваются по шкале опасности (DREAD).

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

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

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

Основная сложность, связанная с использованием статических анализаторов заключается в том, что они генерируют довольно много шума (ложных сообщений о проблемах в коде). Программисты, будучи по натуре ленивыми, используют этот аргумент, чтобы так или иначе не заниматься исправлениями найденных ошибок. В Microsoft эта проблема решается безусловным внесением обнаруженных ошибок в bug tracking систему. Тем самым у программиста не остается выбора между исправлением кода и попытками избежать этого. Правка кода (или добавление метки о ложном срабатывании) занимает гораздо меньше времени, чем попытки «отмазаться».

  1. Автоматическое тестирование кода, попадающего в систему контроля версий. В разных группах это делается по разному. Но общая идея остается одинаковой. Любое изменение исходного кода в репозитории, так или иначе будет пропущено через набор тестов. Изменения не будут пропущены в основную ветку, пока все обнаруженные ошибки не будут исправлены.

  2. Обязательный просмотр кода (code review) перед внесением изменений в репозиторий. Удивительно, что может сделать ещё одна пара глаз, просматривающая написанный тобой код. Внимательный просмотр кода не столько способствует нахождению программных ошибок, сколько заставляет автора кода убедиться, что все сделанные изменения закончены на 100% и не нуждаются в дальнейшей доделке. Пока что мой лучший результат – 50% изменений, которые не потребовали хотя бы косметических правок после просмотра кода. Иными словами, без code review около половины изменений нуждались в повторной правке. Результаты моих коллег аналогичны.

  3. Ежедневная автоматическая сборка приложения и прогон всех тестов. Здесь все более менее понятно.

Вот, так сказать, краткий обзор. :-) А как это делается у вас?

comments powered by Disqus