Перейти к содержанию

Возможна атака на цепочку поставок через атаку MavenGate

Критичность: ВЫСОКИЙ
Модуль: Анализ компонент с открытым исходным кодом

Описание

Приложение использует библиотеку с открытым исходным кодом, которая может участвовать в атаке на цепочку поставок (под названием MavenGate).

В чем заключается суть атаки MavenGate, почему она стала возможной и почему она так опасна? Обратимся к первоисточнику и посмотрим, из чего состоит типичный Gradle-проект и как работает механизм управления зависимостями.

  1. Каждый Gradle-проект содержит список репозиториев, откуда необходимо выгружать зависимости. Они могут быть разными, но наиболее популярные проекты — MavenCentral, JCentral и JitPack с Google (для Android). Репозитории делятся на приватные, где публиковать компоненты могут только их правообладатели (например, Google-репозиторий), и публичные — где каждый может размещать что угодно (среди них как раз MavenCentral, JCenter и т. д.).

    Указание перечня репозиториев в файле сборки gradle

  2. Список зависимостей имеет формат groupId:artifactId:version, например, com.google.code.gson:gson:2.10.1.

    Описание зависимостей в файле сборки

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

Но как опубликовать свою библиотеку, что для этого нужно? Как правило, процесс очень похож во многих репозиториях. Чтобы выложить библиотеку, необходимо владеть доменом, который относится к ее group.id. То есть, чтобы выложить пакет с именем ru.stingraymobile, необходимо быть владельцем домена stingraymobile.ru. И чтобы это подтвердить, на момент регистрации необходимо добавить TXT-запись с определенным значением в ваш домен.

Злоумышленник определяет библиотеки, для которых доступна регистрация домена, покупает его и после этого загружает библиотеку с полезной нагрузкой во все репозитории, где ее нет. Именно на этой особенности и построена рассматриваемая атака: библиотеки, домены которых доступны для свободной регистрации, уязвимы и могут быть подменены злоумышленниками в процессе сборки приложения.

Пример эксплуатации

Чтобы понять, как можно реализовать эту атаку, разберем пример. Возьмем библиотеку org.xmlmatchers. По данным Maven, она используется в 62-х проектах и опубликована только на MavenCentral. Домен xmlmatchers.org свободен для регистрации и стоит $9.99 в год.

Вот какой может быть последовательность действий злоумышленника:

  1. Покупает домен xmlmatchers.org за 10 долларов.

  2. Регистрируется во всех публичных репозиториях, где первичная валидация происходит по домену.

  3. Загружает в эти репозитории библиотеку, которая содержит полезную нагрузку в дополнение к основному функционалу с той же версией, что и в MavenCentral. Дополнительно загружает на одну минорную версию выше.

В результате:

  • Все пользователи, применяющие библиотеку напрямую (и у кого первым установлен не MavenCentral-репозиторий), получат версию злоумышленника.

  • Все пользователи, которые подключают ее напрямую, получат сообщение от IDE, что библиотеку можно обновить.

  • Все проекты, использующие эту зависимость (и у кого первым установлен не MavenCentral-репозиторий), получат версию злоумышленника.

Повторяем это действие для всех найденных библиотек со свободными доменами.

Есть и второй вектор атаки — для его реализации нужно просканировать все репозитории, кроме Central, на библиотеки со свободными доменами. По полученному списку проверить, каких из них нет в основном Maven-репозитории.

Далее путь очень похожий:

  1. Покупается домен.

  2. Дорабатывается и заливается библиотека в MavenCentral.

  3. Все проекты и пользователи, у которых первым в списке стоит Central-репозиторий, получают библиотеку с полезной нагрузкой

Весьма несложный путь для атак на достаточно большое количество проектов.

Рекомендации

Есть несколько вариантов, как защититься от этого типа атаки (лучше делать все это вместе):

Первый способ: собрать SBOM-файл для своих Java- и Android-приложений и посмотреть, что именно они используют — все прямые и транзитивные зависимости. Провести анализ и выявить библиотеки, домены которых свободны для продажи или куплены за прошедшие несколько недель, и исключить эти зависимости из проекта, если это возможно. Дополнительно обязательно проверить, нет ли в ваших файлах сборки пакетов с версией, которая ссылается на самую свежую без прямого указания. В случае обнаружения подобных зависимостей необходимо явно зафиксировать версию библиотеки.

Второй способ: проверить контрольную сумму пакета (целостность) или хэш от загруженной библиотеки. И проверять загружаемые библиотеки при сборке на соответствие этим хэш-суммам.

Третий способ: проверка подписи загружаемых библиотек, но, как показывает практика, мало кто из разработчиков публикует открытые ключи. Тем не менее это один из самых эффективных способов защиты от данной атаки.

Стоит сказать и о разработке в закрытом контуре. Компании, которые используют внутренние репозитории в режиме зеркалирования (библиотека, перед тем как попасть к разработчику или в систему сборки, сначала загружается во внутренний репозиторий и при последующих обращениях к ней отдаёт сохраненный ранее файл), менее подвержены этому типу атаки, чем те, кто загружает библиотеки из публичных репозиториев напрямую. Тем не менее, рекомендуется проверить все библиотеки, которые содержатся в проксирующих репозиториях, на предмет возможности захвата домена, посмотреть, какие источники для загрузки Java-библиотек разрешены и какие версии были загружены с начала года. И более детально изучить их, выяснить, а те ли они, за кого себя выдают, или кто-то уже успел загрузить «правильную» версию.

Ссылки

  1. https://blog.oversecured.com/Introducing-MavenGate-a-supply-chain-attack-method-for-Java-and-Android-applications/

  2. https://habr.com/ru/companies/swordfish_security/articles/790544/

  3. https://docs.gradle.org/current/userguide/dependency_verification.html#sec:checksum-verification

  4. https://docs.gradle.org/current/userguide/dependency_verification.html#sec:signature-verification

К началу