Исследователь взломал системы Apple, Microsoft и десятков других компаний, атаковав цепочки зависимостей

Повезло, что это была не настоящая атака, а просто изучение проблем безопасности.

Исследователь Алекс Бирсан обнаружил простой способ взлома внутренних систем. Чтобы выполнить код на сервере, достаточно подменить частные пакеты с зависимостями одноимёнными пакетами из общедоступных репозиториев. Стандартные менеджеры пакетов NPM, PyPI, RubyGems фактически делали это сами. При этом администраторы не получали никаких уведомлений, а системы продолжали работать без сбоев.

Метод основан на том, что компании используют в приложениях зависимости из стандартных репозиториев, а также внутренние зависимости, которые хранятся в собственных репозиториях и не распространяются публично. Если знать имена пакетов с внутренними зависимостями и создать пакеты с такими же именами в публичных репозиториях, то можно выполнить код на серверах компании. Это связано с тем, что пакетные менеджеры вроде npm, pip и gem пытаются загрузить внутренние зависимости компаний в том числе из публичных репозиториев. Проблема не специфична для NPM, PyPI, RubyGems и проявляется в других системах, среди которых NuGet, Maven и Yarn.

Идея такой атаки появилась после того, как исследователь изучил файлы манифеста package.json из пакета npm, который использовался внутри системы PayPal. Бирсан обнаружил, что некоторых пакетов нет в общедоступном репозитории npm. Это были внутренние пакеты, созданные PayPal. После этого исследователь начал поиск имён внутренних пакетов в репозиториях GitHub или в CDN известных компаний. Собрав базу, он создал поддельные пакеты с такими же именами в публичных репозиториях, таких как npm, PyPI и RubyGems. Каждый пакет выходил под реальной учётной записью и содержал пояснение, что он предназначен для исследования безопасности.

Список зависимостей npm

С этого файла началось большое исследование безопасности / medium.com.@alex.birsan

Вскоре стало понятно, что если пакет с одним и тем же именем присутствует и в общедоступном, и в частном репозитории, то публичный пакет получает приоритет. Используя эту технику, Бирсан провёл успешные атаки на серверы Microsoft, Apple, PayPal, Shopify, Netflix, Tesla, Yelp и Uber. В PyPI на приоритет загрузки влиял номер версии — загружалась наиболее свежая версия пакета, вне зависимости от репозитория. В NPM и RubyGems приоритет зависел только от репозитория.

75 % всех зафиксированных запусков кода были связаны с загрузкой NPM-пакетов. Это объясняется тем, что имён внутренних модулей JavaScript было найдено намного больше, чем имён зависимостей на Python и Ruby. Внутренние gem-пакеты были обнаружены у 8 компаний, 4 из них удалось атаковать, создав дубликат пакета в RubyGems. Среди жертв оказалась Spotify, сборочный сервер которой установил поддельный пакет shopify-cloud спустя всего несколько часов после его публикации. Поддельный Node.js-пакет idms-pmrpc попал в сеть Apple, в том числе на сервер, связанный с Apple ID.

О своих выводах исследователь сообщал компаниям. Он подчеркивает, что каждая организация, которая была подвергнута атаке, предоставила разрешение на проверку своей безопасности либо в публичной программе вознаграждения, либо в частной форме. Компании уже выплатили ему вознаграждение — всего Бирсан получил 130 тысяч долларов.

Как защититься от атак на зависимости?

После изучения проблемы компания Microsoft опубликовала рекомендации по защите сборочных систем от атак на зависимости:

  • В PyPI рекомендуется использовать опцию «–index-url» вместо «–extra-index-url» для переопределения приоритета обработки зависимостей.
  • В NuGet в nuget.config в секции packageSources рекомендуется использовать запись <clear /> для удаления наследуемых конфигураций, а также явно добавлять внутренние репозитории через <add />.
  • В Maven рекомендуется настроить одно общее зеркало при помощи опций <mirrorOf>*</mirrorOf> и перенаправлять в него все запросы к репозиториям. Другой вариант —  переопределение репозиториев по умолчанию при помощи настройки <releases>.
  • В NPM и Yarn в пакетах рекомендуется определить scopeprefix для привязки репозитория к каждому пакету (возможна привязка только одного репозитория).

Источники: OpenNet
Medium
BleepingComputer