Blokování obsahu 2.0

Není to tak dávno, co jsem psal, že používám ad-block. A že se za to nestydím. Nebyl to tedy úplně přesný titulek, neb nepoužívám ad-block, ale prostě block, a že se tím blokují i reklamy je jen takový vedlejší účinek. Primární cíl je blokování toho, co se mi nelíbí. Tedy JavaScripty, kterým nedůvěřuji. JavaScripty a requesty, které se snaží o mne něco zjistit a něco udělat na mém počítači.

Bohužel častým kanálem takových věcí jsou reklamní sítě. Přeci jen to je lákavé – stačí do reklamní sítě dostat nepěknou věc a mám jistotu, že se dostane přes velkou množinu špatně zabezpečených webů ke spoustě uživatelům. Dalšími kanály mohou být nově udělátka pro notifikace o cookie nařízené Evropskou Unií. Další už je velice málo pravděpodobné, ale co se asi stane, když se někomu povede hacknout like tlačítko či FB komentáře? I kdyby jen na chviličku. Ale i když pravděpodobnost je malá, stále tyhle prvky mne sledují, což se mi nelíbí.

Proto používám uBlock. Nikoliv ad-block, už rozhodně ne populární Adblock Plus, který sice skrývá (pouze!) reklamy, ale nově má v plánu některé zobrazovat či nahrazovat svými. Názor si udělejte sami.

Jenže stále jsem měl menší problém. Sice mne uBlock chrání před spoustou nebezpečného balastu na internetu, ale kdo mne chrání před uBlockem? Jak si mohu být jist, že samotný uBlock publikuje kód, který je dostupný na GitHubu, bez modifikace a ověřený komunitou? A co když se někomu povede převzít účet a nahrát zákeřnou verzi? Přeci jen má přístup ke všemu, co si prohlížím…

Proto jsem si kód forkl a udělal si review. Snažil jsem se dostat moji ověřenou kopii privátně do store, abych měl synchronizované přes všechny prohlížeče, a případně mohl nabídnout i lidem, kteří mi věří. Ale Google mi to bohužel nedovolil. Takže mám pouze ubalenou verzi, kterou si přes developer mode ručně nahrávám.

Nyní jsem zase o něco klidnější. Nenainstaluje se mi žádná úprava, dokud se na ni sám nepodívám a neschválím. A taky vím, že v pluginu škodlivý kód velice pravděpodobně momentálně není. :-)

Používám ad-block

A nestydím se za to.

Ano, vím kde pracuji a co mne tedy živí. Nepoužívám ad-block primárně kvůli reklamě, ale především z technických důvodů. Čtu si pravidelně o bezpečnosti, prošla mi rukama také skvělá kniha Bulletproof SSL and TLS a mám zalepené kamerky. Možná jsem paranoidní. Nebo možná jen vím, jak to běžně v praxi chodí. A to tak, že bezpečnost řeší málokdo. Pokud ji už řeší, ne vždy ji řeší správně a důkladně. Ještě větší problém je, že ji občas nelze ani řešit důkladně, neb můžete narazit na JS plugin, který potřebujete, a musíte v CSP hlavičce kvůli němu povolit unsafe-eval.

Tedy existuje spousta webů se špatným zabezpečením a co se dostane do reklamní sítě, to se může jednoduše dostat ke spoustě lidem na spoustě webů. Což se už stalo nespočetkrát, třeba před pár dny Googlu. Samozřejmě bych mohl vytipovat důvěryhodné weby, jenže nikdy si nemohu být ničím jist.

Každopádně je tu další problém. Nechci být sledován. Teorie, kdy si web vydělává reklamou a tím může dodávat obsah zadarmo, je hezká, jenže prakticky reklama dělá na pozadí věci, které jsou u mne za čárou. Například Facebook se svým like tlačítkem na všech webech má přehled, kde se jeho uživatelé po webu pohybují (uBlock Origin má v 3rd-party filters sekci Social, doporučuji zapnout). Čte také soukromé zprávy a na jejich základě nabízí reklamy. Google zase čte e-maily. Je to logický krok a chápu ho; dobře zacílená reklama je lepší i pro uživatele.

Jenže se chci svobodně rozhodnout, komu dám důvěrné informace. Jestli vůbec někomu. Sice existuje „Do Not Track“ hlavička, jenže to je pouze dobrovolné. Spíš je to „prosím, nesledujte mě“. Což samozřejmě reklamní síť může a nemusí brát v úvahu. Či dokonce to ta síť může zahrnout do ještě lepšího sledování.

Navíc, jelikož nejsou weby ani na https, poskytovatelé internetu mohou přidávat do stránek reklamu, aniž by sami autoři takový počin schválili. Nemusí to být jen reklama, ale i malware.

Abych nezapomněl, žijeme v EU, kde každý web musí informovat o tom, že používá základní kámen webu. Cookies. Takže při návštěvě webu se musí nejprve odkliknout otravná hláška. Která se mimochodem taky s oblibou implementuje pomocí třetí strany, která tak dostává velkou moc být využita na šíření malware. (uBlock Origin má v 3rd-party filters EU: Prebake - Filter Obtrusive Cookie Notices, doporučuji zapnout.)

Sečteno podtrženo, dokud nebudu moct reklamním sítím či webům věřit, budu používat nekompromisně „ad-block“ na veškerou havěť. Obsah zadarmo neznamená, že musím otevřít dveře vandalům. Samozřejmě chápu vydavatele a nemám problém, aby mi zobrazili vstupní bránu, kde buď vypnu ad-block nebo zaplatím.

Checklist na zabezpečení webových aplikací

V poslední době jsem častokrát řešil bezpečnost webů a vzpomínal, cože vše to musím mít v cajku. Tak jsem se rozhodl si sepsat takový check-list. A možná bude užitečný i někomu jinému. :-)

Základem je HTTPS

Bez toho asi nemá smysl ani řešit nic jiného. Takže to je must-have první věc, kterou řešit, pokud chcete web zabezpečit. A ne jen nutně zabezpečit, cokoliv proběhne po drátech nešifrovaně, může kdekoliv po cestě někdo upravit. Třeba se na nás přiživovat vkládáním vlastní reklamy. Jop, i tací poskytovatelé internetu mezi námi existují.

HSTS

Když už je HTTPS nastavené, další krok je mít správně nastavený redirect z HTTP na HTTPS. Aby se nestalo, že lze nějak web prohlížet přes nezabezpečené vody. Když už jste si dali tu práci, ať to má smysl.

Redirect však není vše. Uživatelé často pečou na to, co do prohlížeče zadají, a tak útočník může vylákat oběť na HTTP, i když třeba máme redirecty pořešené. Proto nastavíme HSTS hlavičku, aby prohlížeč ani HTTP nezkoušel a v takovém případě sám přesměroval. (Ano, znamená to, že když podělám SSL, nebude vůbec fungovat web. Ale mnohdy lepší žádný, než nebezpečný.)

Strict-Transport-Security: max-age=31536000; includeSubDomains

Session cookie

Web je nyní zabezpečený a snažíme se našeho uživatele držet od HTTP co nejdále. Ale nikdy si nemůžeme být jisti, co se útočníkovi povede udělat. Proto budeme držet to nejcenější v co největším bezpečí. Mluvím o session v cookie. Rozhodně by měla být nastavena jako HTTP, což znamená, že ji nelze přečíst JavaScriptem. Mít nastaveno taky Secure není taky na škodu. Znamená to, že cookina půjde pouze po šifrovaném spojení.

CSP

Neboli Content Security Policy je hlavička povolující jen určité zdroje. To znamená, že touto hlavičkou lze znemožnit útočníkovi vložit nebezpečný script. Resp. vložit může, ale nic to neudělá. Lze nastavit defaultně pro všechny, případně pro každý typ zvlášť (obrázek, fonty, JavaScripty, …).

Rozhodně je dobré se vyhnout unsafe-inline či dokonce unsafe-eval. Nejlépe dovolit jen vaši doménu, případně ještě ověřené CDNky. A samozřejmě nejen zakázat, ale také zakázané pokusy nahlásit – je dobré vědět, zda se někdo o něco pokouší.

Content-Security-Policy: default-src 'self'; report-uri /csp-report;

Případně lze využít verzi, která jen nebezpečný zdroj napráší. Vhodné do začátku, než se odladí již běžící web, ale rychle bych se dostal do striktního módu.

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report;

XSS

CSP je fajn, ale pokud se útočníkovi povede dostat do stránky script přes naši samotnou webovou aplikaci, jsme namydlení. Naštěstí prohlížeče obsahují zabudovanou ochranu proti XSS (Cross Site Scripting). Normálně bývá zapnutá, ale jistota je jistota… (A opět lze bonzovat, což je asi to nejužitečnější na této hlavičce.)

X-Xss-Protection: 1; mode=block; report=/xss-report;

Iframe

Iframy se sice už nepoužívají, ale neměli bychom na ně zapomínat. Skrývají totiž potenciální nebezpečí. Útočník může naši stránku dát do iframe, překrýt nějakou zajímavou hrou (třeba klikací reklama v podobě „chytni všechny míče a máš možnost vyhrát nový iPhone“) a donutit tak uživatele kliknout na místa na našem webu, jak potřebuje. Proto je nejlepší úplně zablokovat možnost naši stránku v nějakém iframe mít.

X-Frame-Options: DENY

Typy souboru

Ať už na webu máme nahrávání souborů, které pak i zobrazujeme, či nikoliv, nikdy si nemůžeme být jisti, co se útočníkovi povede. Proto je možnost mu zase jednoduše znepříjemnit práci a to tak, že typ souboru budeme vždy určovat my a prohlížeč se nebude snažit hádat. Tedy pokud útočník nahraje JavaScript či celou HTML stránku, ale my takové věci nepodporujeme, pak prostě jako HTML stránku nevydáme a tudíž se nic nestane.

X-Content-Type-Options: nosniff

CSRF

Už jste si všimli, že e-mailové aplikace se ptají, zda zobrazit obrázky? Je to z důvodu, že pokud jste například přihlášeni na Facebooku a útočník vám poslal e-mail s obrázkem, který není obrázek, ale jen odkaz na smazání účtu, a vy se na takový obrázek chcete podívat… máte po účtu. Teoreticky. Bude to platit na webech, kde takové akce lze provést obyčejným GET požadavkem, což Facebook není.

Základem je veškeré akce nedělat GETem, ale POSTem či ostatními. To ale nezabrání místo obrázku využít například formulář, který uživatel vyplní nevědomky, neb si myslí, že je o něčem úplně jiném. Proto je dobré přidat ke každému požadavku ještě nějaký token. Na serveru vygenerovat token a ten při akci poslat zpět (a zvalidaovat, samozřejmě). Poté útočník musí nejprve zjistit i validní CSRF token, aby mohl takto uškodit. Což je podstatně složitější, neb web máme za SSL.

HPKP

Třešničkou na dortu je HPKP, což určuje, kterým certifikátům věřit. Defaultně prohlížeče věří všem certifikátům autorit, které mají v seznamu věrohodných. Jenže už se stalo, že byla certifikační autorita napadnuta…

Public-Key-Pins: pin-sha256='…'; pin-sha256='…'; max-age=5184000; report-uri=/hpkp-report;

V ukázce je vidět dvakrát pin-sha256. To není překlep, ale první je aktuálně používaný a druhý backup. Například příprava na vyexpirování atp. A opět lze zároveň bonzovat pokusy a nebo pouze bonzovat.

Public-Key-Pins-Report-Only: pin-sha256='…'; pin-sha256='…'; max-age=5184000; report-uri=/hpkp-report;

Hesla

Pokud se spravují hesla, musí se sledovat novinky a mít hesla co nejlépe zabezpečená. Tedy žádné MD5 hashe, ale co nejpomalejší hashovací algoritmus. Jakýkoliv algoritmus je oslaben proti jednomu typu útoku – brute force. Proto je dobré vybrat pomalý algoritmus, aby si nemohl útočník louskat hashe na jeho Raspberry po večerech. Často jsem používal PBKDF2 (default v Djangu), ale nic se nezkazí s bcrypt (náročné na CPU) či scrypt (náročné na paměť), které už jsou rozšířené. Mimochodem výkon lze stále lépe škálovat, než paměť.

Jelikož uniknutí databáze, kterou by mohl začít někdo louskat, nehrozí tak často, je potřeba se zamyslet taky nad přihlašovacím formulářem. Není dobré nechat útočníka v pohodě zkoušet louskat přímo na našem webu. Minimálně si monitorovat nebezpečné množství pokusů, raději s automatickým zpomalováním až blokováním. S blokováním však opatrně, neb se pak může zamezit přístup skutečným uživatelům. Například u naší „interní“ aplikaci víme, odkud se uživatelé přihlašují, takže můžeme podezřelá místa rovnou blokovat. U aplikací pro širokou veřejnost je lepší volbou zpomalování.

Logování

Pokud máte vše až potud, web máte dobře zabezpečen. :-) Ale dovolím si na závěr ještě jednu drobnost. A to, že i na druhé straně, tedy na vašem serveru, je potřeba k citlivým údajům přistupovat opatrně. Základem je mít vypnut debug mód v produkci (a nejlépe i na testu). I když má například Werkzeug debugger nově PIN k aktivaci, je to prostě díra.

Co je ale důležitější, je logování. Logujete si celé požadavky i se vstupními parametry? Všude, včetně login obrazovky? Pak máte logy pravděpodobně plné hesel v čitelné podobě. My jsme si například ve Flasku přetížili Werkzeugový ImmutableOrderedMultiDict, který skryje nebezpečné hodnoty.

Další tip, pokud pracujete v kódu často s citlivými údaji, použít nějaký speciální objekt, který nedovolí nijak zobrazit vnitřní hodnotu. Můžete pak hodnotu přenášet všude možně a máte jistotu, že se po cestě nezaloguje. Něco ve stylu:

class SecretValue(object):
    def __init__(self, secret_value):
        self.__secret_value = secret_value
    
    def get_secret_value(self):
        return self.__secret_value
    
    def __str__(self):
        return '--secret-value--'
    
    def __repr__(self):
        return '<SecretValue>'

>>> v = SecretValue('aaa')
>>> str(v)
'--secret-value--'
>>> repr(v)
'<SecretValue>'
>>> str({'value': v})
"{'value': }"
>>> logging.info(p)
INFO:root:--secret-value--
>>> logging.info('value: {}'.format(v))
INFO:root:value: --secret-value--

Poslední tip je na tracebacky. Python to například nedělá, ale PHP nahradí parametry funkcí za skutečné hodnoty. Docela užitečná věc pro debugování, ale nepraktická na citlivé údaje. Doporučuji takové chování vypnout, pokud lze. Pokud nelze, vybrat si rozumější nástroj. :-)


A to je vše! Aspoň z toho nejvíce důležitého. Pokud si myslíte, že mi něco ještě chybí, klidně mne upozorněte v komentářích.

Uložená hesla v prohlížeči rozhodně nejsou v bezpečí

Na Lupě vyšel článek Hesla uložená v prohlížeči Chrome lze získat „až překvapivě snadno“. Hned mě napadlo, o čem to bude. Je tomu nedávno, co jsem si všiml, jak snadno si lze hesla v nastavení prohlížeče přečíst. Tím jsem si ještě více potvrdil, že je dobré k mému prohlížeči nepouštět nikoho bez plné důvěry.

Zamýšlel jsem, proč je vůbec něco takového možné. Je mi jasné, že heslo je stejně někde v podobě, která lze rozšifrovat. Musí, jinak by celá funkcionalita byla k ničemu. V horším případě je někde v plain textu (což v případě Chrome neplatí; data jsou šifrována). Přeci ale není důvod to nechat přečíst kde komu na vyžádání bez jakékoliv crackovací utilitky. Nebo by to alespoň mohlo být skryto za nějaké master password…

Pak mi to ale došlo. Je úplně jedno, jestli jsou uložená hesla v prohlížeči nějak šifrována, jestli jdou či nejdou zobrazit nebo jestli jsou chráněny s master password. Vše je irelevantní díky konzoli. Stačí otevřít stránku, nechat si heslo předvyplnit, otevřít vývojářskou konzoli a napsat document.getElementById("somepasswordinput").value a voilà! Existuje i varianta pro nefanoušky JavaScriptu: otevře se konzole, klikne se na tlačítko přihlásit a podívá se, jaká data v POST požadavku odešla.

Pro jistotu znovu: jakkoliv šifrovaná a zaheslovaná uložená hesla v prohlížeči lze zjistit snadno. Stačí mít na chvilku přístup k prohlížeči.

Proto si myslím, že Google dělá dobrou věc. Možnost zadat master password ve Firefoxu akorát vyvolává falešný pocit bezpečí. Opravdu jsem si kdysi dávno myslel, že s master password je vše v pořádku. Až s Chromem jsem zjistil, jak moc jsem se mýlil.

P.S.: Jestli má vůbec smysl řešit hesla, když se mi někdo dostane k počítači, kde jsem všude přihlášen. ;)

On-line bankovnictví Komerční banky

Založil jsem si u Komeční banky účet, spokojeně odjel domů a zapomněl si na pobočce dokumenty. To naštve, ale o tom vám tu vyprávět nechci; chci si postěžovat o tom, jak mají řešené internetové bankovnictví, přesněji přístup k němu.

 

Jako první mě naštvala nutnost mít certifikát. Bez certifikátu ani rána! To znamená (v podání KB) mít nutně nainstalovanou Javu (což o to, tu já tu i mám), jenže ten jejich software mi vytěžuje jedno jádro na maximum a po minutě/dvou shodí všechny taby, na kterých je Komerční banka. WTF?! Napočítal jsem do tří a řekl si, že to přežiju, že do banky budu chodit přes jiný prohlížeč, než je Chromium; našel jsem Operu (a jak ta se na mém počítači vzala?) a ta, zdá se, jakžtakž funguje.

První problém jsem překonal, tak jdu dál. No hádejte, o klik později mě zase rozhořčili – prostě si drze dovolili vytvořit adresář, kam bude umístěn certifikát, aniž by se mě to zeptalo, kam bych ho rád umístil. To není moc dobrá bezpečnost, když ukládají certifikáty automaticky na stejná místa. No dobrá, disk by měl být šifrovaný, zkusím to překousnout.

Následuje zadání hesla k certifikátu. To už bylo ale na mě příliš, musel jsem si zanadávat – oni omezují delku hesla a zakazují speciální znaky! Tak co to má být? Já chci mít své peníze v naprostém bezpečí a řešení Komerční banky mi ho teda rozhodně nepřináší. Jelikož ztráta certifikátu = výlet na pobočku, tak musím certifikát nějak zálohovat a jelikož nemohu použít silné heslo, tak se z toho stává poměrně snadná kořist.

Všichni mi říkají, že jméno kocoura se jako heslo pro roota nehodí. Ale když já jsem si tak zvykl na svýho qŧb!7R$_2&t!

Mimochodem – on-line bankovnictví KB se mi vzhledově vůbec nelíbí.

Hacking webových aplikací

Nedávno jsem měl v práci obsáhlejší přednášku o bezpečnosti webových aplikací. Několik popisovaných problémů jsem znal, jmenovitě například cross-site request forgery (CSFR), csoss-site scripting (XSS), SQL Injection a spoustu dalších; některé jsem jen znal, ale nevěděl, že se jim nějak říka (pak jsem vědel a už zase nevím :); některé jsem neznal a některé přímo šokovaly, i když si nejsem jist, zda mě to přímo šokovalo nebo jsem jen nevěřil vynalézavosti záškodníků.

Nemám v plánu tu popisovat všechno, co jsem se dozvěděl – jen vám tu hodím seznam bezpečnostních hrozeb, abyste si jich alespoň všimli a měli o nich povědomí, že existují:

  • Authentication
    • Dictionary / Brute Force Attack
    • Insufficient Authentication
    • Weak Password Recovery Validation
  • Authorization
    • Credential/Session Prediction
    • Insufficient Authorization
    • Insufficient Session Expiration
    • Session Fixation
    • Cross-site request forgery (CSRF)
    • Clickjacking
    • JavaScript Hijacking
  • Client-side Attacks
    • Content Spoofing
    • Cross-site scripting (XSS)
    • Cross-site Tracing (XST)
    • Browser and Plug-in vulnerabilities
  • Protocol Attacks
    • HTTP Response Splitting
    • HTTP Request Smuggling
  • Injection Attacks
    • Buffer Overflows
    • Format String
    • OS Commanding
    • LDAP Injection
    • SQL Injection
    • XPATH Injection
    • SSI Injection
    • SOAP Injection
  • Information Disclosure
    • Directory Indexing
    • Information Leakage
    • Path Traversal
    • Predictable Resource Location / Forced Browsing
    • Insecure Direct Object Reference
    • Webserver/Application Fingerprinting
  • Server-Side Script Execution
    • Unprotected Upload
    • Remote File Inclusion
    • Local File Inclusion
  • Logical Attacks
    • Abuse of functionality
    • Insufficient Anti-Automation
    • Insufficient Process Validation
    • Parameter Tampering/Cookie Poisoning / Hidden Field Manipulation

Že jich je hodně? Ano, je, ale doporučuju vložit čas do jejich projití, minimálně prolétnutí. :) Abyste však měli inspiraci si je projít, příkládám některá zajímavá videa:

    Taky zajímavá praktika (na kterou jsem bohužel nenašel video) je vložit stránku do iframe, do vyšší vrstvy vložit různé divy s jiným obsahem a pokusit se zaujmout uživatele natolik, aby sám klikl na místa, která se hackrovi hodí, aniž by uživatel věděl, co vlastně na pozadí provádí.

    Až po této přednášce, kde mi byly ukázány podobné praktiky, jsem vlastně pochopil všechny ty reklamy typu „chyť 10x míč a vyhraj bla bla!. Asi už všechny interaktivní reklamy a podobné hříčky budete taky ignorovat, že? :) Nakonec doporučím občas se podívat na server soom.cz, díky kterému jsme měli v práci zmíněnou přednášku a kde naleznete další informace na toto téma.