Защита от уязвимости Dependency Confusion в PHP с помощью Composer

Original author: Nils Adermann
  • Translation


Недавно Алекс Бирсан опубликовал статью «Dependency Confusion: How I Hacked Into Apple, Microsoft and Dozens of Other Companies», в которой рассказал, как использовал диспетчеры пакетов уровня языков наподобие npm (Javascript), pip (Python) и gems (Ruby), чтобы заставить компании установить и запустить в своей инфраструктуре зловредный код.

Проблема сводится к тому, что компании ссылаются на внутренние пакеты по имени, например my-internal-package, а злоумышленник публикует в центральном реестре/репозитории пакетов языка (для PHP это packagist.org) пакет с таким же названием my-internal-package, имеющий более высокую версию. После этого компании устанавливали и выполняли эти зловредные пакеты вместо своих внутренних пакетов, потому что их диспетчер пакетов выбирал версию с более высоким номером из стандартного репозитория пакетов вместо внутреннего репозитория.

Рассказывая о решении этой проблемы для Composer и Packagist в Twitter, Джорди вкратце перечислил различные меры, используемые Composer и Packagist для защиты компаний от этой серьёзной проблемы:

  1. Названия пакетов Composer всегда содержат префикс поставщика, например, my-company/our-internal-pkg. Такое правило присваивания имён принудительно применяется утилитой командной строки и на packagist.org. Packagist.org сохраняет префиксы имени поставщика для мейнтейнера после публикации его первого пакета. Никто больше не может опубликовать другой пакет с префиксом вендора my-company/ без согласия мейнтейнера. Если у вашей компании есть хотя бы один публичный пакет на packagist.org с префиксом поставщика (подойдёт даже пустой префикс), например, my-company/dummy-pkg, то злоумышленники не смогут создавать пакеты, совпадающие с вашими внутренними названиями пакетов, в которых используется ваш префикс поставщика. Если вы запрашиваете my-company/my-internal-package внутри своей инфраструктуры, злоумышленники не смогут «похитить» это имя на packagist.org.
  2. Что касается Composer 2.0, то его пользовательские репозитории по умолчанию каноничны. Это означает, что если имя пакета найдено в репозитории пользовательского или приватного пакета, то всегда будут загружаться только эти версии. Если то же имя пакета существует в репозиториях с меньшим приоритетом или на packagist.org, то оно игнорируется. Даже если злоумышленник публикует пакет с тем же названием, что и ваш внутренний пакет, в более высокой версии, Composer не установит его.
  3. Private Packagist всегда обрабатывал сторонние зеркальные репозитории, в том числе и на packagist.org, как канонические, и никогда не загружал информацию пакетов с зеркал, если существует приватный пакет с тем же именем. То есть Private Packagist защищает пользователей на Composer 1.x так же, как это по умолчанию делает Composer 2.
  4. Private Packagist позволяет вручную подтверждать каждый новый зеркальный пакет из стороннего репозитория наподобие packagist.org до того, как его можно будет установить с помощью Composer. Это дополнительная функция, предоставляющая пользователям ещё больше контроля над используемым ими сторонним кодом.
  5. Composer всегда генерирует файл блокировки (lock file) со списком конкретных версий и URL скачивания установленных зависимостей. Мы настоятельно рекомендуем выполнять коммиты файла блокировки в систему контроля версий и использовать на этапах сборки только composer install, эта команда устанавливает только конкретные версии, перечисленные в файле блокировки. Можно встроить анализ изменений в файле блокировки в свой обычный рабочий процесс, чтобы гарантировать, что код не загружается из ненадёжных сторонних источников.
  6. При помощи Composer 2 можно исключать загрузку имён пакетов или паттернов для каждого репозитория. Так что можно быть уверенным, что даже написанные с опечаткой несуществующие пакеты без зарегистрированного префикса на packagist.org не смогут загружаться с packagist.org с помощью замены стандартной конфигурации в composer.json. Этот исключающий фильтр можно использовать и для дополнительных репозиториев сторонних пакетов.


    "repositories": {
        "private-repo": {
            "url": "https://my-repo.internal"
        }
        "packagist.org": {
            "url": "https://repo.packagist.org",
            "exclude": ["myprefix/*"]
        }
    }

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



На правах рекламы


Подыскиваете VDS для отладки проектов, сервер для разработки и размещения? Вы точно наш клиент :) Посуточная тарификация серверов, создавайте собственную конфигурацию в несколько кликов, антиDDoS и лицензии Windows уже включены в стоимость.

VDSina.ru
Серверы в Москве и Амстердаме

Comments 7

    +4

    Мало того что префикс поставщика защищает от самой возможности подмены пакета, так и еще позволяет сделать fork уже существующего пакета чтобы поддерживать его самостоятельно если оригинальный пакет заброшен или не принимает изменения которые нужны вам.


    Когда начал пользоваться npm по началу дико раздражало отсутствие этого префикса.

      –1
      Проблема сводится к тому, что компании ссылаются на внутренние пакеты по имени, например my-internal-package, а злоумышленник публикует в центральном реестре/репозитории пакетов языка (для PHP это packagist.org) пакет с таким же названием my-internal-package, имеющий более высокую версию. После этого компании устанавливали и выполняли эти зловредные пакеты вместо своих внутренних пакетов, потому что их диспетчер пакетов выбирал версию с более высоким номером из стандартного репозитория пакетов вместо внутреннего репозитория.

      Что?!!! Я понимаю какой-нибудь пет-проект на локалхосте с настройками композера (или его аналогов) по-умолчанию такое чисто теоретически может прокатить. Но для более серьёзных контор это вряд ли.
      Во-первых: ну хорошо, угадал он что в компании Pear Inc. используют префикс пакетов pear-ink/, а не pear/ и не pi/, а с остальной частью имени пакета он что будет делать, подбирать рандомом, или он сначала получил доступ к исходникам?
      Во-вторых: мы вот ни разу не apple, но у нас почему-то изначально lock файл комитится и проект разворачивается только через composer install, и не потому что мы параноики, а чтоб иметь протестированное окружение, а не то что там composer update автоматом наподключает.
      В-третьих, за пакетами мы ходим через кеширующий прокси, на котором политики: все что не разрешено — запрещено.
        +3
        One such company is the Canadian e-commerce giant Shopify, whose build system automatically > installed a Ruby gem named shopify-cloud only a few hours after I had uploaded it, and then tried > to run the code inside it. The Shopify team had a fix ready within a day, and awarded a $30,000 > bug bounty for finding the issue.

        Another $30,000 reward came from Apple, after the code in a Node package which I uploaded to > npm in August of 2020 was executed on multiple machines inside its network. The affected projects appeared to be related to Apple’s authentication system, externally known as Apple ID.
          0
          Я сам не идеален, но уже на многое насмотрелся.
          Если разработчики могут(это ключевое слово) они обязательно накосячат.
          Первый пример с головы, я у себя в компании заколебался всем объяснять что билдить под рутом опасно, но они копипастят не моё решение)
            +3
            Вы видимо не вникали в упомянутую статью про Dependency Confusion — схема как раз хорошо сработала для больших и серьезных компаний, для npm и rubygems. И там достаточно было всего лишь, что-бы кто-то невнимательный засветил названия внутренних пакетов (ничего угадывать не надо), и чтобы такой пакет не был еще опубликован в паблик-репозитории. Ну и конечно же, чтобы сам package-manager был подвержен этой уязвимости. Всё.
            То, что Composer приучил всех комитить лок-файлы, использовать префиксы и то, что он по умолчанию ставит пакеты из локального репозитория — это заслуга разработчиков Composer. Но не всем так повезло.
            0
            Буквально вчера, читал про Azure Key Vault
            docs.microsoft.com/en-us/learn/modules/manage-secrets-with-azure-key-vault/1-introduction
            И вот они приводят пример Синьйор Разработчика!!! (look no further than the story of Steve, the senior developer.):

            Steve had been in his job at a pet food delivery company for a few weeks. He was exploring the details of the company's web app — a .NET Core web app that used an Azure SQL database for storing order information and third-party APIs for credit card billing and mapping customer addresses — when he accidentally pasted the connection string for the orders database into a public forum.

            Days later, accounting noticed that the company was delivering a lot of pet food that nobody had paid for. Someone had used the connection string to access the database and created orders by updating the database directly.

            After realizing his mistake, Steve hurriedly changed the database password to lock out the attacker. After changing the password, the website started returning errors to users: the app server needed an updated configuration with the new password. Steve logged directly into the app server and changed the app configuration instead of redeploying, but the server was still showing failed requests.

            Steve had forgotten that multiple instances of the app ran on different servers, and he had only changed the configuration for one. A full redeployment was needed, causing another 30 minutes of downtime.

            Fortunately for Steve, the accounting department was able to correct the errors quickly, and only one day's worth of orders were impacted. He might not be so lucky in the future, though, and needs to find a way to improve the security and maintainability of the app.



            Я думал что случай надуманный, и это перебор… но наверное это самы настоящий реальный кейс рукалицо.жпг
              0
              Есть такое понятие, как SBOM. Говорят про него редко.
              Во многих корпорациях есть security policy с требованием использования только внутренних репозиториев. Но не во всех.

              Only users with full accounts can post comments. Log in, please.