Оглавление
Open Source стал неотъемлемой частью современного мира. Сегодня уже нет необходимости объяснять, что это такое, – с этим явлением все давно свыклись и приняли его как данность. Однако возникает другой вопрос: как эффективно и зрело работать с Open Source?
Автор: Алексей Хорошилов, руководитель Центра исследований безопасности системного программного обеспечения, ведущий научный сотрудник ФГБУН “ИСП РАН”
Уровни зрелости заимствования
На начальном этапе, который многие из нас проходят еще в студенческие годы, подход к Open Source зачастую прост и беззаботен – «установил и забыл», но все вроде бы работает, и работает достаточно долго. Иногда, в лучшем случае, что-то обновляется вручную. Но рано или поздно приходит понимание, что этот подход ограничен, и хочется заглянуть чуть дальше.
Следующий этап наступает, когда компания осознает, что нельзя неконтролируемо заимствовать все подряд. В этот момент появляются каталоги и кэши пакетов, устанавливаются правила: только проверенные компоненты и исключительно из внутренних репозиториев. Продуктовый процесс начинает включать обязательные проверки компонентов, прежде чем они попадут в эти репозитории.
Затем приходит понимание важности регулярного мониторинга уязвимостей. Настраиваются процессы, позволяющие своевременно выявлять проблемы в используемых компонентах и оперативно обновлять их при необходимости.
На еще более зрелом уровне появляются процедуры проверки входящих пакетов и их обновлений. Для начала они могут быть относительно легковесными. Например, некоторые организации адаптируют методику, опубликованную ФСТЭК России в 2022 г. для проприетарного ПО, и успешно применяют ее к компонентам Open Source. В дальнейшем проверки могут расширяться до полноценных практик разработки безопасного программного обеспечения (РБПО), включая статический анализ, функциональное тестирование, фаззинг-тестирование и т.д.
Другими словами, работа с Open Source – это путь от стихийного подхода к зрелой практике, где каждая новая ступень помогает компаниям минимизировать риски и выстраивать более надежную и устойчивую инфраструктуру.
Шаги для повышения зрелости
Давайте обратим внимание на основные и, казалось бы, очевидные шаги, которые, тем не менее, могут быть организованы далеко не везде.
Во-первых, при получении кода стоит удостовериться в его подлинности: проверить цифровую подпись, если она есть, сравнить результаты загрузки из разных источников, например, с российского и нероссийского IP-адресов, чтобы убедиться, что код не изменен специально для российских пользователей. Затем – проверить его через антивирус и применить хотя бы базовые YARA-правила, чтобы выявить потенциальные угрозы базового уровня.
Следующий уровень – более сложный, включающий использование проверенных практик работы с программным обеспечением. Например, проведение статического анализа исходного кода, выполнение тестов на качество и безопасность для каждого компонента, который планируется использовать, а также фаззинг-тестирование для выявления уязвимостей. Это тяжелый и ресурсоемкий процесс, доступный лишь немногим организациям, располагающим соответствующими ресурсами и опытом.
Если взглянуть на текущую ситуацию, становится очевидным, что зрелость процессов в компаниях воспитывать нужно и важно. Особенно это заметно в тех сегментах, где программное обеспечение применяется для решения ответственных задач.
Где-то работа ведется более системно, и это дает положительные результаты. В качестве примера можно привести сентябрьское информационное письмо ФСТЭК России, обязывающее разработчиков составить перечень заимствованных компонентов и предоставить информацию о них. Этот простой, на первый взгляд, шаг позволяет многим компаниям впервые получить полное представление о том, что именно используется в их продуктах, и приступить к работе над улучшением процессов.
Однако, если мы говорим о полноценной реализации третьего уровня зрелости – с полным охватом статического анализа, фаззинга и прочих проверок, – становится ясно, что для большинства серьезных разработчиков это практически невыполнимая задача. Огромный объем заимствованного кода просто не позволяет проверить все досконально.
Более того, очевидно, что подавляющее большинство организаций сталкиваются с одними и теми же задачами: компоненты, используемые в разработке, пересекаются у разных участников отрасли на 80% или даже больше. Это поднимает вопрос о необходимости выработки единых решений и инструментов для оптимизации этих трудоемких процессов.
Центр исследований безопасности системного программного обеспечения
Три года назад началась работа над проектом, направленным на организацию совместных исследований заимствованных программных компонентов. В 2021 г. мы стартовали с ядра Linux – наиболее крупного и критически важного компонента с точки зрения его роли в обеспечении ключевых функций и высокой степени уязвимости на поверхности атаки. Постепенно проект расширялся, охватывая и другие компоненты, чтобы проводить их углубленное исследование с использованием лучших практик РБПО.
На примере ядра Linux можно наглядно посмотреть, как организована эта работа. Для начала мы создали зеркало всех репозиториев, связанных с ядром Linux, которые размещены на kernel.org. Для исследования безопасности и сопровождения были выделены две стабильные ветки ядра – 5.10 и 6.1. Выбор осуществлялся совместно с участниками проекта, учитывая актуальность версий и их практическое применение в продуктах участников.
Для исследования ядра у нас развернута специализированная инфраструктура – своего рода исследовательская ферма, которая позволяет выполнять полный цикл анализа от статического анализа и фаззинг-тестирования до других сложных проверок. Этот анализ выполняется регулярно, поскольку разработка ядра Linux не стоит на месте: обновления стабильных веток выходят практически еженедельно, а иногда и чаще.
При обнаружении проблем и подготовке собственных исправлений мы в первую очередь стараемся отправить их в апстрим, то есть в международное сообщество разработчиков ядра. Такой подход помогает минимизировать проблемы в будущем и снизить трудоемкость последующих синхронизаций.
Но несмотря на нацеленность на работу с апстримом, нам приходится вести и собственные ветки ядра. В них включаются патчи, которые задерживаются на пути попадания в интересующие нас стабильные ветки или которые разработчики стабильных веток ядра считают нужным принимать. Это, как правило, касается доработок, направленных на автоматизацию и повышение эффективности фаззинг-тестирования. В контексте стабильных веток такие изменения могут считаться избыточными, так как они добавляют новую функциональность. Однако с точки зрения обеспечения качественного исследования кода мы считаем их абсолютно необходимыми и включаем в наши ветки.
Если выявляются критические уязвимости, мы придерживаемся особого регламента: такие исправления не публикуются в открытом доступе сразу. Они сначала помещаются в приватную ветку, доступную только участникам проекта, и проходят период эмбарго. По истечении этого срока патчи передаются международному сообществу.
Схема работы Центра
При обработке результатов анализа ядра мы в первую очередь отрабатываем то, что появилось в результате последнего обновления. На нашем сайте [1] можно найти множество примеров таких проблем.
Один из типичных случаев – автоматическое бэкпортирование патча, когда соседние строки кода кажутся неизменными относительно апстрима, и патч применяется автоматически. Однако в стабильных ветках, таких как 5.10 или 6.1, он может работать некорректно. Такие ситуации встречаются регулярно. Например, на прошлой неделе ошибку удалось выявить фаззингом, а на позапрошлой – статическим анализом. В среднем подобные проблемы фиксируются раз в месяц-два.
Наш опыт показывает, что международное сообщество справляется с такими ошибками примерно в 80% случаев, обнаруживая их уже в следующем релизе или через релиз. Эти ошибки не выявляются автоматически при выпуске, но достаточно быстро исправляются. Тем не менее, около 20% проблем остаются незамеченными. Мы стараемся оперативно информировать сообщество о таких ситуациях, чтобы минимизировать расхождения. В своих ветках мы устраняем выявленные проблемы до релиза, внося необходимые исправления и отправляя их на повторное тестирование.
Этот подход позволяет эффективно обнаруживать ошибки, которые регулярно возникают в обновлениях из-за недочетов в бэкпортировании или других процессах, поскольку количество новых сработок, появляющихся при тестировании очередного обновления, оказывается, как правило, достаточно небольшим.
Однако что делать с огромным объемом работы, связанной с анализом всего компонента целиком? Например, ядро Linux содержит более 35 млн строк кода. Запуск статического анализа для такого объема порождает до 40 тыс. предупреждений. В 2021 г., глядя на такие цифры, многие из нас чувствовали себя ошеломленными.
Но благодаря совместным систематическим усилиям удалось организовать эффективный процесс обработки и этого объема предупреждений.
Мы сформировали регулярный процесс анализа с двухнедельными итерациями. На каждую итерацию для участников выделяется небольшой объем предупреждений, который можно реально обработать.
Эти результаты проверяются независимыми экспертами, что позволило кардинально улучшить качество проводимого анализа. Когда статический анализ проводится «для галочки», его результаты часто отправляются в архив и остаются без внимания. Однако понимание того, что твою работу будут проверять квалифицированные эксперты, создает совершенно иной уровень ответственности. Качество их проработки в таких условиях значительно возрастает.
Для подтвержденных предупреждений разрабатываются патчи, которые затем направляются в международное сообщество. Особенно важно, что в этой работе участвуют не только сотрудники Центра, но и инженеры из организаций-участников.
За прошедшее время отработано более 60% предупреждений статического анализа, исправлены десятки проблем, выявляемых фаззинг-тестированием.
Заключение
С течением времени все больше инженеров, выделенных организациями для участия в совместных исследованиях, обучались взаимодействию с международным сообществом и стали активно вносить вклад, создавая все больше патчей. Если у некоторых организаций уже имелись опытные мейнтейнеры ядра, и участие для них было привычным процессом, то для более чем десятка других организаций мы наблюдали значительный рост их специалистов. Один из важнейших результатов нашей деятельности – формирование квалифицированных кадров, способных эффективно работать на международном уровне.
Для систематизации этой работы был сформирован консорциум [2], в который вошли практически все российские организации, занимающиеся ядром Linux. В рамках консорциума разработаны программы исследований, определяющие объем и направления работ. Первая программа была утверждена координационным советом весной 2024 г., вторая сейчас находится на завершающем этапе. Организации, которые уже вышли на зрелый уровень работы, демонстрируют отличные результаты, успешно выполняя все обязательства.
Этот подход мы сейчас масштабируем на другие заимствованные компоненты с открытым исходным кодом. Основное внимание уделяется компонентам, которые критически важны для разработчиков средств защиты информации, подлежащих сертификации. В частности, в центре внимания – системы виртуализации, языки программирования и их интерпретаторы, такие как Python, .NET, Node.js, а также стандартные и специализированные библиотеки, часто оказывающиеся на поверхности атаки.
Принципы работы остаются неизменными: глубокий анализ, взаимодействие с сообществом, внесение исправлений в апстрим, совместная работа. На сегодняшний день благодаря этому подходу уже принято более ста пятидесяти патчей в различные исследуемые компоненты.
В перспективе мы видим, что только совместная работа над исследованием безопасности заимствованных компонентов, может позволить достичь третьего уровня зрелости, что не только повысит доверие к коду, используемому в ключевых системах, но и создаст условия для устойчивого развития технологий с учетом современных требований безопасности и качества.
https://portal.linuxtesting.ru/
https://portal.linuxtesting.ru/pub/docs/LVC_Consortium_Agreement.pdf
ITSec_articles