Aktualizace článku
- 19.9. Dependabot umí kontrolovat a aktualizovat i samotné actions
- 25.1. Přidán odkaz na článek o
composer audit
- 17.1. Na GitHubu si lze nechat posílat i jen security alerty k používaným
balíčkům
- 16.1. Skenování závislostí na GitLabu a další alternativy k Dependabotu
- 20.11. GitHub přesunul nastavení upozornění na nové Releases do
kategorie Custom
Chybu,
kterou objevil Cyku Hong z Taiwanu, může útočník za určitých okolností
využít ke vzdálenému spuštění kódu na některých webech pomocí
speciálně sestaveného URL. Takové chyby spadají do kategorie Remote Code
Execution (RCE) a zažijete s nimi spousty legrace, nebo možná taky ne, to
podle toho, na které straně barikády stojíte.
David Grudl, tvůrce Nette, s chybou
zatočil správně: opravené verze balíčků vzhledem k závažnosti té
chyby vydal nejdříve „potichu“,
přičemž opravil i již
dávno nepodporované vykopávky typu Nette 2.0, poslal e-mail
podporovatelům, měsíc a něco počkal a teprve poté informaci uveřejnil na
blogu,
na diskuzním
fóru a v seznamu Common
Vulnerabilities and Exposures, ve kterém dostala číslo CVE-2020-15227.
(A když si něčím nebyl jistý, tak se mě zeptal 🤓)
Ve velkém a bez Composeru
Týden po zveřejnění se začaly objevovat nejen nástroje na otestování
i demonstraci zranitelnosti („Proof-of-Concept“, PoC), ale i vývojáři,
kteří chybu do té doby z různých důvodů zatím nezaregistrovali. Když
jsem to viděl, tak mě napadlo, že by řešení problému mohl pomoci
jednoduchý skript, který na serveru najde zranitelné soubory a příp. je
rovnou opraví náhradou jednoho řádku kódu za jiný.
Cílem byly převážně různé webhostingové firmy, které by mohly
vytipovat své zákazníky a přímo je informovat, nebo jim to rovnou opravit.
Napsal
jsem 2 prográmky v shellu (fungují v Bashi v Linuxu i FreeBSD), David
to později reimplementoval i v PHP.
Lukáš V. mi dokonce za ty skripty jen tak, sám od sebe, poslal nějaké to
kilčo, dík!
Tohle samo o sobě už by vám mohlo dát pár nápadů jak postupovat
poté, co vám někdo ve vašem frameworku, balíčku nebo knihovně najde
nějakou docela závažnou bezpečnostní chybu. Neméně důležité je ale
informaci o chybě a nutnosti aktualizovat dostat také k uživatelům vašeho
výtvoru. A jak se o tom mohou dozvědět co nejrychleji?
Podporujte a sledujte vývojáře
Pokud používáte nějaké knihovny nebo frameworky jako např. Nette nebo
cokoliv jiného, tak máte několik možností, jak se dozvědět, že fakt
musíte aktualizovat a tohle je asi ta nejdůležitější.
Podporujte vývojáře
nástrojů, které používáte. Vy budete mít dobrý pocit a ti
vývojáři, kromě jiného, budou na vás mít nějaký kontakt a mohou vám
napsat, že byste měli aktualizovat. Win-win situace. Když jsme
začali chybou v Nette, tak osobně Nette podporuji, v seznamu přispěvovatelů
mě nejspíš nepřehlédnete. Najdete tam i Scotta Helmeho, protože Nette mj.
používáme i na Report URI, na kterém
s ním pracuji. David Grudl podporovatelům poslal info o tom, že by měli
aktualizovat už 25. srpna, pár hodin po vydání opravených verzí verze, a
o měsíc a něco dříve, než informace o chybě zveřejnil.
Sledujte twittery a blogy vývojářů a diskuzní fóra (viz příspěvek na
blogu
Nette a na diskuzním
fóru). Pokud navíc vývojáři používají GitHub, tak ten vám může
poslat notifikaci klidně i jen při vydání nové verze nebo při objevení
bezpečnostního problému:
GitHub Dependabot
Pokud vyvíjíte na GitHubu a spravujete závislosti pomocí Composeru, tak
můžete využít Dependabota – robota,
který hlídá a automaticky aktualizuje všechny vaše závislosti. Dependabot
zvládá nejen PHP, ale i jiné
jazyky a správce balíčků. Nastavíte ho ve vašem repozitáři v menu
Settings > Security & analysis:
Prozkoumejte i sekci Security > Dependabot alerts, ve
které najdete všechna otevřená i vyřešená upozornění, která
Dependabot vytvořil:
Jsou tam i odkazy na automaticky vytvořené pull requesty, viz příklad. Tenhle opuštěný
projekt naštěstí nikde neběží, balíček
nette/application zde tedy nemusím aktualizovat, pull
request chci nechat v tomto stavu, abyste viděli, jak to případně bude
vypadat u vás.
Dependabot také umí kontrolovat nové verze samotných actions,
viz moje
konfigurace, automaticky vytvořený pull request pro
update jedné takové akce a dokumentace.
Kdybyste někdy potřebovali získat číslo CVE i pro nějaký váš
výtvor a informaci o chybě tak dostat „do oběhu“, tak se vám bude hodit
sekce Security Advisories. V seznamu zveřejněných
upozornění balíčku nette/application najdete i ono CVE-2020-15227.
Podobný záznam
je i v databázi všech GitHubových
upozornění.
GitLab také nabízí skenování
závislostí, ale pouze v nejdražší placené verzi. Alternativami
k Dependabotu jsou např. Snyk nebo Renovate.
Roave Security Advisories
Dalším nástrojem, který vám může pomoci odhalit neaktualizované PHP
knihovny s bezpečnostními chybami je balíček Roave Security
Advisories. Pojďme si ho ukázat v praxi, opět na mém starém a nepoužívaném projektu.
Nejdříve nainstalujeme závislosti uvedené v souboru
composer.lock
, přičemž vhodnější by bylo použít
composer update
, ale tím bychom nainstalovali již opravenou verzi
a to v tomto případě nechceme:
$ composer install
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
[...]
- Installing nette/application (v2.3.7): Downloading (100%)
[...]
Verze 2.3.7 obsahuje bezpečnostní chybu (a to v řadě 2.3 až do verze
2.3.13 včetně), takže instalace balíčku Roave Security
Advisories pomocí
composer require --dev roave/security-advisories:dev-latest
selže s tím, že jakože konflikt, protože
nette/application máme ve verzi 2.3.7:
$ composer require --dev roave/security-advisories:dev-latest
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.
Problem 1
- roave/security-advisories dev-latest conflicts with nette/application[v2.3.7].
- roave/security-advisories dev-latest conflicts with nette/application[v2.3.7].
- roave/security-advisories dev-latest conflicts with nette/application[v2.3.7].
- Installation request for roave/security-advisories dev-latest -> satisfiable by roave/security-advisories[dev-latest].
- Installation request for nette/application (locked at v2.3.7, required as ~2.3.1) -> satisfiable by nette/application[v2.3.7].
Installation failed, reverting ./composer.json to its original content.
Museli bychom nejdříve aktualizovat nette/application na
2.3.14 nebo novější a pak půjde nainstalovat i
roave/security-advisories:dev-latest
. Od této chvíle nepůjde
pomocí composer require
nebo composer update
nainstalovat žádný balíček se známou bezpečnostní chybou.
PHP Security Advisories Database
Roave Security Advisories nemá žádný kód, veškeré jeho
know-how spočívá v sekci conflict
v souboru composer.json
,
ve které jsou uvedené verze PHP balíčků s nějakou známou bezpečnostní
chybou. Ty se tam dostávají z PHP Security
Advisories Database (viz Contributing),
která jde používat několika
dalšími způsoby. Jde používat dokonce i jako GitHub
Action (viz můj
příklad), takže se kontrola bude provádět například při každém
pushi (a v mém příkladu i jednou za hodinu).
Od Composeru 2.4 lze využít
i příkaz composer audit
.
Bylo by skvělé, kdyby tuto databázi uměly pro upozorňování svých
zákazníků nějak využít i klasické sdílené hostingy.
disable_functions
Bránit se proti chybám, jako je právě vzdálené spuštění kódu, asi
nejde jinak než včasnou aktualizací. Jasně, můžete si někde na firewallu
zablokovat nějakou konkrétní URL adresu, ale to je spíš reaktivní
opatření. Můžete ale aspoň zásadně snížit dopad útoku aneb je blbý,
když někdo ve vaší aplikaci spustí nějaký PHP kód, ale je ještě mnohem
blbější, když pomocí PHP spustí nějaký prográmek z příkazové
řádky. Důrazně bych tedy doporučoval zakázat v PHP volání funkcí,
které takové prográmky mohou spouštět. Jsou to tyto:
exec
–
spustí externí program
passthru
–
spustí externí program a zobrazí výstup včetně binárních dat
proc_open
–
spustí program a vrátí ukazatele na vstup a výstup
shell_exec
–
spustí program pomocí shellu a vrátí výstup jako řetězec
system
–
spustí externí program a zobrazí výstup
pcntl_exec
–
spustí program v prostoru aktuálního procesu
popen
–
vrátí ukazatel na spuštěný proces
Zakázat je můžete jen v php.ini
(a to dokonce jen pro určitý server nebo cestu)
pomocí direktivy disable_functions
nebo v konfiguraci FPM poolu
pomocí php_admin_value[disable_functions]
, viz příklad.
Pro kontrolu, jestli náhodou tyhle funkce nepotřebujete volat ve vašem
kódu, použijte analyzátor PHP kódu PHPStan a má pravidla pro
hledání volání nepovolených funkcí a metod, stačí ve vaší konfiguraci
inklůdnout přibalený soubor disallowed-execution-calls.neon
.
Nezapomeňte také sledovat můj
Twitter, o závažných problémech se tam určitě dozvíte také. A rád
vás přivítám i na mém školení
webové bezpečnosti
(nejbližší termín: termín zatím nevypsán).
A ještě jedna věc: pokud jste doposud Nette neaktualizovali, tak už asi
můžete počítat s tím, že do vašeho webu nebo aplikace někdo nakladl
nějaké ty shelly nebo zadní vrátka a měli byste spustit proces obnovy,
vyčištění a případně i pátrání po uniklých datech. A pokud už
máte aktualizováno, tak se můžete pobavit třeba nad Easter eggy na
mém webu.