Kontrola zranitelných balíčků pomocí composer audit
Publikováno: 1.2.2023
Když se v nějaké vámi používané PHP knihovně objeví bezpečnostní chyba, tak máte několik možností jak se o ní dozvědět dříve, než bude pozdě. V jednom z předchozích článků jsem popisoval PHP Security Advisories Database a její použití pomocí Roave Security Advisories i několik dalších způsobů. Všechny zmíněné ale vyžadují mít nebo používat nějaký extra balíček nebo nástroj.
Text vyšel původně na autorově webu.
Kromě balíčku roave/security-advisories, který díky svému dlouhému seznamu zranitelných knihoven a jejich verzí nedovolí takový balíček nainstalovat a upozorní na něj, používám i GitHub Action s názvem The PHP Security Checker, což je vlastně jen githubí omáčkou obalený security check ze Symfony CLI. O všech těchto věcech jsem již psal ve svém dřívějším článku včetně ukázek.
Pokud ale nechcete nic dalšího a rádi byste využili něco, co nejspíš už používáte, tak mám pro vás dobrou zprávu. Od verze 2.4 (vyšla v létě 2022) se Composer té databáze dotazuje rovnou sám, po každém composer require
. Kontrolu lze také vyvolat ručně pomocí composer audit
. K dotazování používá vlastní API, viz třeba seznam zranitelných verzí balíčku guzzlehttp/guzzle.
Kontrola se provádí i po spuštění composer update
(v obou případech lze přeskočit pomocí --no-audit
), ale po composer install
standardně ne – důvodem možná je obvykle automatizované spouštění, kdy výsledek stejně nikdo nevidí a možná taky to, že častá instalace, např. při spouštění testů, by posílala zbytečně moc požadavků na ono zmíněné API. Nicméně pokud i přesto chcete, tak kontrolu po instalaci můžete vynutit pomocí parametru --audit
.
Po composer require
Pojďme se podívat na to, jak to vypadá. Dejme tomu, že bych teď chtěl nějakou tu zranitelnou verzi nainstalovat, konkrétně jsem si vybral Guzzle verze 7.4.4 – Composer to sice udělá, ale bude remcat a upozorní mě, všimněte si posledních dvou řádků:
$ composer require guzzlehttp/guzzle:7.4.4 ./composer.json has been created Running composer update guzzlehttp/guzzle Loading composer repositories with package information Updating dependencies Lock file operations: 8 installs, 0 updates, 0 removals - Locking guzzlehttp/guzzle (7.4.4) - Locking guzzlehttp/promises (1.5.2) - Locking guzzlehttp/psr7 (2.4.3) - Locking psr/http-client (1.0.1) - Locking psr/http-factory (1.0.1) - Locking psr/http-message (1.0.1) - Locking ralouphie/getallheaders (3.0.3) - Locking symfony/deprecation-contracts (v3.2.0) Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 8 installs, 0 updates, 0 removals - Installing symfony/deprecation-contracts (v3.2.0): Extracting archive - Installing psr/http-message (1.0.1): Extracting archive - Installing psr/http-client (1.0.1): Extracting archive - Installing ralouphie/getallheaders (3.0.3): Extracting archive - Installing psr/http-factory (1.0.1): Extracting archive - Installing guzzlehttp/psr7 (2.4.3): Extracting archive - Installing guzzlehttp/promises (1.5.2): Extracting archive - Installing guzzlehttp/guzzle (7.4.4): Extracting archive 2 package suggestions were added by new dependencies, use `composer suggest` to see details. Generating autoload files 4 packages you are using are looking for funding. Use the `composer fund` command to find out more! Found 2 security vulnerability advisories affecting 1 package. Run composer audit for a full list of advisories.
S barvičkami v terminálu je to sice o dost výraznější:
Formát lze sice změnit, viz níže, ale i tak by se to dalo jednoduše přehlídnout. Zvlášť třeba pokud byste spustili composer require
s parametrem --quiet
, „nic nevypisuj“.
composer audit
Proto je asi důležitější ten úplně poslední řádek, který říká, že bychom měli spustit composer audit
:
$ composer audit Found 2 security vulnerability advisories affecting 1 package: +-------------------+----------------------------------------------------------------------------------+ | Package | guzzlehttp/guzzle | | CVE | CVE-2022-31091 | | Title | Change in port should be considered a change in origin | | URL | https://github.com/guzzle/guzzle/security/advisories/GHSA-q559-8m2m-g699 | | Affected versions | >=7,<7.4.5|>=4,<6.5.8 | | Reported at | 2022-06-20T22:24:00+00:00 | +-------------------+----------------------------------------------------------------------------------+ +-------------------+----------------------------------------------------------------------------------+ | Package | guzzlehttp/guzzle | | CVE | CVE-2022-31090 | | Title | CURLOPT_HTTPAUTH option not cleared on change of origin | | URL | https://github.com/guzzle/guzzle/security/advisories/GHSA-25mq-v84q-4j7r | | Affected versions | >=7,<7.4.5|>=4,<6.5.8 | | Reported at | 2022-06-20T22:24:00+00:00 | +-------------------+----------------------------------------------------------------------------------+
To už je o něco lepší, že? Rovnou vidíme, který balíček má nějakou zranitelnost a jakou. Dokonce i návratová hodnota je nenulová, došlo k nějaké chybě, takže se to dá použít i v různých skriptech:
$ echo $? 1
Když se pokusím nainstalovat nejnovější verzi bez známých bezpečnostních problémů, tak to bude vypadat takto:
$ composer require guzzlehttp/guzzle [...] No security vulnerability advisories found Using version ^7.5 for guzzlehttp/guzzle [...]
Výstup z composer audit
pak bude vypadat následovně, včetně nulové návratové hodnoty, což znamená vše oukej:
$ composer audit No security vulnerability advisories found $ echo $? 0
Pro správnou funkčnost composer audit
musí být balíčky standardně nainstalovány. Pokud ale použijete parametr --locked
(composer audit --locked
), tak balíčky nainstalovány být nemusí a kontrola se provede jen na základě obsahu composer.lock
.
Pokud byste z nějakého důvodu nechtěli kontrolovat balíčky v sekci require-dev
, tak můžete použít --no-dev
. Osobně bych ale kontroloval vše.
Jako GitHub Action
Díky nenulové návratové hodnotě při nalezení známého bezpečnostního problému v nějakém používaném balíčku lze composer audit
spouštět jednoduše například i v GitHub Actions. A přesně tak to používám i já:
composer-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: composer audit
Tuhle kontrolu spouštím každé dvě hodiny, abych se o případném problému a nutnosti aktualizovat dozvěděl včas. Na nějaké důležitější aplikaci, než je můj web, bych to klidně spouštěl častěji, třeba každou hodinu.
Formát výstupu
Composer nabízí několik různých formátů vypisovaných informací o známých zranitelnostech:
table
: tabulka viz výše, standardně se použije procomposer audit
plain
: obyčejný textový výpis, bez tabulkyjson
: hádejtesummary
: jen krátká informace o tom, jestli se něco nalezlo, nebo ne; standardně procomposer require
,composer update
,composer install
Formát můžete změnit parametrem:
--audit-format=FORMAT
procomposer require
,composer update
,composer install
--format=FORMAT
procomposer audit
Dodám snad už jen to, že Composer můžete aktualizovat pomocí composer self-update
.