Naše úsilí o připojení se zaměřuje na rozšíření přístupu k internetu a jeho přijetí po celém světě. Patří sem naše práce na technologiích, jako je Terragraph, naše spolupráce s mobilními operátory na úsilí o rozšíření přístupu na venkově, naše práce v rámci projektu Telecom Infra a programy, jako je Free Basics. Jak jsme pokračovali v práci na Free Basics, naslouchali jsme zpětné vazbě a doporučením občanské společnosti a dalších zúčastněných stran. Vyvinuli jsme program Discover speciálně proto, abychom se těmito doporučeními zabývali a zapracovali je do nového produktu, který podporuje konektivitu. Dnes Facebook Connectivity a naši partneři ze společností Bitel, Claro, Entel a Movistar zahajují zkušební provoz služby Discover v Peru.

Poskytování této služby a zároveň zajištění bezpečnosti lidí před potenciálními bezpečnostními riziky bylo náročnou technickou výzvou. Chtěli jsme vyvinout model, který by nám umožnil bezpečně prezentovat webové stránky ze všech dostupných domén včetně jejich zdrojů (skripty, média, styly atd.). Níže vás seznámíme s modelem, který jsme vytvořili, s jedinečnými volbami architektury, které jsme na této cestě učinili, a s kroky, které jsme podnikli ke zmírnění rizik.

Kde jsme začali

Pro Free Basics bylo naším úkolem najít způsob, jak poskytnout bezplatnou službu lidem, kteří používají mobilní web, a to i na funkčních telefonech bez podpory aplikací třetích stran. Službu mohli poskytovat partneři mobilních operátorů, ale omezení sítě a zařízení brány znamenala, že bezplatný mohl být pouze provoz do určitých destinací (obvykle rozsah IP adres nebo seznam doménových jmen). S více než 100 partnery po celém světě a s časem a obtížemi spojenými se změnou konfigurace síťových zařízení operátorů jsme si uvědomili, že musíme přijít s novým přístupem.

Tento nový přístup vyžadoval, abychom nejprve vytvořili webovou proxy službu, kde by operátor mohl službu zdarma zpřístupnit na jediné doméně: freebasics.com. Odtud bychom jménem uživatele načítali webové stránky a doručovali je do jeho zařízení. I v moderních prohlížečích existují určité problémy s architekturou webového proxy serveru. Na webu jsou klienti schopni vyhodnocovat bezpečnostní hlavičky HTTP, jako jsou CORS (cross-origin resource sharing) a CSP (Content Security Policy), a využívat soubory cookie přímo z webu. V konfiguraci proxy serveru však klient komunikuje s proxy serverem a proxy server funguje jako klient webu. Prokládání webových stránek třetích stran prostřednictvím jediného jmenného prostoru porušuje některé předpoklady týkající se způsobu ukládání souborů cookie, rozsahu přístupu skriptů ke čtení nebo úpravám obsahu a způsobu vyhodnocování CORS a CSP.

Pro řešení těchto obav jsme zpočátku zavedli některá přímá omezení, včetně toho, které weby lze navštěvovat pomocí Free Basics, a nemožnosti spouštět skripty. Druhé jmenované se postupem času stalo větším problémem, protože mnoho webových stránek, včetně mobilních, začalo spoléhat na JavaScript pro kritické funkce, včetně vykreslování obsahu.

Počáteční architektura

Návrh domény

Abychom se přizpůsobili omezené funkčnosti mnoha bran mobilních operátorů, zvažovali jsme alternativní architektury, včetně:

  1. Kooperativního řešení, kdy webové stránky mohou přidělit subdoménu (např, free.example.com) a přeložit ji do našeho IP prostoru pro operátory, aby ji mohli bezplatně zpřístupnit uživateli.

Toto řešení mělo klady:

  • umožňovalo přímou end-to-end komunikaci mezi klientem a serverem.
  • Vyžadovalo minimální zásahy na straně proxy serveru.

Mělo však i některé nevýhody:

  • Stránky se musely k tomuto schématu přihlásit, což majitelům stránek přinášelo další technické náklady.
  • Prohlížeče by si musely vyžádat konkrétní doménu prostřednictvím SNI (Server Name Indication), aby proxy server věděl, kam se má připojit. Podpora SNI však není univerzální, což toto řešení učinilo méně schůdným.
  • Pokud by účastníci omylem brouzdali přímo na example.com, a ne na subdoménu free.example.com, byli by zpoplatněni – a nemuseli by být nutně přesměrováni na subdoménu, pokud by provozovatel neimplementoval nějakou další logiku.
  1. Zapouzdření IPv4 v IPv6, kdy můžeme zapouzdřit celý prostor IPv4 do jediné volné datové podsítě IPv6. Přizpůsobený DNS resolver pak rekurzivně resolvuje IPv4 a odpovídá zapouzdřenými odpověďmi IPv6.

Toto řešení mělo také klady:

  • Nevyžadovalo spolupráci majitele webu.
  • Nebylo potřeba SNI pro překlad vzdálené IP.

A nevýhody:

  • Prohlížeče by viděly doménu www.example.com.freebasics.com, ale certifikát www.example.com by vedl k chybě.
  • Takto podporovalo IPv6 jen několik bran operátorů.
  • Ještě méně zařízení podporovalo IPv6, zejména starší verze OS.

Žádné z těchto řešení nebylo životaschopné. Nakonec jsme se rozhodli, že nejlepší možnou architekturou bude origin collapsing, kdy náš proxy server běží v rámci jediného jmenného prostoru domény origin collapsed pod freebasics.com. Provozovatelé pak mohou snadněji povolovat přenosy do tohoto cíle a udržovat své konfigurace jednoduché. Každý origin třetí strany je zakódován v subdoméně, takže můžeme zaručit, že překlad jmen bude vždy směřovat provoz na volnou IP adresu.

Například:

https://example.com/path/?query=value#anchor

Je přepsáno na:

https://https-example-com.0.freebasics.com/path/?query=value#anchor

Na straně serveru existuje rozsáhlá logika, která zajišťuje správnou transformaci odkazů a hrefů. Stejná logika pomáhá zajistit, aby i weby pouze s protokolem HTTP byly bezpečně doručeny přes protokol HTTPS na serveru Free Basics mezi klientem a proxy serverem. Toto schéma přepisování adres URL nám umožňuje používat jediný jmenný prostor a certifikát TLS namísto vyžadování samostatného certifikátu pro každou subdoménu na internetu.

Všechny internetové počátky se stávají sourozenci pod 0.freebasics.com, což vyvolává určité bezpečnostní úvahy. Nemohli jsme využít přidání domény do seznamu veřejných přípon, protože bychom museli pro každý původ vydat jiný soubor cookie, což by nakonec překročilo limity souborů cookie prohlížeče.

Cookies

Na rozdíl od webových klientů, kteří mohou využívat soubory cookie přímo z webu, vyžaduje služba proxy odlišné nastavení. Free Basics ukládá uživatelské soubory cookie na straně serveru z několika důvodů:

  1. Mobilní prohlížeče nižší úrovně mají často omezenou podporu souborů cookie. Pokud vydáme byť jen jeden soubor cookie pro každý web pod naší doménou proxy serveru, mohli bychom být omezeni na nastavení pouhých desítek souborů cookie. Pokud by společnost Free Basics nastavila soubory cookie na straně klienta pro každý web pod 0.freebasics.com, starší prohlížeče by rychle narazily na limity pro místní ukládání souborů cookie – a dokonce i moderní prohlížeče by dosáhly limitu na doménu.
  2. Omezení jmenného prostoru domény, které jsme museli implementovat, také vylučuje použití sourozeneckých a hierarchických souborů cookie. Například soubor cookie nastavený na libovolné subdoméně na adrese .example.com by byl normálně čitelný na libovolné jiné subdoméně. Jinými slovy, pokud a.example.com nastaví soubor cookie na .example.com, pak by jej b.example.com měla být schopna přečíst. V případě Free Basics by a-example-com.0.freebasics.com nastavoval soubor cookie na example.com.0.freebasics.com, což není podle normy povoleno. Protože to nefunguje, ostatní původy, například b-example-com.0.freebasics.com, by neměly přístup k souborům cookie nastaveným pro jejich nadřazenou doménu.

Aby služba proxy mohla přistupovat k této nádobě se soubory cookie na straně serveru, využívá Free Basics dva soubory cookie na straně klienta:

  1. Soubor cookie datr, identifikátor prohlížeče používaný pro účely integrity webu.
  2. The ick (internet cookie key), který obsahuje kryptografický klíč používaný k zašifrování cookie jar na straně serveru. Protože je tento klíč uložen pouze na straně klienta, nemůže být nádoba se soubory cookie na straně serveru dešifrována společností Free Basics, pokud uživatel službu nevyužívá.

Abychom pomohli chránit soukromí a bezpečnost uživatelů při ukládání jejich souborů cookie do nádoby se soubory cookie na straně serveru, zajistíme, aby:

  1. Soubory cookie na straně serveru byly šifrovány pomocí klíče ick, který je uložen pouze na straně klienta.
  2. Když klient poskytne ick, server jej při každém požadavku zapomene, aniž by byl kdy zaznamenán.
  3. Obě cookie na straně klienta označíme jako Secure a HttpOnly.
  4. Index souboru cookie hashujeme pomocí klíče na straně klienta, takže soubor cookie není zpětně dohledatelný, když klíč není přítomen.

Povolením spouštění skriptů riskujeme fixaci souborů cookie na straně serveru. Abychom tomu zabránili, vylučujeme použití JavaScriptu z Free Basics. Navíc, přestože součástí Free Basics může být jakákoli webová stránka, prověřujeme každou stránku individuálně z hlediska možných vektorů zneužití bez ohledu na její obsah.

Vylepšení toho, co jsme vytvořili

Pro podporu modelu sloužícího jakékoli webové stránce s možností bezpečnějšího spouštění skriptů jsme museli výrazně přehodnotit naši architekturu, abychom zabránili hrozbám, jako je možnost skriptů číst nebo fixovat soubory cookie uživatele. JavaScript je velmi obtížné analyzovat a zabránit spuštění nechtěného kódu.

Pro příklad uvádíme několik způsobů, jak by útočník mohl vložit kód, který bychom museli být schopni filtrovat:

setTimeout();location = ' javascript:alert(1) <!--';location = 'javascript\n:alert(1) <!--';location = '\x01javascript:alert(1) <!--';var location = 'javascript:alert(1)';for(location in {'javascript:alert(1)':0}); = 'javascript:alert(1)';location.totally_not_assign=location.assign;location.totally_not_assign('javascript:alert(1)');location] = 'javascript:alert(1)';Reflect.set(location, 'href', 'javascript:alert(1)')new Proxy(location, {}).href = 'javascript:alert(1)'Object.assign(window, {location: 'javascript:alert(1)'});Object.assign(location, {href: 'javascript:alert(1)'});location.hash = '#%0a alert(1)';location.protocol = 'javascript:';

Model, který jsme vymysleli, rozšířil návrh Free Basics, ale také chrání soubor cookie, který uchovává šifrovací klíč, před přepsáním skripty. Používáme vnější rámec, kterému důvěřujeme a který potvrzuje, že s vnitřním rámcem, který prezentuje obsah třetích stran, nebylo manipulováno. Následující část podrobně ukazuje, jak zmírňujeme fixaci relace a další útoky, jako je phishing a clickjacking. Vyložíme metodu, jak bezpečně zobrazit obsah třetích stran a zároveň umožnit spuštění JavaScriptu.

Vylepšení architektury v nástroji Discover

Odkazy na doménu se v tomto bodě změní na naši novou doménu, podobně původem zhroucenou discoverapp.com.

JavaScript a fixace cookies

Při povolování JavaScriptu z webů třetích stran jsme museli uznat, že to umožňuje určité vektory, na které jsme se museli připravit, protože skripty mohou měnit a přepisovat odkazy, přistupovat k libovolné části DOM a v nejhorším případě fixovat cookies na straně klienta.

Řešení, které jsme vymysleli, muselo řešit fixaci souborů cookie, takže namísto snahy analyzovat a blokovat určitá volání skriptů jsme se rozhodli detekovat je v okamžiku, kdy k nim dochází, a učinit je nepoužitelnými. Toho dosáhneme následujícím způsobem:

  1. Při registraci vygenerujeme nový, bezpečný náhodný soubor ick.
  2. Soubor ick odešleme prohlížeči jako soubor HttpOnly cookie.
  3. Poté vytvoříme HMAC hodnotu nazvanou ickt z digestu ick a datr (abychom se vyhnuli fixaci obou) a uložíme kopii ickt na klientovi na místo v localStorage, kam potenciální útočník nemůže zapisovat. Námi používané umístění je https://www.0.discoverapp.com, které nikdy neslouží pro obsah třetích stran. Vzhledem k tomu, že tento původ je sourozencem všech původů třetích stran, nemůže dojít ke snížení domény nebo jakémukoli jinému druhu modifikace domény a původ je považován za důvěryhodný.
  4. Vkládáme ickt, odvozený z cookie ick viděného v požadavku, dovnitř HTML v každé odpovědi proxy třetí strany.
  5. Při načtení stránky porovnáme vložený ickt s důvěryhodným ickt pomocí window.postMessage() a v případě neshody zrušíme platnost relace odstraněním souborů cookie datr a ick.
  6. Zabráníme interakci uživatele se stránkou, dokud tento proces nedokončíme.

Jako další ochranu nastavíme nový soubor cookie datr, pokud zjistíme více souborů cookie na stejném místě, a vložíme časové razítko, abychom mohli vždy použít ten nejnovější.

Řešení dvou rámců

Pro ověření potřebujeme způsob, jak se stránka třetí strany může dotazovat na hodnotu ickt a ověřit ji. Toho dosáhneme vložením stránky třetí strany do <iframe> na stránce v zabezpečeném původu a injektováním kusu JavaScriptu do stránky třetí strany. Vytvoříme zabezpečený vnější rámec a vnitřní rámec třetí strany.

Vnitřní rámec

Vnitřním rámcem injektujeme skript do každé proxované stránky, kterou obsluhujeme. Spolu s ním injektujeme také hodnotu ickt vypočítanou z ick viděnou v požadavku. Chování vnitřního rámce je následující:

  1. Kontrola s vnějším rámcem:
    • postMessage nahoru s ickt vloženým do stránky.
    • Čekat.
    • Pokud skript dostane potvrzení od zabezpečeného původu, necháme uživatele se stránkou interagovat.
    • Pokud skript čeká příliš dlouho nebo dostane odpověď od neočekávaného původu, přesuneme rámec na chybovou obrazovku bez obsahu třetí strany (naše stránka „Oops“), protože je možné, že vnější rámec buď neexistuje, nebo je jiný, než vnitřní rámec očekává.
  2. Kontrola pomocí parent:
    • postMessage na parent.
    • Čekat.
    • Pokud skript dostane odpověď s source===parent a původem pod .0.discoverapp.com, bude pokračovat.
    • Pokud skript čeká příliš dlouho nebo dostane odpověď od neočekávaného původu, přejdeme na stránku „Oops“.

Několik poznámek k vnitřnímu rámci:

  1. Potenciální útočníci by se i v případě jeho obejití mohli fixovat pouze na původ, na kterém mohou dosáhnout spuštění kódu, takže vektory fixace cookies by byly zbytečné.
  2. Předpokládáme, že neškodný původ nebude úmyslně obcházet protokol vnitřního a vnějšího zasílání zpráv.

Vnější rámec

Vnější rámec je tu proto, aby potvrdil, že vnitřní rámec je konzistentní:

  1. Ujišťujeme se, že vnější rámec je vždy horním rámcem s JavaScriptem a X-Frame-Options: DENY.
  2. Počkáme na postMessage.
  3. Pokud vnější rámec obdrží zprávu:
    • Je od původu vnitřního rámce?
    • Pokud ano, ohlásí správnou hodnotu ickt?
      • Pokud ano, pošleme potvrzovací zprávu.
      • Pokud ne, smažeme relaci, odstraníme všechny soubory cookie a přejdeme na bezpečný původ.
  4. Pokud vnější rámec neobdrží zprávu po dobu několika sekund nebo pokud dílčí rámec není nejvyšším vnitřním rámcem, odstraníme umístění z adresního řádku bezpečného rámce.

Interakce se stránkou

Aby se předešlo závodním podmínkám, kdy by osoba mohla zadat heslo pod zafixovaným souborem cookie dříve, než vnitřní rámec dokončí ověření, je důležité zabránit interakci osob se stránkou před dokončením ověřovací sekvence vnitřního rámce.

Aby se tomu zabránilo, server přidává style="display:none" do prvku <html> každé stránky. Vnitřní rámec jej odstraní, jakmile obdrží potvrzení vnějšího rámce.

Kód JavaScriptu je stále povolen ke spuštění a zdroje jsou stále načítány. Pokud však osoba nezadala na stránce žádný vstup, prohlížeč neudělá nic, co by potenciální útočník nemohl udělat pouhou návštěvou webu – pokud tedy web již není zranitelný vůči podvržení požadavku (CSRF).

Při volbě tohoto řešení jsme pak museli řešit další možné výsledky, konkrétně:

  1. Asynchronní fixace souborů cookie.
  2. Clickjacking kvůli rámování.
  3. Phishing vydávající se za doménu Discover.

Asynchronní fixace souborů cookie

Do této chvíle ochrana, kterou jsme implementovali, počítala se synchronní fixací, ale může k ní dojít i asynchronně. Abychom tomu zabránili, použijeme klasickou metodu prevence CSRF. Požadujeme, aby příkazy POST nesly parametr dotazu s datr, který je vidět při načítání stránky. Parametr dotazu pak porovnáme s cookie datr viděným v požadavku. Pokud se neshodují, požadavek nevyplníme.

Abychom zabránili úniku datr, vložíme zašifrovanou verzi datr dovnitř vnitřního rámce a zajistíme, aby byl tento parametr dotazu přidán ke každému objektu <form> a XHR. Protože stránka nemůže sama odvodit token datr, přidaný datr je ten, který je v daném okamžiku vidět.

U anonymních požadavků vyžadujeme, aby měly také parametr dotazu datr. Anonymita je zachována, protože ji nepropustíme na web třetí strany – chybí cookie ick, takže nemůžeme použít cookie jar. V tomto případě však nejsme schopni validovat proti souboru cookie datr, takže anonymní POSTy lze provádět v rámci zafixovaných relací. Protože jsou však anonymní a chybí jim ick, nemohou uniknout žádné citlivé informace.

Clickjacking

Pokud web odešle X-Frame-Options: DENY, nebude se načítat ve vnitřním rámci. Toto záhlaví používají webové stránky, aby zabránily vystavení určitým typům útoků, jako je například clickjacking. Tuto hlavičku z odpovědi HTTP odstraníme, ale požádáme vnitřní rámec, aby pomocí postMessage ověřil, že parent je rám okna top. Pokud ověření selže, přesměrujeme uživatele na stránku „Oops“.

Phishing

„Adresní řádek“, který poskytujeme v zabezpečeném rámu, slouží k tomu, aby byl uživateli vystaven nejvyšší původ vnitřního rámu. Může však být zkopírován phishingovými stránkami, které se vydávají za Discover. Škodlivým odkazům bráníme v navigaci pryč ze služby Discover tím, že pomocí <iframe sandbox> zabráníme navigaci nahoře. Vnějšímu rámci lze uniknout pouze přímou navigací na jiný web.

Soubory cookie na straně klienta

Soubor document.cookie umožňuje JavaScriptu číst a upravovat soubory cookie, které nejsou označeny HttpOnly. Bezpečná podpora je náročná v systému, který udržuje soubory cookie na serveru.

Přístup k souborům cookie: Když je přijat požadavek, proxy server vyjmenuje všechny soubory cookie, které jsou viditelné pro daný původ. Poté připojí ke stránce s odpovědí užitečné zatížení JSON. Kód na straně klienta je injektován tak, aby shimoval document.cookie a učinil tyto soubory cookie viditelnými pro ostatní skripty, jako by to byly skutečné soubory cookie na straně klienta.

Modifikace souborů cookie:

Důvěra ve schopnosti prohlížeče CORS by v tomto případě nestačila – origin a.example.com, který se pokusí nastavit cookie na example.com, bude prohlížečem zablokován, protože tyto originy jsou sourozenci a nejsou hierarchické.

I přesto, když server obdrží nový soubor cookie nastavený klientem, nemůže bezpečně vynutit, zda je cílová doména povolena; původ pisatele je znám pouze u klienta a ne vždy je zaslán serveru způsobem, kterému můžeme důvěřovat.

Aby server donutil klienta prokázat, že je oprávněn nastavovat soubory cookie na konkrétní doméně, pošle kromě užitečného zatížení JSON také seznam kryptografických tokenů pro každý z původů, u kterých je žádající původ oprávněn nastavovat soubory cookie. Tyto tokeny jsou osoleny hodnotou ick, takže je nelze přenášet mezi uživateli.

Podložka na straně klienta pro document.cookie se stará o rozlišení a vložení tokenu do skutečného textu cookie, který je odeslán proxy serveru. Proxy pak může ověřit, že zapisující origin skutečně disponuje tokenem pro zápis do cílové domény cookie, a uloží jej do nádoby cookie na straně serveru a při příštím požadavku na stránku jej opět odešle klientovi.

Protokol Bootstrap

Model obsahuje tři typy originů: portálový origin (Discover portal atd.), zabezpečený origin (vnější rámec) a přepisovací origin (vnitřní rámec). Každý z nich má jinou potřebu:

  1. Portálový origin vyžaduje datr.
  2. Zabezpečený origin vyžaduje ickt.
  3. Přepisovací origin vyžaduje datr a ick.

S protokolem localStorage

Tady je znázorněn proces zavádění pro většinu moderních mobilních prohlížečů:

Je důležité si uvědomit, že aby se zabránilo reflexi, koncový bod zavádění v bezpečném originu vždy vydává nový ick a ickt; ick nikdy nezávisí na vstupu uživatele. Všimněte si, že protože jsme nastavili domain=.discoverapp.com na ick i datr, jsou k dispozici ve všech typech původu a ickt je k dispozici pouze v zabezpečeném původu.

Bez protokolu localStorage

Protože některé prohlížeče, například Opera Mini (oblíbená v mnoha zemích, kde Discover působí), nepodporují localStorage, nemůžeme hodnoty ick a ickt uložit. To znamená, že musíme použít jiný protokol:

Rozhodli jsme se oddělit přepisovací původ od zabezpečeného původu, aby nesdílely stejnou příponu hostitele podle veřejného seznamu přípon. Pro ukládání zabezpečené kopie ickt (jako cookie) používáme www.0.discoverapp.com a všechny originy třetích stran přesouváme pod 0.i.org. V dobře ošetřeném prohlížeči nastavení souboru cookie na zabezpečený původ znepřístupní všechny přepisovací původy.

Protože jsou nyní původy oddělené, stává se náš proces zavádění dvoufázovým procesem. Dříve jsme mohli nastavit ick ve stejném požadavku, který jsme poskytli localStorage s ickt. Nyní musíme zavést dva originy, v samostatných požadavcích, aniž bychom otevřeli fixační vektory ick.

Vyřešíme to tak, že nejprve zavedeme zabezpečený origin se souborem cookie ickt a uživateli poskytneme šifrovanou verzi ick s klíčem, který zná pouze proxy server. K zašifrovanému textu ick je připojena nonce, kterou lze použít k dešifrování daného ick v přepisovacím originu a nastavení cookie, ale pouze jednou.

Útočník si může vybrat buď:

  1. Použít nonce k odhalení cookie ick.
  2. Předat ji uživateli, aby zafixoval její hodnotu.

V obou případech nemůže útočník současně znát a vnutit uživateli konkrétní hodnotu ick. Tento proces také synchronizuje datr mezi původy.

Tato architektura prošla značným interním i externím testováním zabezpečení. Věříme, že jsme vyvinuli návrh, který je dostatečně robustní, aby odolal typům útoků na webové aplikace, s nimiž se setkáváme ve volné přírodě, a bezpečně poskytoval připojení, které je pro mobilní operátory udržitelné. Po spuštění služby Discover v Peru plánujeme zahájit další zkušební provoz služby Discover s partnerskými operátory v řadě dalších zemí, kde jsme prováděli beta testování funkcí produktu, včetně Thajska, Filipín a Iráku. Předpokládáme, že služba Discover bude v těchto dalších zemích spuštěna v nejbližších týdnech, a prozkoumáme další zkoušky, kterých se budou chtít zúčastnit partnerští operátoři.

Rádi bychom poděkovali Berku Demirovi za pomoc při této práci.

Ve snaze o větší srozumitelnost našeho jazyka jsme tento příspěvek upravili tak, aby se slovo „whitelist“ nahradilo slovem „allowlist“.

Ve snaze o větší srozumitelnost našeho jazyka jsme tento příspěvek upravili tak, aby se slovo „whitelist“ nahradilo slovem „allowlist“.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.