Programování

Třináct pravidel pro vývoj zabezpečených aplikací Java

Zabezpečení je jedním z nejsložitějších, nejširších a nejdůležitějších aspektů vývoje softwaru. Zabezpečení softwaru je také často přehlíženo nebo zjednodušeno pouze na několik drobných úprav na konci vývojového cyklu. Výsledky vidíme v ročním seznamu hlavních narušení bezpečnosti dat, které v roce 2019 dosáhlo více než 3 miliard exponovaných záznamů. Pokud se to může stát hlavnímu, může se to stát vám.

Dobrou zprávou je, že Java je dlouholetá vývojová platforma s mnoha integrovanými bezpečnostními funkcemi. Balíček zabezpečení Java prošel intenzivním testováním bitev a je často aktualizován kvůli novým chybám zabezpečení. Novější rozhraní Java EE Security API, vydané v září 2017, řeší chyby zabezpečení v architekturách cloudu a mikroslužeb. Ekosystém Java také zahrnuje širokou škálu nástrojů pro profilování a hlášení bezpečnostních problémů.

Ale i při solidní vývojové platformě je důležité zůstat ostražití. Vývoj aplikací je složitý úkol a chyby zabezpečení se mohou skrývat v pozadí. Měli byste myslet na zabezpečení v každé fázi vývoje aplikace, od jazykových funkcí na úrovni třídy až po autorizaci koncových bodů API.

Následující základní pravidla nabízejí dobrý základ pro vytváření bezpečnějších aplikací Java.

Pravidlo zabezpečení Java č. 1: Napište čistý a silný kód Java

Zranitelnosti se rádi skrývají ve složitosti, takže udržujte svůj kód co nejjednodušší, aniž byste obětovali funkčnost. Používání osvědčených návrhových principů, jako je DRY (neopakujte se), vám pomůže napsat kód, který lze snáze zkontrolovat kvůli problémům.

Ve svém kódu vždy zveřejněte co nejméně informací. Skrytí podrobností implementace podporuje kód, který je udržovatelný i zabezpečený. Tyto tři tipy půjdou dlouhou cestu k psaní zabezpečeného kódu Java:

  • Využijte dobře modifikátory přístupu Java. Znalost toho, jak deklarovat různé úrovně přístupu pro třídy, metody a jejich atributy, bude dlouhou cestou k ochraně vašeho kódu. Všechno, co lze nastavit jako soukromé, by mělo být soukromé.
  • Vyvarujte se reflexe a sebepozorování. Existují případy, kdy si takové pokročilé techniky zaslouží, ale většinou byste se jim měli vyhnout. Použití reflexe eliminuje silné psaní, což může do vašeho kódu vnést slabá místa a nestabilitu. Porovnání názvů tříd jako řetězců je náchylné k chybám a může snadno vést ke kolizi oboru názvů.
  • Vždy definujte nejmenší možné povrchy API a rozhraní. Oddělte součásti a zajistěte jejich interakci na nejmenší možné ploše. I když je některá oblast vaší aplikace napadena porušením, ostatní budou v bezpečí.

Pravidlo zabezpečení Java č. 2: Vyhněte se serializaci

Toto je další tip na kódování, ale je dost důležitý na to, aby byl vlastním pravidlem. Serializace trvá vzdálený vstup a transformuje jej na plně vybavený objekt. Zbavuje se konstruktorů a modifikátorů přístupu a umožňuje, aby se proud neznámých dat stal spuštěným kódem v JVM. Výsledkem je, že serializace Java je hluboce a ze své podstaty nejistá.

Konec serializace Java

Pokud jste to ještě neslyšeli, Oracle má dlouhodobé plány na odstranění serializace z Javy. Mark Reinhold, hlavní architekt skupiny platforem Java ve společnosti Oracle, uvedl, že věří, že třetina nebo více všech zranitelností Java zahrnuje serializaci.

Pokud je to možné, vyhněte se serializaci / deserializaci v kódu Java. Místo toho zvažte použití formátu serializace, jako je JSON nebo YAML. Nikdy, nikdy nevystavujte nechráněný koncový bod sítě, který přijímá a jedná podle proudu serializace. To není nic jiného než vítaná podložka pro chaos.

Pravidlo zabezpečení Java č. 3: Nikdy nevystavujte nezašifrovaná pověření nebo PII

Je těžké tomu uvěřit, ale tato chyba, které se lze vyhnout, rok co rok způsobuje bolest.

Když uživatel zadá heslo do prohlížeče, odešle se na server jako prostý text. To by mělo být naposledy, co uzře denní světlo. Vy musí zašifrujte heslo pomocí jednosměrného cypheru, než jej uložíte do databáze, a poté to proveďte znovu při každém porovnání s touto hodnotou.

Pravidla pro hesla se vztahují na všechny osobní údaje (PII): kreditní karty, čísla sociálního zabezpečení atd. Se všemi osobními údaji svěřenými vaší žádosti je třeba zacházet s nejvyšší úrovní péče.

Nešifrované přihlašovací údaje nebo PII v databázi jsou zející bezpečnostní dírou, která čeká na objevení útočníka. Stejně tak nikdy nezapisujte nezpracovaná pověření do protokolu ani jinak nepřenášejte do souboru nebo do sítě. Místo toho pro vaše hesla vytvořte solený hash. Nezapomeňte provést průzkum a použít doporučený hashovací algoritmus.

Přejít na pravidlo č. 4: pro šifrování vždy používejte knihovnu; neházejte vlastní.

Pravidlo zabezpečení Java č. 4: Používejte známé a testované knihovny

Pospěšte si na tuto otázku a odpověď na téma vytvoření vlastního bezpečnostního algoritmu. Lekce tl; dr je: používat známé a spolehlivé knihovny a rámce, kdykoli je to možné. To platí napříč spektrem, od hašování hesel po autorizaci REST API.

Naštěstí máte Java a její ekosystém zde. Pro zabezpečení aplikací je Spring Security de facto standardem. Nabízí širokou škálu možností a flexibilitu, aby se vešly do jakékoli architektury aplikace, a zahrnuje celou řadu bezpečnostních přístupů.

Vaším prvním instinktem v řešení bezpečnosti by mělo být provedení výzkumu. Prozkoumejte osvědčené postupy a poté prozkoumejte, jaké knihovny tyto postupy pro vás implementují. Například pokud se díváte na používání webových tokenů JSON ke správě ověřování a autorizace, podívejte se na knihovnu Java, která zapouzdřuje JWT, a pak se naučte, jak to integrovat do Spring Security.

Dokonce i při použití spolehlivého nástroje je poměrně snadné provést autorizaci a autentizaci. Pohybujte se pomalu a dvakrát zkontrolujte vše, co děláte.

Pravidlo zabezpečení Java č. 5: Buďte paranoidní ohledně externího vstupu

Ať už pochází od uživatele, který píše do formuláře, datového úložiště nebo vzdáleného API, nikdy nevěřte externímu vstupu.

SQL injection a cross-site scripting (XSS) jsou jen nejčastěji známé útoky, které mohou být výsledkem nesprávného zacházení s externím vstupem. Méně známým příkladem - jedním z mnoha - je „miliardový smíchový útok“, při kterém může expanze entit XML způsobit útok Denial of Service.

Kdykoli obdržíte vstup, mělo by to být zkontrolováno a dezinfikováno. To platí zejména pro cokoli, co by mohlo být předloženo ke zpracování jinému nástroji nebo systému. Například pokud by něco mohlo skončit jako argument pro příkazový řádek OS: pozor!

Speciální a dobře známou instancí je SQL injection, které je popsáno v dalším pravidle.

Pravidlo zabezpečení Java č. 6: Ke zpracování parametrů SQL vždy používejte připravené příkazy

Kdykoli vytvoříte příkaz SQL, riskujete interpolaci fragmentu spustitelného kódu.

S tímto vědomím je dobrým zvykem vždy k vytvoření SQL použijte třídu java.sql.PreparedStatement. Podobná zařízení existují pro obchody NoSQL, jako je MongoDB. Pokud používáte vrstvu ORM, použije se implementace Připravené prohlášeníje pro vás pod kapotou.

Pravidlo zabezpečení Java č. 7: Neodhalujte implementaci pomocí chybových zpráv

Chybové zprávy ve výrobě mohou být pro útočníky úrodným zdrojem informací. Stohovací stopy, zejména, mohou odhalit informace o technologii, kterou používáte, a o tom, jak ji používáte. Vyhněte se odhalení trasování zásobníku koncovým uživatelům.

Do této kategorie spadají také upozornění na neúspěšné přihlášení. Obecně se přijímá chybová zpráva jako „Přihlášení se nezdařilo“ versus „Nenašel jsem daného uživatele“ nebo „Nesprávné heslo“. Nabídněte potenciálně hanebným uživatelům co nejmenší pomoc.

V ideálním případě by chybové zprávy neměly odhalit podkladový technologický zásobník pro vaši aplikaci. Tyto informace udržujte co nejprůhlednější.

Pravidlo zabezpečení Java č. 8: Udržujte bezpečnostní vydání aktuální

Od roku 2019 zavedla společnost Oracle nové licenční schéma a plán vydání pro Javu. Bohužel pro vývojáře nová kadence vydání věci neusnadňuje. Jste však zodpovědní za častou kontrolu aktualizací zabezpečení a jejich použití ve vašem JRE a JDK.

Pravidelnou kontrolou bezpečnostních upozornění na domovské stránce Oracle se ujistěte, že víte, jaké kritické opravy jsou k dispozici. Společnost Oracle každé čtvrtletí dodává automatickou aktualizaci opravy pro aktuální vydání Java LTS (dlouhodobá podpora). Potíž je v tom, že tato oprava je k dispozici, pouze pokud platíte za licenci podpory Java.

Pokud vaše organizace za takovou licenci platí, postupujte podle trasy automatických aktualizací. Pokud ne, pravděpodobně používáte OpenJDK a opravu si budete muset udělat sami. V tomto případě můžete použít binární opravu nebo jednoduše nahradit stávající instalaci OpenJDK nejnovější verzí. Alternativně můžete použít komerčně podporovaný OpenJDK, jako je Azul's Zulu Enterprise.

Potřebujete každou bezpečnostní opravu?

Pokud pozorně sledujete výstrahy zabezpečení, možná zjistíte, že danou sadu aktualizací nepotřebujete. Například vydání z ledna 2020 objeví se být kritickou aktualizací Java; pozorné čtení však ukazuje, že aktualizace opravuje pouze díry v zabezpečení appletu Java a neovlivňuje servery Java.

Pravidlo zabezpečení Java č. 9: Hledejte chyby zabezpečení závislostí

Existuje mnoho nástrojů k automatickému prohledání zranitelnosti vaší základny kódu a závislostí. Musíte je pouze použít.

OWASP, projekt zabezpečení otevřené webové aplikace, je organizace zaměřená na zlepšování zabezpečení kódu. Seznam důvěryhodných, vysoce kvalitních nástrojů pro automatické skenování kódu OWASP obsahuje několik nástrojů orientovaných na Javu.

Pravidelně kontrolujte základ kódu, ale sledujte také závislosti třetích stran. Útočníci cílí na otevřené i uzavřené knihovny. Sledujte aktualizace svých závislostí a aktualizujte svůj systém, jakmile budou vydány nové opravy zabezpečení.

Pravidlo zabezpečení Java č. 10: Monitorujte a zaznamenávejte aktivitu uživatelů

Dokonce i jednoduchý útok hrubou silou může být úspěšný, pokud aplikaci aktivně nesledujete. Pomocí nástrojů pro monitorování a protokolování sledujte stav aplikace.

Pokud byste se chtěli přesvědčit, proč je monitorování důležité, stačí sedět a sledovat pakety TCP na portu naslouchání aplikací. Uvidíte všechny druhy aktivit, nad rámec jednoduchých uživatelských interakcí. Některé z těchto aktivit budou roboti a zlí činitelé, kteří hledají zranitelná místa.

Měli byste protokolovat a monitorovat neúspěšné pokusy o přihlášení a nasadit protiopatření, abyste zabránili beztrestnému útoku vzdálených klientů.

Monitorování vás může upozornit na nevysvětlitelné špičky a protokolování vám pomůže odhalit, co se po útoku pokazilo. Ekosystém Java zahrnuje nepřeberné množství komerčních a otevřených řešení pro protokolování a monitorování.

Pravidlo zabezpečení Java č. 11: Dávejte pozor na útoky DoS (Denial of Service)

Kdykoli zpracováváte potenciálně drahé zdroje nebo provádíte potenciálně nákladné operace, měli byste se chránit před využitím uprchlých zdrojů.

Společnost Oracle udržuje seznam potenciálních vektorů pro tento typ problému ve svých dokumentech Secure Coding Guidelines for Java SE document, under the "Denial Of Service".

V zásadě byste měli kdykoli provést nákladnou operaci, například rozbalení komprimovaného souboru, sledovat explozi využití prostředků. Nedůvěřujte manifestům souborů. Důvěřujte pouze skutečné spotřebě na disku nebo v paměti, sledujte to a chraňte se před nadměrnými útoky na server.

Podobně je v některých procesech důležité sledovat neočekávané navždy smyčky. Pokud je smyčka podezřelá, přidejte stráž, která zajistí, že smyčka postupuje, a zkratujte ji, pokud se zdá, že byla zombie.

Pravidlo zabezpečení Java č. 12: Zvažte použití správce zabezpečení Java

Java má správce zabezpečení, kterým lze omezit prostředky, ke kterým má spuštěný proces přístup. Může izolovat program z hlediska přístupu na disk, paměť, síť a JVM. Zúžení těchto požadavků na vaši aplikaci sníží stopu možného poškození útokem. Taková izolace může být také nepohodlná, a proto Bezpečnostní manažer není ve výchozím nastavení povoleno.

Budete se muset sami rozhodnout, zda budete pracovat Bezpečnostní manažerSilný názor stojí za další vrstvu ochrany vašich aplikací. V dokumentech Oracle se dozvíte více o syntaxi a schopnostech správce zabezpečení Java.

Pravidlo zabezpečení Java č. 13: Zvažte použití služby externího cloudového ověřování

Některé aplikace musí jednoduše vlastnit svá uživatelská data; pro zbytek by poskytovatel cloudových služeb mohl mít smysl.

Prohlédněte si okolí a najdete řadu poskytovatelů cloudového ověřování. Výhodou takové služby je, že za zabezpečení citlivých uživatelských dat je odpovědný poskytovatel, nikoli vy. Na druhou stranu přidání služby ověřování zvyšuje složitost vaší podnikové architektury. Některá řešení, jako je FireBase Authentication, zahrnují SDK pro integraci napříč zásobníkem.

Závěr

Představil jsem 13 pravidel pro vývoj bezpečnějších aplikací Java. Tato pravidla jsou osvědčená, ale největší pravidlo ze všech je toto: buďte podezřelí. K vývoji softwaru vždy přistupujte opatrně a s ohledem na bezpečnost. Hledejte zranitelná místa ve svém kódu, využijte výhod bezpečnostních API a balíčků Java a pomocí nástrojů třetích stran sledujte a zaznamenávejte bezpečnostní kód svého kódu.

Tady jsou tři dobré zdroje na vysoké úrovni, které vám umožní držet krok s neustále se měnícím prostředím zabezpečení Java:

  • OWASP Top 10
  • CWE Top 25
  • Pokyny společnosti Oracle k zabezpečenému kódu

Tento příběh „Třináct pravidel pro vývoj zabezpečených aplikací Java“ původně publikoval JavaWorld.