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.
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
.
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 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.
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.
Spouštění kontroly pomocí GitHub Actions
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 pro composer 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ě pro composer require
, composer update
, composer install
Formát můžete změnit parametrem:
--audit-format=FORMAT
pro composer require
, composer update
, composer install
--format=FORMAT
pro composer audit
Dodám snad už jen to, že Composer můžete aktualizovat pomocí composer self-update
.