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.
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 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.
Spouštění kontroly pomocí GitHub Actions
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 auditplain: 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=FORMATprocomposer require,composer update,composer install--format=FORMATprocomposer audit
Dodám snad už jen to, že Composer můžete aktualizovat pomocí composer self-update.
Aktualizace článku
27. ledna 2023 Parametr --locked zajistí, že composer audit se bude dělat na základě obsahu composer.lock
Vyvíjím webové aplikace, zajímá mě jejich bezpečnost. Nebojím se o tom mluvit veřejně, hledám hranice tak, že je posouvám. Chci naučit webové vývojáře stavět bezpečnější a výkonnější weby a aplikace.
Veřejná školení
Zvu vás na následující školení, která pořádám a vedu:
