Na konferenci Black Hat Europe 2017 byla odhalena celá řada bezpečnostních chyb v populárních programovacích jazycích. Interprety těchto jazyků obsahují vážné bezpečnostní chyby, které pak vystavují výsledný kód různým typům útoků. Autorem nové analýzy je Fernando Arnaboldi, který pracuje jako bezpečnostní konzultant ve společnosti IOActive.
Pro testování vytvořil vlastní automatizovaný software, pomocí kterého se snažil objevit bezpečnostní chyby v pěti nejpopulárnějších interpretovaných jazycích současnosti: JavaScript, Perl, PHP, Python a Ruby.
Při testování byla použita metoda zvaná fuzzing, kdy se na vstup programu dostávají nevalidní, neočekávaná nebo jednoduše náhodná data. To dovoluje navozovat běžně netestované stavy, které sice neodpovídají běžnému použití, ale mohou být zneužity k cílenému útoku.
Fuzzing umožňuje odhalit pády, špatnou práci s paměti nebo třeba neočekávané chování programu. Nejedná se o novinku, tyto techniky se používají už velmi dlouho, rádi je mají například lidé z Google. Nedávno byla takto objevena celá řada chyb v linuxových ovladačích USB.
Diferenciální fuzzer XDiFF
Arnaboldi si pro tento účel napsal vlastní diferenciální fuzzer XDiFF (eXtended Differential Fuzzing Framework), který poté uvolnil na GitHubu. Je napsán tak, aby generoval práva pro pětici zmíněných jazyků. Pro každý z nich zvolil sadu základních funkcí, do kterých pak vkládal různé typy vstupů (payloads).
Aby bylo možné odhalit zranitelnosti v kódu, je potřeba zvolit správné vstupy. Autor tedy zvolil méně než tři desítky primitivních hodnot (čísla, znaky a podobně), které doplnil o známý payload. Ten byl zvolen tak, aby dovoloval odhalit, že se testovaná aplikace pokusila přistoupit k externím zdrojům – tedy že se stalo něco neočekávaného.
Diferenciální fuzzery jsou méně časté než ty klasické. Jejich funkce je rozšířená o to, že obvykle testují jeden kód na více různých implementacích stejného jazyka a hledají odlišné chování. Porovnávají se například výstupy a chybové hlášky s očekávaným stavem.
Konkrétně se hlídá, zda program vyzrazuje obsah lokálních souborů, spouští cizí kód nebo volá neobvyklé funkce operačního systému. Tato náročná práce přinesla své ovoce, každý z testovaných programovacích jazyků má nějaký problém:
- Python obsahuje nedokumentované metody a lokální proměnné, které mohou být zneužity pro spuštění příkazu v operačním systému.
- Perl obsahuje funkce typu typemap, které dovolují provést kód stejně jako
eval()
. - Node.js zobrazuje za určitých okolností chybové hlášky odhalující obsah souborů na disku.
- JRuby načítá a spouští vzdálený kód ve funkci, která k tomu není určena.
- PHP dovoluje zneužít jména konstant ke vzdálenému spuštění kódu.
Chyby ohrožují i dobře napsané programy
Arnaboldi varuje, že případný útočník může tyto chyby zneužít i v programu, který je jinak napsán velmi bezpečně. Protože se programy vyskytují v interpretru, může je programátor jen velmi těžko ovlivnit. Nevědomky tak při psaní svého kódu použije nebezpečné funkce, které jsou zneužitelné, i když je zbytek programu napsán přesně podle pravidel bezpečného programování.
Podle objevitele bezpečnostních problémů jde pravděpodobně o chyby v kódu nebo o snahu zjednodušit si vývoj. Chyby jednoznačně ohrožují výsledné programy, ale měly by být opraveny v interpretrech. Taková oprava pak vyřeší plošně problémy ve všech programech využívajících daný jazyk.