Stack Overflow je dnes asi nejdůležitějším zdrojem informací pro vývojáře. Dozví se tam novinky, tipy i odpovědi na mnoho otázek od těch nejtriviálnějších až po velmi složité. Součástí mnoha odpovědí jsou také připravené kusy kódu, které vypadají velmi lákavě a proto je stačí prostě použít. Stiskneme „ctrl-Cizí“ a pak „ctrl-Vlastní“ a máme hotovo.
Zrada ovšem spočívá v tom, že kód sice funguje, ale velmi často má zásadní bezpečnostní nedostatky. To je dáno jednak tím, že autor odpovědi je prostě „někdo z lidu“, ale zároveň často nezná celý kontext a reaguje jen na dotaz pokrývající malou část celého problému. Pokud je kód dobře napsaný a funguje, mají pak další stovky a tisíce programátorů tendenci jej kopírovat do svých děl.
Vzniká tím velmi nebezpečná situace, kdy se chybně napsaný kód velmi rychle rozšíří do stovek projektů. Stačí taková fóra sledovat a když se na nich objeví děravý kód jako odpověď na populární problém, hned je jasné, kudy brzy povede cesta do mnohých aplikací. Někteří testeři (a nejen ti) to tak skutečně dělají.
At a pentest talk, the pentester says: I read @StackOverflow to understand devs. Vulns from the verified answers will be in the apps soon.
— Michal Špaček (@spazef0rze) November 10, 2016
Použít takto připravený kód v produkčním prostředí chce zkušenosti a odborné znalosti, jinak je to velmi riskantní procedura. Vědci ze známého Fraunhofer Institute se zaměřili na platformu Android a objevili celou řadu takto napsaných děravých aplikací, které používají miliony uživatelů. Problém se ale netýká zdaleka jen Stack Overflow a Androidu.
Patnáct procent aplikací
Ve své zprávě Stack Overflow Considered Harmful? [PDF] vědci uvádějí, že proskenovali Stack Overflow a hledali v něm ukázky kódu týkajících se bezpečnosti. Těch bylo celkem nalezeno 4019. Ty poté ohodnotili z hlediska dopadu na bezpečnost aplikace. Následně analyzovali aplikace pro Android a tyto kódy v nich hledali. Výsledek je překvapivý: z 1,3 milionu zkoumaných aplikací jich 15,4 % obsahuje kód převzatý ze Stack Overflow. Drtivá většina (97,9 %) pak obsahuje alespoň jeden děravý příklad (data ke stažení).
Do výzkumu byly zařazeny jen „kódy týkající se bezpečnosti“, tedy ty, které se dotýkají jednoho z následujících témat:
- Cryptography: Java Cryptography Architecture (JCA), Java Cryptography Extension (JCE)
- Secure network communications: Java Secure Socket Extension (JSSE), Java Generic Security Service (JGSS), Simple Authentication and Security Layer (SASL)
- Public key infrastructure: X.509 and Certificate Revocation Lists (CRL) in java.security.cert, Java certification path API, PKCS#11, OCSP
- Authentication and access control: Java Authentication and Authorization Service (JAAS)
Navíc byly zahrnuty i takové ukázky, které se týkají oblíbených bezpečnostních knihoven, populární balík Apache TLS/SSL a také knihovny keyczar a jasypt, které usnadňují vývojářům přístup k bezpečnostním funkcím.
Kód byl poté roztříděn na bezpečný a nebezpečný. Bezpečné jsou ty varianty, které využívají aktuální šifrovací algoritmy a rozumnou délku klíče, případně některé parametry závisí na vývojářově dalším vstupu, ale nedovolují snadnou kompromitaci aplikace. Nebezpečné jsou pak ty, které obsahují zjevnou slabinu, typicky týkající se klíčů nebo zastaralých algoritmů.
Nebezpečné chování
Nejvíce děr bylo nalezeno v souvislosti se zpracováním TLS. Už výrazně menší skupinu pak tvoří kód týkající se symetrické kryptografie (typicky AES v nebezpečném ECB režimu) často také přímo obsahující vestavěné klíče. Dešifrovat pak data z takto vytvořené aplikace je velmi snadné:
byte[] rawSecretKey = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; String iv = "00000000"; byte[] iv = new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF };
Poměrně málo chyb se pak týkalo asymetrické kryptografie, hašů a podpisu nebo třeba bezpečného generování náhodných čísel. Následující kód nahrazuje seed pro generátor vlastním řetězcem:
byte[] keyStart = "this is a key".getBytes(); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); sr.setSeed(keyStart);
Velká část aplikací je tak zranitelná man-in-the-middle útokem, používá špatně pinning veřejného klíče nebo špatně zachází s kryptografickými primitivy. Dále bylo objeveno špatné zacházení s úložištěm a obcházení systému oprávnění kvůli komunikaci mezi jednotlivými komponentami aplikace. To může ve výsledku vést k úniku uživatelských dat, sledování uživatele nebo třeba zneužití geolokace.
Byl objeven například kód vypínající ověřování hostname při sestavování TLS spojení. Akceptováno je pak cokoliv:
@Override public boolean verify(String hostname, SSLSession session) { return true; }
Zpráva uvádí, že mnoho chyb lze přičítat nedostatečným znalostem vývojářů. Byly objeveny například aplikace, při jejichž vývoji autor vypnul TLS a v ostré verzi jej zapomněl zpět zapnout. Řada vývojářů je také zmatená z množství TLS parametrů, které pak zvolí náhodně nebo špatně. V mnoha tématech je také jako řešení problémů s šifrováním doporučováno jeho úplné vypnutí.
Řešením je hodnocení bezpečnosti
Součástí Stack Overflow je ale obrovské množství dobře napsaných příkladů, které vývojářům opravdu pomáhají. Není ovšem vyřešeno, jak oddělit ty dobré od těch špatných. Tradiční hodnotící systém tu zjevně selhává, jak bylo naznačeno výše. Autoři studie doporučují přidat ještě jeden druh hodnocení, které se zaměří přímo na otázku bezpečnosti.
Přidání dalšího bodování by ale jen zkomplikovalo práci s fórem a další vrstva by znepřehlednila hodnocení jako celek. Autoři dokumentu proto navrhují automatické testování bezpečnosti, které by mohlo zajistit například rozšíření do prohlížeče. To by mohlo hlídat ukázky kódů na stránce a zároveň kusy kopírované přes schránku. Takové rozšíření je už v tuto chvíli ve vývoji a mělo by být dostupné pro Firefox a Chrome.
Nekopírujte bezhlavě z webu
Viditelnost jednotlivých témat na Stack Overflow je ovlivňována hlasováním uživatelů. Vědci předpokládali, že nebezpečné kusy kódu budou mít vyšší skóre, protože vyžadují více zkoumání. Taková varianta se ale nepotvrdila a správně implementované příklady dosáhly vyššího hodnocení. Zajímavý je ale jiný postřeh: pokud je kód v otázce viditelně označen jako nebezpečný, má tendenci sbírat vyšší počet bodů. Na hodnocení ale může mít dopad celá řada dalších faktorů.
Byla ovšem nalezena přímá souvislost mezi bodovým hodnocením a zařazením problematických ukázek kódu do aplikací. Čím vyšší skóre nebo počet zobrazení, tím větší zastoupení kódu v aplikacích. Výslovné varování má ale překvapivě opět opačný efekt: jasně označené ukázky jsou kopírovány mnohem častěji.
Zajímavé také je, že drtivá většina zkopírovaných děravých ukázek pochází ze samotného dotazu. Jen zlomek je jich pak z odpovědi. To dokládá skutečně neuvěřitelně riskantní práci některých vývojářů, kteří jsou ochotni bez rozmyslu použít kód jiného člověka řešícího problém na fóru. Stack Overflow je dobrým místem pro efektivní řešení koncepčních témat, ale hůř dopadá, když dojde na konkrétní implementace.
Neplatí to jen pro Android a Stack Overflow: nekopírujte bez rozmyslu kód, který jste našli v náhodném fóru někde na internetu. On dost možná funguje, protože má třeba vysoké hodnocení dalších uživatelů. Nic to ale nevypovídá o jeho kvalitě a dopadu na bezpečnost vaší aplikace.