Как composer.lock защищает ваш проект от вредоносных зависимостей - PullRequest
2 голосов
/ 30 сентября 2019

В моем проекте я проверяю файл composer.lock на github . Предположим, мне требуется исправная зависимость в composer.json, например:

"require": {
    "foo/bar": "v3.0"
  },

После того, как я вызову composer install , создается файл composer.lock.

"packages": [
        {
            "name": "foo/bar",
            "version": "v3.0",
            "source": {
                "type": "git",
                "url": "https://github.com/foo/bar.git",
                "reference": "bbafb0edb791b23220563d113d00371ea42aedaa"
            },
            "type": "project",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Mr.Foo",
                    "email": "mr.foo@bar.de"
                }
            ],
            "time": "2019-09-30T12:13:55+00:00"
        }

Предположим, что злоумышленник, владеющий репозиторием foo / bar, удалит тег v3.0. Злоумышленник назвал бы другой коммит v3.0. Может ли кто-нибудь подтвердить, что composer install всегда будет проверять зависимости при установке composer.lock? Если я запускаю composer install без composer.lock file composer создаст новый файл .lock с новой ссылкой (идентификатор фиксации). Если я запускаю composer, установить с composer.lock файл composer будет придерживаться идентификатора фиксации («reference»: «bbafb0edb791b23220563d113d00371ea42aedaa», старый v3.0). Composer не будет загружать вредоносную фальшивку v3.0. Версия 3.0 указывает на новый идентификатор коммита на github.

Может ли кто-нибудь подтвердить, что тег ссылки composer.lock имеет «более высокий приоритет», чем тег version ? Композитор полностью защищает мой проект от подобных атак?

1 Ответ

3 голосов
/ 01 октября 2019

TL; DR;

Определенно, ответ на ваш вопрос:

Да, композитор защитит вас

Либо он установит пакеты на основе хеша фиксации, указанного в вашем composer.lock, если он существует в хранилище, просто игнорируя несоответствие между фиксацией и версией, либо произойдет сбой сдовольно прямо выраженная причина: «история была переписана?»


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

Итак, вот что я сделал:

  1. Есть "очевидное"«Сценарий, в котором злоумышленник действительно переписывает историю и удаляет коммит, тег которого соответствует вашему composer.json ограничению
  2. Во второй раз, есть также случай, когда злоумышленник сохранит коммит, помеченный какваш констraint, но добавит новый коммит и пометит новый коммит тегом, соответствующим вашему ограничению

Первый сценарий:

Я установил базовый пакет для какой-то конкретной версии(не последний, просто для ограничения версии):

$ composer require psr/log:1.0.0

Что заставило меня закончить с этим довольно простым composer.json

{
    "require": {
        "psr/log": "1.0.0"
    }
}

И это composer.lock

{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
        "This file is @generated automatically"
    ],
    "content-hash": "2865f724e23cffb23b3afd3a968e0359",
    "packages": [
        {
            "name": "psr/log",
            "version": "1.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/php-fig/log.git",
                "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
                "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
                "shasum": ""
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "Psr\\Log\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "PHP-FIG",
                    "homepage": "http://www.php-fig.org/"
                }
            ],
            "description": "Common interface for logging libraries",
            "keywords": [
                "log",
                "psr",
                "psr-3"
            ],
            "time": "2012-12-21T11:40:51+00:00"
        }
    ],
    "packages-dev": [],
    "aliases": [],
    "minimum-stability": "stable",
    "stability-flags": [],
    "prefer-stable": false,
    "prefer-lowest": false,
    "platform": [],
    "platform-dev": []
}

Затем, чтобы проверить это, я просто изменил хеш коммита fe0936ee26643249e916849d48e3a51d5f5e278b везде, где я бы нашел его в composer.lock одним символом: fe0936ee26643249e916849d48e3a51d5f5e278c (последний b стал c);заканчивая этим composer.lock:

{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
        "This file is @generated automatically"
    ],
    "content-hash": "2865f724e23cffb23b3afd3a968e0359",
    "packages": [
        {
            "name": "psr/log",
            "version": "1.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/php-fig/log.git",
                "reference": "fe0936ee26643249e916849d48e3a51d5f5e278c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278c",
                "reference": "fe0936ee26643249e916849d48e3a51d5f5e278c",
                "shasum": ""
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "Psr\\Log\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "PHP-FIG",
                    "homepage": "http://www.php-fig.org/"
                }
            ],
            "description": "Common interface for logging libraries",
            "keywords": [
                "log",
                "psr",
                "psr-3"
            ],
            "time": "2012-12-21T11:40:51+00:00"
        }
    ],
    "packages-dev": [],
    "aliases": [],
    "minimum-stability": "stable",
    "stability-flags": [],
    "prefer-stable": false,
    "prefer-lowest": false,
    "platform": [],
    "platform-dev": []
}

Обратите внимание, что: если вы попробуете это в своем браузере, поскольку композитор позже сделает это за вас, вы получите страницу 404:https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278c

Я удалил свою папку vendor, ради этого:

$ rm -Rf vendor

Затем перезапустите установку зависимостей, завершив ее выводом:

$ composer install
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 1 install, 0 updates, 0 removals
  - Installing psr/log (1.0.0): Downloading (0%)    Failed to download psr/log from dist: The "https://codeload.github.com/php-fig/log/legacy.zip/fe0936ee26643249e916849d48e3a51d5f5e278c" file could not be downloaded (HTTP/1.1 404 Not Found)
    Now trying to download from source
  - Installing psr/log (1.0.0): Cloning fe0936ee26 from cache
    fe0936ee26643249e916849d48e3a51d5f5e278c is gone (history was rewritten?)


  [RuntimeException]                                                                                                                  
  Failed to execute git checkout 'fe0936ee26643249e916849d48e3a51d5f5e278c' -- && git reset --hard 'fe0936ee26643249e916849d48e3a51d  
  5f5e278c' --                                                                                                                        

  fatal: reference is not a tree: fe0936ee26643249e916849d48e3a51d5f5e278c                                                            


install [--prefer-source] [--prefer-dist] [--dry-run] [--dev] [--no-dev] [--no-custom-installers] [--no-autoloader] [--no-scripts] [--no-progress] [--no-suggest] [-v|vv|vvv|--verbose] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--apcu-autoloader] [--ignore-platform-reqs] [--] [<packages>]...

Если бы у вас была только одна строка для чтения из этого вывода, это было бы:

fe0936ee26643249e916849d48e3a51d5f5e278c больше нет (история была переписана?)

Второй сценарий:

На этот раз я немного покопался в репозитории php-fig / log , чтобы найти начальный коммит репозитория: https://github.com/php-fig/log/commit/a7ab552fdb2efb80aeca09da3bbd9335fc945ff0

И, втаким же образом я отредактировал свой composer.lock, но на этот раз имитировал тот факт, что начальный коммит репо помечен 1.0.0, когда он явно не .

Это дало мне это composer.lock

{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
        "This file is @generated automatically"
    ],
    "content-hash": "2865f724e23cffb23b3afd3a968e0359",
    "packages": [
        {
            "name": "psr/log",
            "version": "1.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/php-fig/log.git",
                "reference": "a7ab552fdb2efb80aeca09da3bbd9335fc945ff0"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/php-fig/log/zipball/a7ab552fdb2efb80aeca09da3bbd9335fc945ff0",
                "reference": "a7ab552fdb2efb80aeca09da3bbd9335fc945ff0",
                "shasum": ""
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "Psr\\Log\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "PHP-FIG",
                    "homepage": "http://www.php-fig.org/"
                }
            ],
            "description": "Common interface for logging libraries",
            "keywords": [
                "log",
                "psr",
                "psr-3"
            ],
            "time": "2012-12-21T11:40:51+00:00"
        }
    ],
    "packages-dev": [],
    "aliases": [],
    "minimum-stability": "stable",
    "stability-flags": [],
    "prefer-stable": false,
    "prefer-lowest": false,
    "platform": [],
    "platform-dev": []
}

Обратите внимание, что: , попробовав на этот раз, загрузит zip, содержащийсостояние хранилища в том виде, в каком оно было при первоначальной фиксации: https://api.github.com/repos/php-fig/log/zipball/a7ab552fdb2efb80aeca09da3bbd9335fc945ff0

Повторил указанное выше удаление папки vendor

$ rm -Rf vendor

Очистить кэш компоновщика, также, на этот раз, потому что, уведомление о спойлере , установка завершится успешно:

$ composer clearcache && rm -Rf vendor
Clearing cache (cache-vcs-dir): /tmp/cache/vcs
Clearing cache (cache-repo-dir): /tmp/cache/repo
Clearing cache (cache-files-dir): /tmp/cache/files
Clearing cache (cache-dir): /tmp/cache
All caches cleared.

Затем повторно запустите установку зависимостей, завершив ее выводом:

$ composer install
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 1 install, 0 updates, 0 removals
  - Installing psr/log (1.0.0): Downloading (100%)         
Generating autoload files

Мне было любопытно, что установка идет слишком хорошо, и я более детально запустил процесс, чтобы узнать, что на самом деле делал композитор:

$ rm -Rf vendor/ && composer clearcache && composer install -vvv
Cache directory does not exist (cache-vcs-dir): 
Clearing cache (cache-repo-dir): /tmp/cache/repo
Clearing cache (cache-files-dir): /tmp/cache/files
Clearing cache (cache-dir): /tmp/cache
All caches cleared.
Reading ./composer.json
Loading config file ./composer.json
Checked CA file /etc/ssl/certs/ca-certificates.crt: valid
Executing command (/app): git branch --no-color --no-abbrev -v
Executing command (/app): git describe --exact-match --tags
Executing command (/app): git log --pretty="%H" -n1 HEAD
Executing command (/app): hg branch
Executing command (/app): fossil branch list
Executing command (/app): fossil tag list
Executing command (/app): svn info --xml
Failed to initialize global composer: Composer could not find the config file: /tmp/composer.json
To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section
Running 1.8.6 (2019-06-11 15:03:05) with PHP 7.3.8 on Linux / 4.9.184-linuxkit
Reading ./composer.lock
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Reading ./composer.lock
Resolving dependencies through SAT
Looking at all rules.

Dependency resolution completed in 0.000 seconds
Analyzed 43 packages to resolve dependencies
Analyzed 43 rules to resolve dependencies
Package operations: 1 install, 0 updates, 0 removals
Installs: psr/log:1.0.0
  - Installing psr/log (1.0.0): Downloading https://api.github.com/repos/php-fig/log/zipball/a7ab552fdb2efb80aeca09da3bbd9335fc945ff0
Downloading (connecting...)
Following redirect (2) https://codeload.github.com/php-fig/log/legacy.zip/a7ab552fdb2efb80aeca09da3bbd9335fc945ff0
Downloading https://codeload.github.com/php-fig/log/legacy.zip/a7ab552fdb2efb80aeca09da3bbd9335fc945ff0
Downloading (100%)Writing /tmp/cache/files/psr/log/6e79f232da13c50e0fd07e74eb2d58c350e71a60.zip into cache from /app/vendor/psr/log/4ff496e542e24af2efd56eaf051e132b

 Extracting archiveExecuting command (CWD): unzip -qq  '/app/vendor/psr/log/4ff496e542e24af2efd56eaf051e132b' -d '/app/vendor/composer/9c2feb29'
    REASON: Required by the root package: Install command rule (install psr/log 1.0.0)

Generating autoload files

Где вы можете увидеть, как установить библиотеку по хешу коммитаa7ab552fdb2efb80aeca09da3bbd9335fc945ff0, доверяя инструкциям composer.lock.

- Установка psr / log (1.0.0): загрузка https://api.github.com/repos/php-fig/log/zipball/a7ab552fdb2efb80aeca09da3bbd9335fc945ff0

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

...