Požadavky na zabezpečení v ASP.NET Core SignalR

Autor : Andrew Stanton – zdravotní sestry

Tento článek poskytuje informace o zabezpečení SignalR .

Sdílení prostředků různého původu

Sdílení prostředků mezi zdroji (CORS) se dá použít k povolení připojení mezi zdroji SignalR v prohlížeči. Pokud je JavaScriptový kód hostovaný v jiné doméně než SignalR aplikace, musí být povolen middleware CORS , aby se JavaScript mohl připojit k SignalR aplikaci. Povoluje žádosti mezi zdroji jenom z domén, které důvěřujete nebo ovládáte. Například:

  • Váš web je hostovaný na http://www.example.com
  • Vaše SignalR aplikace je hostována na http://signalr.example.com

V aplikaci by měla být nakonfigurovaná CORS SignalR , aby povolovala jenom původ www.example.com .

Další informace o konfiguraci CORS najdete v tématu povolení požadavků mezi zdroji (CORS). SignalRvyžaduje následující zásady CORS:

  • Povolí konkrétní očekávané zdroje. Povolení libovolného zdroje je možné, ale není zabezpečené nebo Doporučené.
  • Metody HTTP GET a POST musí být povoleny.
  • Přihlašovací údaje musí být povoleny v pořadí, aby cookie správně fungovaly rychlé relace založené na. Musí být povolené i v případě, že se ověřování nepoužívá.

V 5,0 jsme ale v klientovi TypeScript zadali možnost, aby nepoužívala přihlašovací údaje. Možnost Nepoužívat přihlašovací údaje by se měla používat jenom v případě, že víte 100%, že přihlašovací údaje, jako Cookie je třeba, se ve vašich aplikacích nepotřebují v aplikacích, které cookie používají Azure App Service při použití více serverů pro rychlé relace.

Následující zásada CORS například umožňuje klientovi, který je SignalR hostitelem https://example.com aplikace, získat přístup k SignalR aplikaci hostované na https://signalr.example.com :

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // ... other middleware ...

    // Make sure the CORS middleware is ahead of SignalR.
    app.UseCors(builder =>
    {
        builder.WithOrigins("https://example.com")
            .AllowAnyHeader()
            .WithMethods("GET", "POST")
            .AllowCredentials();
    });

    // ... other middleware ...
    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<ChatHub>("/chathub");
    });

    // ... other middleware ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // ... other middleware ...

    // Make sure the CORS middleware is ahead of SignalR.
    app.UseCors(builder =>
    {
        builder.WithOrigins("https://example.com")
            .AllowAnyHeader()
            .WithMethods("GET", "POST")
            .AllowCredentials();
    });

    // ... other middleware ...

    app.UseSignalR(routes =>
    {
        routes.MapHub<ChatHub>("/chathub");
    });

    // ... other middleware ...
}

Omezení původu protokolu WebSocket

Ochrany, které poskytuje CORS, se nevztahují na objekty WebSockets. Pro omezení původu u WebSockets si přečtěte omezení původu WebSockets.

Ochrany, které poskytuje CORS, se nevztahují na objekty WebSockets. Prohlížeče neobsahují:

  • Provádění požadavků CORS v řádu CORS
  • Respektujte omezení zadaná v Access-Control hlavičkách při vytváření požadavků protokolu WebSocket.

Prohlížeče ale Origin při vydávání požadavků protokolu WebSocket odesílají hlavičku. Aplikace by měly být nakonfigurovány pro ověření těchto hlaviček, aby bylo zajištěno, že budou povoleny pouze objekty WebSockets přicházející z očekávaných zdrojů.

v ASP.NET Core 2,1 a novějších lze ověření hlaviček dosáhnout pomocí vlastního middleware, který je umístěn před UseSignalR a middleware ověřování v Configure :


// In Startup, add a static field listing the allowed Origin values:
private static readonly HashSet<string> _allowedOrigins = new HashSet<string>()
{
    // Add allowed origins here. For example:
    "https://www.mysite.com",
    "https://mysite.com",
};

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // ... other middleware ...

    // Validate Origin header on WebSocket requests to prevent unexpected cross-site 
    // WebSocket requests.
    app.Use((context, next) =>
    {
        // Check for a WebSocket request.
        if (string.Equals(context.Request.Headers["Upgrade"], "websocket"))
        {
            var origin = context.Request.Headers["Origin"];

            // If there is an origin header, and the origin header doesn't match 
            // an allowed value:
            if (!string.IsNullOrEmpty(origin) && !_allowedOrigins.Contains(origin))
            {
                // The origin is not allowed, reject the request
                context.Response.StatusCode = (int) HttpStatusCode.Forbidden;
                return Task.CompletedTask;
            }
        }

        // The request is a valid Origin or not a WebSocket request, so continue.
        return next();
    });

    // ... other middleware ...

    app.UseSignalR(routes =>
    {
        routes.MapHub<ChatHub>("/chathub");
    });

    // ... other middleware ...
}

Poznámka

OriginZáhlaví řídí klient a, podobně jako Referer záhlaví, může být falešným. Tato záhlaví by se neměla používat jako ověřovací mechanismus.

ConnectionId

ConnectionIdpokud SignalR je verze serveru nebo klienta ASP.NET Core 2,2 nebo starší, může vystavení způsobit škodlivou zosobnění. pokud je SignalR verze serveru a klienta ASP.NET Core 3,0 nebo novější, ConnectionToken ConnectionId musí být místo toho zachovaná tajná. ConnectionTokenNezveřejňuje se v žádném rozhraní API. může být obtížné zajistit, aby se starší SignalR klienti nepřipojovali k serveru, takže i v případě SignalR , že je vaše verze serveru ASP.NET Core 3,0 nebo novější, ConnectionId neměl by být vystavený.

Protokolování přístupového tokenu

Při použití protokolu WebSockets nebo Server-Sentch událostí klient prohlížeče pošle přístupový token do řetězce dotazu. Získání přístupového tokenu prostřednictvím řetězce dotazu je obecně bezpečné jako použití standardního Authorization záhlaví. K zajištění zabezpečeného koncového připojení mezi klientem a serverem vždy použijte protokol HTTPS. Mnohé webové servery protokolují adresu URL pro každý požadavek včetně řetězce dotazu. Protokolování adres URL může protokolovat přístupový token. ASP.NET Core zaznamená adresu URL pro každý požadavek ve výchozím nastavení, což bude obsahovat řetězec dotazu. Například:

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/chathub?access_token=1234

Pokud máte obavy týkající se protokolování těchto dat do protokolů serveru, můžete toto protokolování zcela zakázat nakonfigurováním Microsoft.AspNetCore.Hosting protokolovacího nástroje na Warning úroveň nebo výše (tyto zprávy jsou zapsány na Info úrovni). Další informace najdete v tématu použití pravidel filtru protokolu v kódu pro další informace. Pokud přesto chcete protokolovat určité informace o žádostech, můžete napsat middleware pro protokolování dat, která požadujete, a odfiltrovat access_token hodnotu řetězce dotazu (Pokud je k dispozici).

Výjimky

Zprávy výjimek se obecně považují za citlivá data, která by neměla být odhalena klientovi. Ve výchozím nastavení SignalR neodesílají podrobnosti o výjimce vyvolané metodou centra klientovi. Místo toho klient obdrží obecnou zprávu oznamující, že došlo k chybě. Doručení zprávy výjimky klientovi lze přepsat (například při vývoji nebo testování) pomocí EnableDetailedErrors. Zprávy výjimek by neměly být vystaveny klientovi v produkčních aplikacích.

Správa vyrovnávací paměti

SignalR pro správu příchozích a odchozích zpráv používá vyrovnávací paměti pro připojení. Ve výchozím nastavení SignalR omezuje tyto vyrovnávací paměti na 32 KB. Největší zpráva, kterou může klient nebo server odeslat, je 32 KB. Maximální velikost paměti spotřebované připojením pro zprávy je 32 KB. Pokud jsou vaše zprávy vždycky menší než 32 KB, můžete omezit limit, který:

  • Zabraňuje klientovi, aby mohl odeslat větší zprávu.
  • Server nikdy nebude muset přidělit velké vyrovnávací paměti pro příjem zpráv.

Pokud jsou vaše zprávy větší než 32 KB, můžete tento limit zvýšit. Zvýšení tohoto limitu znamená:

  • Klient může způsobit přidělení rozsáhlých vyrovnávacích pamětí pro server.
  • Přidělení serveru pro velké vyrovnávací paměti může snížit počet souběžných připojení.

U příchozích a odchozích zpráv platí omezení, jak je možné nakonfigurovat u objektu HttpConnectionDispatcherOptions nakonfigurovaného v nástroji MapHub :

  • ApplicationMaxBufferSize představuje maximální počet bajtů od klienta, které jsou vyrovnávací paměti serveru. Pokud se klient pokusí odeslat zprávu větší, než je toto omezení, připojení může být zavřeno.
  • TransportMaxBufferSize představuje maximální počet bajtů, které může server odeslat. Pokud se server pokusí odeslat zprávu (včetně návratových hodnot z metod z rozbočovače) větší, než je tento limit, bude vyvolána výjimka.

Nastavením limitu 0 zakážete tento limit. Odebráním tohoto limitu můžete klientovi poslat zprávu libovolné velikosti. Zlomyslní klienti odesílající velké zprávy můžou způsobit přidělení nadměrné paměti. Nadměrné využití paměti může významně snížit počet souběžných připojení.