Sdílet prostřednictvím


Úvod do zabezpečení SignalR

Patrick Fletcher, Tom FitzMacken

Výstraha

Tato dokumentace není určená pro nejnovější verzi SignalR. Podívejte se na ASP.NET Core SignalR.

Tento článek popisuje problémy se zabezpečením, které je nutné zvážit při vývoji aplikace SignalR.

Verze softwaru používané v tomto tématu

Předchozí verze tohoto tématu

Informace o starších verzích služby SignalR naleznete v tématu Starší verze signalR.

Dotazy a komentáře

Napište nám prosím svůj názor na to, jak se vám tento kurz líbil a co bychom mohli vylepšit v komentářích v dolní části stránky. Pokud máte dotazy, které přímo nesouvisí s kurzem, můžete je publikovat na fóru ASP.NET SignalR nebo StackOverflow.com.

Přehled

Tento dokument obsahuje následující části:

Koncepty zabezpečení služby SignalR

Autentizace a autorizace

SignalR neposkytuje žádné funkce pro ověřování uživatelů. Místo toho integrujete funkce SignalR do existující struktury ověřování pro aplikaci. Uživatele ověřujete jako obvykle ve své aplikaci a pracujete s výsledky ověřování v kódu SignalR. Můžete například ověřovat uživatele pomocí ověřování formulářů ASP.NET a pak v centru vynutit, kteří uživatelé nebo role mají oprávnění volat metodu. V centru můžete klientovi předat také ověřovací informace, jako je uživatelské jméno nebo jestli uživatel patří do role.

SignalR poskytuje atribut Authorize k určení, kteří uživatelé mají přístup k centru nebo metodě. Atribut Authorize použijete u hubu nebo konkrétních metod v hubu. Bez atributu Authorize jsou všechny veřejné metody v centru dostupné klientovi, který je připojený k centru. Další informace o centrech najdete v tématu Ověřování a autorizace služby SignalR Hubs.

Tento atribut Authorize použijete pro rozbočovače, nikoliv pro trvalá připojení. Při použití PersistentConnection musíte přepsat metodu AuthorizeRequest pro vynucení autorizačních pravidel. Další informace o trvalých připojeních najdete v tématu Ověřování a autorizace trvalých připojení SignalR.

Token připojení

SignalR snižuje riziko spuštění škodlivých příkazů tím, že ověřuje identitu odesílatele. Pro každou žádost klient a server předá token připojení, který obsahuje ID připojení a uživatelské jméno pro ověřené uživatele. ID připojení jednoznačně identifikuje každého připojeného klienta. Server náhodně vygeneruje ID připojení při vytvoření nového připojení a zachová toto ID po dobu trvání připojení. Ověřovací mechanismus pro webovou aplikaci poskytuje uživatelské jméno. SignalR používá k ochraně tokenu připojení šifrování a digitální podpis.

Diagram znázorňující šipku z žádosti klienta o nové připojení k přijetí žádosti o připojení na serveru, pokračující k odpovědi serveru a končící u přijetí odpovědi klientem. Ověřovací systém vygeneruje v polích Odpověď a Přijatá odpověď token připojení.

Pro každý požadavek server ověří obsah tokenu, aby se zajistilo, že požadavek pochází od zadaného uživatele. Uživatelské jméno musí odpovídat ID připojení. Ověřením ID připojení i uživatelského jména signalR znemožní škodlivému uživateli snadno zosobnění jiného uživatele. Pokud server nemůže ověřit token připojení, požadavek selže.

Diagram znázorňuje šipku z požadavku klienta na server, který přijal požadavek, až po uložený token. Token připojení a zpráva se nacházejí jak v boxu Klient, tak v boxu Server.

Vzhledem k tomu, že ID připojení je součástí procesu ověření, neměli byste odhalit ID připojení jednoho uživatele jiným uživatelům nebo uložit hodnotu do klienta, například v souboru cookie.

Tokeny připojení vs. jiné typy tokenů

Tokeny připojení jsou občas označeny nástroji zabezpečení, protože se zdá, že se jedná o tokeny relací nebo ověřovací tokeny, které představují riziko, pokud jsou vystaveny.

Připojovací token služby SignalR není ověřovací token. Slouží k potvrzení, že uživatel provádějící tento požadavek je stejný jako uživatel, který vytvořil připojení. Token připojení je nezbytný, protože ASP.NET SignalR umožňuje přecházet mezi servery. Token přidruží připojení k určitému uživateli, ale nevytvrdí identitu uživatele, který požadavek provádí. Aby se požadavek SignalR správně ověřil, musí mít nějaký jiný token, který ověřuje identitu uživatele, například cookie nebo nosný token. Samotný token připojení však neprovádí žádnou deklaraci identity, že požadavek provedl tento uživatel, pouze že ID připojení obsažené v tokenu je přidruženo k tomuto uživateli.

Vzhledem k tomu, že token připojení neposkytuje žádné autentizační tvrzení samo o sobě, není považován za "relace" nebo "ověřovací" token. Převzetí tokenu připojení daného uživatele a jeho přehrání v požadavku ověřeném jako jiný uživatel (nebo neověřený požadavek) selže, protože identita uživatele uložená v tokenu se neshoduje.

Opětovné připojení ke skupinám při znovupřipojení

Aplikace SignalR ve výchozím nastavení automaticky znovu přiřadí uživatele k příslušným skupinám při opětovném připojení z dočasného přerušení, například při vyřazení a opětovném navázání připojení před vypršením časového limitu připojení. Při opětovném připojení klient předá token skupiny, který obsahuje ID připojení a přiřazené skupiny. Token skupiny je digitálně podepsaný a šifrovaný. Klient si po opětovném připojení zachová stejné ID připojení; ID připojení předané z znovu připojovaného klienta proto musí odpovídat předchozímu ID připojení používanému klientem. Toto ověření brání uživateli se zlými úmysly předávat žádosti o připojení k neoprávněným skupinám při opětovném připojení.

Je ale důležité si uvědomit, že platnost tokenu skupiny nevyprší. Pokud uživatel patří do skupiny v minulosti, ale byl z této skupiny zakázaný, může být tento uživatel schopen napodobit token skupiny, který obsahuje zakázanou skupinu. Pokud potřebujete bezpečně spravovat, do kterých skupin patří uživatelé, musíte tato data ukládat na server, například do databáze. Pak do aplikace přidejte logiku, která ověřuje na serveru, jestli uživatel patří do skupiny. Příklad ověření členství ve skupině najdete v tématu Práce se skupinami.

Automatické opětovné připojování skupin se použije jenom v případech, kdy se připojení znovu připojí po dočasném přerušení. Pokud se uživatel odpojí tím, že přejde mimo aplikaci nebo se aplikace restartuje, musí aplikace zpracovat, jak přidat daného uživatele do správných skupin. Další informace najdete v tématu Práce se skupinami.

Jak SignalR brání útokům Cross-Site Request Forgery (CSRF)

Útok CSRF (Cross-Site Request Forgery) je útok, kdy škodlivý web odešle požadavek na ohrožený web, kde je uživatel aktuálně přihlášený. SignalR brání CSRF tím, že znemožní škodlivému webu vytvořit platný požadavek pro vaši aplikaci SignalR.

Popis útoku CSRF

Tady je příklad útoku CSRF:

  1. Uživatel se přihlásí do www.example.com pomocí ověřování přes formuláře.

  2. Server ověří uživatele. Odpověď ze serveru obsahuje ověřovací soubor cookie.

  3. Bez odhlášení uživatel navštíví škodlivý web. Tento škodlivý web obsahuje následující formulář HTML:

    <h1>You Are a Winner!</h1>
    <form action="http://example.com/api/account" method="post">
        <input type="hidden" name="Transaction" value="withdraw" />
        <input type="hidden" name="Amount" value="1000000" />
        <input type="submit" value="Click Me"/>
    </form>
    

    Všimněte si, že akce formuláře se odesílá na zranitelný web, ne na škodlivý web. Toto je „meziwebová“ část CSRF.

  4. Uživatel klikne na tlačítko Odeslat. Prohlížeč obsahuje ověřovací soubor cookie s požadavkem.

  5. Požadavek běží na example.com serveru s kontextem ověřování uživatele a může udělat cokoli, co může ověřený uživatel dělat.

I když tento příklad vyžaduje, aby uživatel klikl na tlačítko formuláře, může škodlivá stránka stejně snadno spustit skript, který odešle požadavek AJAX do aplikace SignalR. Použití protokolu SSL navíc nezabrání útoku CSRF, protože škodlivý web může odeslat požadavek "https://".

Útoky CSRF jsou obvykle možné na weby, které k ověřování používají soubory cookie, protože prohlížeče odesílají všechny relevantní soubory cookie na cílový web. Útoky CSRF se ale neomezují pouze na zneužití souborů cookie. Například základní ověřování a ověřování pomocí algoritmu digest jsou také zranitelná. Jakmile se uživatel přihlásí pomocí ověřování Basic nebo Digest, prohlížeč automaticky odešle přihlašovací údaje, dokud relace nekončí.

Opatření proti CSRF zavedená službou SignalR

Služba SignalR provede následující kroky, aby zabránila škodlivému webu ve vytváření platných požadavků na vaši aplikaci. SignalR ve výchozím nastavení provede tyto kroky, nemusíte ve svém kódu provádět žádnou akci.

  • Zakázat požadavky mezi doménami SignalR zakáže požadavky mezi doménami, aby uživatelům zabránil ve volání koncového bodu SignalR z externí domény. SignalR považuje všechny požadavky z externí domény za neplatné a zablokuje požadavek. Doporučujeme zachovat toto výchozí chování; jinak by škodlivý web mohl uživatele oklamat odesíláním příkazů na váš web. Pokud potřebujete použít žádosti mezi doménami, viz Jak vytvořit připojení mezi doménami.
  • Předání připojovacího tokenu v řetězci dotazu, nikoli souboru cookie SignalR předá token připojení jako hodnotu řetězce dotazu místo jako soubor cookie. Uložení tokenu připojení do souboru cookie je nebezpečné, protože prohlížeč může neúmyslně předávat token připojení, když dojde ke zjištění škodlivého kódu. Předáním tokenu připojení v řetězci dotazu zabráníte tomu, aby token připojení přetrval po ukončení aktuálního připojení. Uživatel se zlými úmysly proto nemůže vytvořit žádost pod přihlašovacími údaji pro ověřování jiného uživatele.
  • Ověření tokenu připojení Jak je popsáno v části Token připojení , server ví, které ID připojení je přidružené ke každému ověřenému uživateli. Server nezpracuje žádný požadavek z ID připojení, které neodpovídá uživatelskému jménu. Je nepravděpodobné, že by uživatel se zlými úmysly mohl odhadnout platný požadavek, protože by musel znát uživatelské jméno a aktuální náhodně generované ID připojení. Toto ID připojení bude neplatné, jakmile bude připojení ukončeno. Anonymní uživatelé by neměli mít přístup k žádným citlivým informacím.

Doporučení zabezpečení služby SignalR

Protokol SSL (Secure Socket Layer)

Protokol SSL používá šifrování k zabezpečení přenosu dat mezi klientem a serverem. Pokud vaše aplikace SignalR přenáší citlivé informace mezi klientem a serverem, použijte pro přenos protokol SSL. Další informace o nastavení SSL naleznete v tématu Jak nastavit SSL ve službě IIS 7.

Nepoužívejte skupiny jako mechanismus zabezpečení.

Skupiny představují pohodlný způsob shromažďování souvisejících uživatelů, ale nejedná se o zabezpečený mechanismus pro omezení přístupu k citlivým informacím. To platí zejména v případě, že se uživatelé můžou během opětovného připojení automaticky znovu připojit ke skupinám. Místo toho zvažte přidání privilegovaných uživatelů do role a omezení přístupu k metodě centra pouze na členy této role. Příklad omezení přístupu na základě role najdete v tématu Ověřování a autorizace služby SignalR Hubs. Příklad kontroly přístupu uživatelů ke skupinám při opětovném připojení najdete v tématu Práce se skupinami.

Bezpečné zpracování vstupu od klientů

Aby se zajistilo, že uživatel se zlými úmysly neodesílá skript jiným uživatelům, musíte zakódovat veškerý vstup od klientů určených pro vysílání do jiných klientů. Zprávy byste měli zakódovat na přijímajících klientech místo serveru, protože aplikace SignalR může mít mnoho různých typů klientů. Kódování HTML proto funguje pro webového klienta, ale ne pro jiné typy klientů. Například metoda webového klienta pro zobrazení chatu by bezpečně zpracovávala uživatelské jméno a zprávu voláním html() funkce.

chat.client.addMessageToPage = function (name, message) {
    // Html encode display name and message. 
    var encodedName = $('<div />').text(name).html();
    var encodedMsg = $('<div />').text(message).html();
    // Add the message to the page. 
    $('#discussion').append('<li><strong>' + encodedName
        + '</strong>:  ' + encodedMsg + '</li>');
};

Řešení změny stavu uživatele s aktivním připojením

Pokud se stav ověřování uživatele změní, když existuje aktivní připojení, zobrazí se uživateli chyba oznamující, že identita uživatele se během aktivního připojení SignalR nemůže změnit. V takovém případě by se vaše aplikace měla znovu připojit k serveru, aby se ujistila, že id připojení a uživatelské jméno jsou koordinované. Pokud například vaše aplikace umožňuje, aby se uživatel odhlašil, když existuje aktivní připojení, uživatelské jméno pro připojení se už nebude shodovat s názvem předaným pro další požadavek. Před odhlášením uživatele budete chtít připojení zastavit a poté ho restartovat.

Je však důležité si uvědomit, že většina aplikací nebude muset ručně zastavit a spustit připojení. Pokud vaše aplikace po odhlášení přesměruje uživatele na samostatnou stránku, například výchozí chování v aplikaci Webové formuláře nebo aplikaci MVC nebo aktualizuje aktuální stránku po odhlášení, aktivní připojení se automaticky odpojí a nevyžaduje žádnou další akci.

Následující příklad ukazuje, jak zastavit a spustit připojení při změně stavu uživatele.

<script type="text/javascript">
    $(function () {
        var chat = $.connection.sampleHub;
        $.connection.hub.start().done(function () {
            $('#logoutbutton').click(function () {
                chat.connection.stop();
                $.ajax({
                    url: "Services/SampleWebService.svc/LogOut",
                    type: "POST"
                }).done(function () {
                    chat.connection.start();
                });
            });
        });
    });
</script>

Nebo se stav ověřování uživatele může změnit, pokud váš web používá posuvné vypršení platnosti s ověřováním pomocí formulářů a neexistuje žádná aktivita, která by zachovala platnost ověřovacího souboru cookie. V takovém případě se uživatel odhlásí a uživatelské jméno se už nebude shodovat s uživatelským jménem v tokenu připojení. Tento problém můžete vyřešit přidáním některého skriptu, který pravidelně požaduje prostředek na webovém serveru, aby byl ověřovací soubor cookie platný. Následující příklad ukazuje, jak požádat o prostředek každých 30 minut.

$(function () {
    setInterval(function() {
        $.ajax({
            url: "Ping.aspx",
            cache: false
        });
    }, 1800000);
});

Automaticky generované soubory proxy javascriptu

Pokud nechcete zahrnout všechna centra a metody do souboru proxy JavaScriptu pro každého uživatele, můžete zakázat automatické generování souboru. Tuto možnost můžete zvolit, pokud máte více center a metod, ale nechcete, aby každý uživatel věděl o všech metodách. Automatické generování zakážete nastavením EnableJavaScriptProxies na false.

var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableJavaScriptProxies = false;
app.MapSignalR(hubConfiguration);

Další informace o souborech proxy JavaScriptu najdete v generovaném proxy serveru a o tom, co za vás dělá.

Výjimky

Vyhněte se předávání objektů výjimek klientům, protože objekty mohou klientům odhalit citlivé informace. Místo toho zavolejte metodu na klientovi, která zobrazuje příslušnou chybovou zprávu.

public Task SampleMethod()
{
    try
    { 
        // code that can throw an exception
    }
    catch(Exception e)
    {
        // add code to log exception and take remedial steps

        return Clients.Caller.DisplayError("Sorry, the request could not be processed.");
    }
}