Dela via


Vägledning för att mildra hot för ASP.NET Core Blazor dynamisk återgivning på servern

Not

Det här är inte den senaste versionen av den här artikeln. För den nuvarande utgåvan, se den .NET 9-versionen av den här artikeln.

Varning

Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i .NET och .NET Core Support Policy. Den aktuella versionen kan ses i .NET 9-versionen av den här artikeln.

Viktig

Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.

För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln.

Den här artikeln förklarar hur du minimerar säkerhetshot vid användning av interaktiva Blazori en serversidomiljö.

Appar antar en tillståndskänslig databehandlingsmodell, där servern och klienten upprätthåller en långvarig relation. Det beständiga tillståndet underhålls av en krets, som kan sträcka sig över anslutningar som också är potentiellt långlivade.

När en användare besöker en plats skapar servern en krets i serverns minne. Kretsen anger för webbläsaren vilket innehåll som ska återges och svarar på händelser, till exempel när användaren väljer en knapp i användargränssnittet. För att utföra dessa åtgärder anropar en krets JavaScript-funktioner i användarens webbläsare och .NET-metoder på servern. Den här tvåvägs JavaScript-baserade interaktionen kallas JavaScript-interop (JS interop).

Eftersom JS interop sker via Internet och klienten använder en fjärrwebbläsare delar appar de flesta säkerhetsproblem för webbappar. Det här avsnittet beskriver vanliga hot mot Blazor appar på serversidan och ger vägledning om hotreducering som fokuserar på Internetuppkopplade appar.

I begränsade miljöer, till exempel i företagsnätverk eller intranät, kan vissa av riktlinjerna för riskminimering antingen:

  • Gäller inte i den begränsade miljön.
  • Det är inte värt kostnaden att implementera eftersom säkerhetsrisken är låg i en begränsad miljö.

Interaktiva serverkomponenter med WebSocket-komprimering aktiverat

Komprimering kan utsätta appen för sidokanalattacker mot TLS-krypteringen för anslutningen, till exempel CRIME- och BREACH-attacker. Dessa typer av attacker kräver att cyberattackern:

  • Tvinga en webbläsare att utfärda begäranden med en nyttolast som en cyberattackare kontrollerar till en sårbar webbplats genom att skicka formulär mellan webbplatser eller genom att bädda in webbplatsen i en iframe från en annan sida.
  • Observera längden på det komprimerade och krypterade svaret över nätverket.

För att appen ska vara sårbar måste den återspegla nyttolasten från cyberattackern i svaret, till exempel genom att skriva ut sökvägen eller frågesträngen i svaret. Med hjälp av svarslängden kan cyberattackeraren "gissa" all information om svaret och kringgå anslutningens kryptering.

I allmänhet kan Blazor appar aktivera komprimering via WebSocket-anslutningen med lämpliga säkerhetsåtgärder:

  • Appen kan vara sårbar när den tar innehåll från begäran (till exempel sökvägen eller frågesträngen) som kan påverkas av en cyberattacker och återskapar den i HTML-koden på sidan eller på annat sätt gör den till en del av svaret.

  • Blazor tillämpar följande säkerhetsåtgärder automatiskt:

    • När komprimering har konfigurerats blockerar Blazor automatiskt inbäddning av appen i en iframe, vilket blockerar det första (okomprimerade) svaret från servern från rendering och förhindrar att WebSocket-anslutningen någonsin startar.

    • Begränsningen för att bädda in appen i en iframe kan vara avslappnad. Att lätta på begränsningen gör dock att appen kan attackeras om inbäddningsdokumentet komprometteras via en sårbarhet för skript mellan webbplatser, eftersom det ger cyberattackern ett sätt att utföra attacken.

  • Normalt för att den här typen av angrepp ska äga rum måste appen upprepade gånger återskapa innehållet i svaren så att cyberattackern kan gissa svaret. Med tanke på hur Blazor renderas (det renderas en gång och sedan endast producerar diff av innehållet för de element som har ändrats) är detta svårt för en cyberattacker att utföra. Det är dock inte omöjligt för en cyberattacker, så man måste vara noga med att undvika att återge känslig information tillsammans med extern information som kan manipuleras av en cyberattacker. Några exempel på detta är:

    • Rendera personligt identifierbar information (PII) på sidan samtidigt som du renderar databasinformation som lagts till av en annan användare.

    • Visa PII-information på sidan samtidigt som data från en annan användare via JS interop eller en lokal singleton-tjänst på servern.

I allmänhet rekommenderar vi att du undviker att återge komponenter som innehåller känslig information tillsammans med komponenter som kan återge data från ej betrodda källor som en del av samma renderingsbatch. Ej betrodda källor omfattar routningsparametrar, frågesträngar, data från JS interop och alla andra datakällor som en användare från tredje part kan kontrollera (databaser, externa tjänster).

Delat tillstånd

Blazor appar på serversidan lever i serverminnet och flera appsessioner hanteras i samma process. För varje appsession startar Blazor en krets med ett eget omfång för beroendeinjektionscontainer, vilket innebär att avgränsade tjänster är unika för varje Blazor-session.

Varning

Vi rekommenderar inte att appar på samma server delar tillstånd med hjälp av singleton-tjänster om inte extrem försiktighet vidtas, eftersom detta kan medföra säkerhetsrisker, till exempel att läcka användartillstånd mellan kretsar.

Du kan använda stateful singleton-tjänster i Blazor-appar om de är särskilt utformade för det. Användning av en singleton-minnescache är till exempel acceptabel eftersom en minnescache kräver en nyckel för att få åtkomst till en viss post. Förutsatt att användarna inte har kontroll över de cachenycklar som används med cacheminnet läcker inte tillstånd som lagras i cacheminnet över kretsar.

Allmän vägledning om tillståndshantering finns i ASP.NET Core Blazor state management.

IHttpContextAccessor / HttpContext i Razor komponenter

IHttpContextAccessor måste undvikas med interaktiv återgivning eftersom det inte finns någon giltig HttpContext tillgänglig.

IHttpContextAccessor kan användas för komponenter som återges statiskt på servern. Vi rekommenderar dock att du undviker det om det är möjligt.

HttpContext kan användas som en kaskaderande parameter endast i statiskt renderade rotkomponenter för allmänna uppgifter, till exempel att inspektera och ändra rubriker eller andra egenskaper i komponenten App (Components/App.razor). Värdet är alltid null för interaktiv återgivning.

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

För scenarier där HttpContext krävs i interaktiva komponenter rekommenderar vi att du överför data via beständiga komponenttillstånd från servern. Mer information finns i ASP.NET Core-serversidan och Blazor Web App ytterligare säkerhetsscenarier.

Använd inte IHttpContextAccessor/HttpContext direkt eller indirekt i de Razor komponenterna i Blazor appar på serversidan. Blazor appar körs utanför ASP.NET Core-pipelinekontexten. Den HttpContext garanteras inte vara tillgänglig inom IHttpContextAccessoroch HttpContext garanteras inte ha kontexten som startade Blazor-appen.

Den rekommenderade metoden för att skicka begärandetillståndet till Blazor-appen är genom rotkomponentparametrar under appens initiala rendering. Alternativt kan appen kopiera data till en begränsad tjänst i rotkomponentens initieringslivscykelhändelse för användning i hela appen. Mer information finns i ASP.NET Core-serversidan och Blazor Web App ytterligare säkerhetsscenarier.

En kritisk aspekt av Blazor-säkerhet på serversidan är att användaren som är ansluten till en specifik krets kan komma att uppdateras någon gång efter att Blazor-kretsen har upprättats, men IHttpContextAccessorinte uppdateras. Mer information om hur du hanterar den här situationen med anpassade tjänster finns i ASP.NET Core-serversidan och Blazor Web App ytterligare säkerhetsscenarier.

Resursöverbelastning

Resursöverbelastning kan uppstå när en klient interagerar med servern och gör att servern förbrukar för stora resurser. Överdriven resursförbrukning påverkar främst:

DoS-attacker (Denial of Service) försöker vanligtvis uttömma en app eller serverns resurser. Resursöverbelastning är dock inte nödvändigtvis resultatet av ett angrepp på systemet. Till exempel kan begränsade resurser förbrukas på grund av hög användarefterfrågan. DoS beskrivs ytterligare i avsnittet DoS.

Resurser utanför det Blazor ramverket, till exempel databaser och filhandtag (används för att läsa och skriva filer), kan också uppleva resursöverbelastning. Mer information finns i ASP.NET Core Best Practices.

PROCESSOR

CPU-överbelastning kan uppstå när en eller flera klienter tvingar servern att utföra intensivt CPU-arbete.

Anta till exempel en app som beräknar ett Fibonacci-nummer. Ett Fibonnacci-tal produceras från en Fibonnacci-sekvens, där varje tal i sekvensen är summan av de två föregående talen. Hur mycket arbete som krävs för att nå svaret beror på sekvensens längd och storleken på det ursprungliga värdet. Om appen inte begränsar en klients begäran kan processorintensiva beräkningar dominera cpu-tiden och minska prestandan för andra uppgifter. Överdriven resursförbrukning är ett säkerhetsproblem som påverkar tillgängligheten.

CPU-överbelastning är ett problem för alla offentliga appar. I vanliga webbappar löper begäranden och anslutningar ut som en skyddsåtgärd, men Blazor-appar ger inte samma skyddsåtgärder. Blazor appar måste innehålla lämpliga kontroller och gränser innan de utför potentiellt processorintensivt arbete.

Minne

Minnesöverbelastning kan uppstå när en eller flera klienter tvingar servern att förbruka en stor mängd minne.

Du kan till exempel överväga en app med en komponent som accepterar och visar en lista med objekt. Om den Blazor appen inte begränsar antalet objekt som tillåts eller antalet objekt som återges tillbaka till klienten kan den minnesintensiva bearbetningen och återgivningen dominera serverns minne till den punkt där serverns prestanda är lidande. Servern kan krascha eller vara långsam så att den verkar ha kraschat.

Överväg följande scenario för att underhålla och visa en lista över objekt som gäller ett potentiellt minnesöverbelastningsscenario på servern:

  • Objekten i en List<T>-egenskap eller fält använder serverns minne. Om appen tillåter att listan över objekt växer obundet finns det en risk att servern får slut på minne. Slut på minne gör att den aktuella sessionen slutar (kraschar) och alla samtidiga sessioner i den serverinstansen får ett undantag som inte är minnesinternt. För att förhindra att det här scenariot inträffar måste appen använda en datastruktur som medför en objektgräns för samtidiga användare.
  • Om ett sidindelningsschema inte används för återgivning, använder servern ytterligare minne för objekt som inte syns i användargränssnittet. Utan en gräns för antalet objekt kan minnesbehoven uttömma det tillgängliga serverminnet. Använd någon av följande metoder för att förhindra det här scenariot:
    • Använd sidnumrerade listor vid återgivning.
    • Visa endast de första 100 till 1 000 objekten och kräva att användaren anger sökvillkor för att hitta objekt utöver de objekt som visas.
    • För ett mer avancerat renderingsscenario implementerar du listor eller rutnät som stöder virtualisering. Med virtualisering renderar listor endast en delmängd av objekt som för närvarande är synliga för användaren. När användaren interagerar med rullningslisten i användargränssnittet återger komponenten endast de objekt som krävs för visning. Objekt som för närvarande inte krävs för visning kan lagras i sekundär lagring, vilket är den idealiska metoden. Objekt som inte visas kan också lagras i minnet, vilket är mindre idealiskt.

Not

Blazor har inbyggt stöd för virtualisering. Mer information finns i ASP.NET Core Razor-komponentvirtualisering.

Blazor appar erbjuder en liknande programmeringsmodell som andra gränssnittsramverk för tillståndskänsliga appar, till exempel WPF, Windows Forms eller Blazor WebAssembly. Den största skillnaden är att i flera av användargränssnittsramverken tillhör minnet som förbrukas av appen klienten och endast påverkar den enskilda klienten. Till exempel körs en Blazor WebAssembly-app helt på klienten och använder endast klientminnesresurser. För en Blazor app på serversidan tillhör det minne som förbrukas av appen servern och delas mellan klienter på serverinstansen.

Minneskrav på serversidan är ett övervägande för alla Blazor appar på serversidan. De flesta webbappar är dock tillståndslösa och det minne som används vid bearbetning av en begäran släpps när svaret returneras. Som en allmän rekommendation tillåter du inte klienter att allokera en obunden mängd minne som i andra appar på serversidan som bevarar klientanslutningar. Minnet som förbrukas av en Blazor app på serversidan bevaras under en längre tid än en enskild begäran.

Not

Under utvecklingen kan en profilerare användas eller en spårning som samlas in för att utvärdera minnesbehov för klienter. En profilerare eller spårning samlar inte in det minne som allokerats till en specifik klient. Om du vill samla in minnesanvändningen för en specifik klient under utvecklingen samlar du in en dump och undersöker minnesbehovet för alla objekt som är rotade i en användares krets.

Klientanslutningar

Anslutningsöverbelastning kan uppstå när en eller flera klienter öppnar för många samtidiga anslutningar till servern, vilket hindrar andra klienter från att upprätta nya anslutningar.

Blazor klienter upprättar en enda anslutning per session och håller anslutningen öppen så länge webbläsarfönstret är öppet. Med tanke på anslutningarnas beständiga karaktär och den tillståndskänsliga karaktären hos Blazor appar på serversidan är anslutningsöverbelastning en större risk för appens tillgänglighet.

Det finns ingen gräns för antalet anslutningar per användare för en app. Om appen kräver en anslutningsgräns använder du en eller flera av följande metoder:

  • Kräv autentisering, vilket naturligtvis begränsar möjligheten för obehöriga användare att ansluta till appen. För att det här scenariot ska vara effektivt måste användarna hindras från att etablera nya användare på begäran.
  • Begränsa antalet anslutningar per användare. Du kan begränsa anslutningar via följande metoder. Var noga med att tillåta legitima användare att komma åt appen (till exempel när en anslutningsgräns upprättas baserat på klientens IP-adress).
  • Kräv autentisering, vilket naturligtvis begränsar möjligheten för obehöriga användare att ansluta till appen. För att det här scenariot ska vara effektivt måste användarna hindras från att etablera nya användare på begäran.
  • Begränsa antalet anslutningar per användare. Du kan begränsa anslutningar via följande metoder. Var noga med att tillåta legitima användare att komma åt appen (till exempel när en anslutningsgräns upprättas baserat på klientens IP-adress).
    • Programnivå
      • Utökningsbarhet för slutpunktsroutning.
      • Kräv autentisering för att ansluta till appen och hålla reda på de aktiva sessionerna per användare.
      • Avvisa nya sessioner när du når en gräns.
      • WebSocket-proxyanslutningar till en app med hjälp av en proxy, till exempel Azure SignalR Service som multiplexerar anslutningar från klienter till en app. Detta ger en app större anslutningskapacitet än vad en enskild klient kan upprätta, vilket hindrar en klient från att uttömma anslutningarna till servern.
    • Servernivå

DoS-attacker (tjänsteavbrott)

DoS-attacker (Denial of Service) innebära att en klient gör att servern avtömmer en eller flera av sina resurser, vilket gör appen otillgänglig. Blazor appar innehåller standardgränser och förlitar sig på andra ASP.NET Core- och SignalR-gränser som är inställda på CircuitOptions för att skydda mot DoS-attacker:

Mer information och exempel på konfigurationskodning finns i följande artiklar:

Interaktioner med webbläsaren (klienten)

En klient interagerar med servern genom JS interop-händelsedispatch och renderingsavslut. JS interop-kommunikation går åt båda hållen mellan JavaScript och .NET:

  • Webbläsarhändelser skickas från klienten till servern på ett asynkront sätt.
  • Servern svarar asynkront och återställer användargränssnittet efter behov.

JavaScript-funktioner som anropas från .NET

För anrop från .NET-metoder till JavaScript:

  • Alla anrop har en konfigurerbar tidsgräns efter vilken de misslyckas och returnerar en OperationCanceledException till anroparen.
  • Det går inte att lita på resultatet av ett JavaScript-anrop. Den Blazor appklient som körs i webbläsaren söker efter JavaScript-funktionen som ska anropas. Funktionen anropas och antingen genereras resultatet eller ett fel. En skadlig klient kan försöka:
    • Orsaka ett problem i appen genom att returnera ett fel från JavaScript-funktionen.
    • Inducera ett oavsiktligt beteende på servern genom att returnera ett oväntat resultat från JavaScript-funktionen.

Vidta följande försiktighetsåtgärder för att skydda mot föregående scenarier:

  • Inneslut JS interop-anrop i try-catch-instruktioner för att ta hänsyn till fel som kan uppstå under anropen. Mer information finns i Hantera fel i ASP.NET Core Blazor-appar.
  • Verifiera data som returneras från JS interop-anrop, inklusive felmeddelanden, innan du vidtar några åtgärder.

.NET-metoder som anropas från webbläsaren

Lita inte på anrop från JavaScript till .NET-metoder. När en .NET-metod exponeras för JavaScript bör du överväga hur .NET-metoden anropas:

  • Behandla alla .NET-metoder som exponeras för JavaScript som en offentlig slutpunkt för appen.
    • Verifiera indata.
      • Kontrollera att värdena ligger inom förväntade intervall.
      • Kontrollera att användaren har behörighet att utföra den begärda åtgärden.
    • Allokera inte en alltför stor mängd resurser som en del av .NET-metodens anrop. Du kan till exempel utföra kontroller och placera gränser för processor- och minnesanvändning.
    • Ta hänsyn till att statiska metoder och instansmetoder kan exponeras för JavaScript-klienter. Undvik delningstillstånd mellan sessioner om inte designen kräver delningstillstånd med lämpliga begränsningar.
      • För instansmetoder som exponeras via DotNetObjectReference objekt som ursprungligen skapades via beroendeinmatning (DI) bör objekten registreras som begränsade objekt. Detta gäller alla DI-tjänster som appen använder.
      • För statiska metoder bör du undvika att upprätta tillstånd som inte kan begränsas till klienten om inte appen uttryckligen delar tillstånd efter design för alla användare på en serverinstans.
    • Undvik att skicka användarangivna data i parametrar till JavaScript-anrop. Om det är absolut nödvändigt att skicka data i parametrar kontrollerar du att JavaScript-koden hanterar överföring av data utan att införa XSS(Cross-site scripting) säkerhetsrisker. Skriv till exempel inte användarspecifika data till DOM genom att ange egenskapen innerHTML för ett element. Överväg att använda INNEHÅLLSsäkerhetsprincip (CSP) för att inaktivera eval och andra osäkra JavaScript-primitiver. Mer information finns i Framtvinga en innehållssäkerhetsprincip för ASP.NET Core Blazor.
  • Undvik att implementera anpassad sändning av .NET-anrop ovanpå ramverkets distributionsimplementering. Att exponera .NET-metoder i webbläsaren är ett avancerat scenario som inte rekommenderas för allmän Blazor utveckling.

Evenemang

Händelser ger en startpunkt till en app. Samma regler för att skydda slutpunkter i webbappar gäller för händelsehantering i Blazor appar. En skadlig klient kan skicka alla data som den vill skicka som nyttolast för en händelse.

Till exempel:

  • En ändringshändelse för en <select> kan skicka ett värde som inte ingår i de alternativ som appen presenterade för klienten.
  • En <input> kan skicka textdata till servern och kringgå verifiering på klientsidan.

Appen måste verifiera data för alla händelser som appen hanterar. Det Blazor ramverket forms-komponenter utför grundläggande valideringar. Om appen använder anpassade formulärkomponenter måste anpassad kod skrivas för att verifiera händelsedata efter behov.

Händelser är asynkrona, så flera händelser kan skickas till servern innan appen har tid att reagera genom att skapa en ny återgivning. Detta har vissa säkerhetskonsekvenser att tänka på. Begränsning av klientåtgärder i appen måste utföras i händelsehanterare och inte vara beroende av det aktuella återgivna visningstillståndet.

Överväg en räknarkomponent som ska göra det möjligt för en användare att öka en räknare högst tre gånger. Knappen för att öka räknaren baseras villkorligt på värdet för count:

<p>Count: @count</p>

@if (count < 3)
{
    <button @onclick="IncrementCount" value="Increment count" />
}

@code 
{
    private int count = 0;

    private void IncrementCount()
    {
        count++;
    }
}

En klient kan skicka en eller flera inkrementshändelser innan ramverket skapar en ny återgivning av den här komponenten. Resultatet är att count kan ökas över tre gånger av användaren eftersom knappen inte tas bort av användargränssnittet tillräckligt snabbt. Rätt sätt att uppnå gränsen på tre count steg visas i följande exempel:

<p>Count: @count</p>

@if (count < 3)
{
    <button @onclick="IncrementCount" value="Increment count" />
}

@code 
{
    private int count = 0;

    private void IncrementCount()
    {
        if (count < 3)
        {
            count++;
        }
    }
}

Genom att lägga till if (count < 3) { ... } kontroll i hanteraren baseras beslutet att öka count på det aktuella apptillståndet. Beslutet baseras inte på användargränssnittets tillstånd som det var i föregående exempel, som kan vara tillfälligt inaktuellt.

Skydda mot flera sändningar

Om en händelseåteranrop anropar en tidskrävande åtgärd asynkront, till exempel att hämta data från en extern tjänst eller databas, bör du överväga att använda ett skydd. Skyddet kan hindra användaren från att köa flera åtgärder medan åtgärden pågår, genom att ge visuell feedback. Följande komponentkoduppsättning sätter isLoading till true när DataService.GetDataAsync förvärvar data från servern. När isLoading är trueinaktiveras knappen i användargränssnittet:

<button disabled="@isLoading" @onclick="UpdateData">Update</button>

@code {
    private bool isLoading;
    private Data[] data = Array.Empty<Data>();

    private async Task UpdateData()
    {
        if (!isLoading)
        {
            isLoading = true;
            data = await DataService.GetDataAsync(DateTime.Now);
            isLoading = false;
        }
    }
}

Skyddsmönstret som visas i föregående exempel fungerar om bakgrundsåtgärden körs asynkront med async-await-mönstret.

Avbryt tidigt och undvik användning efter bortskaffande

Utöver att använda ett skydd enligt beskrivningen i avsnittet Skydda mot flera sändningar kan du överväga att använda en CancellationToken för att avbryta långvariga åtgärder när komponenten tas bort. Den här metoden har den extra fördelen att undvika användning efter bortskaffande i komponenter:

@implements IDisposable

...

@code {
    private readonly CancellationTokenSource TokenSource = 
        new CancellationTokenSource();

    private async Task UpdateData()
    {
        ...

        data = await DataService.GetDataAsync(DateTime.Now, TokenSource.Token);

        if (TokenSource.Token.IsCancellationRequested)
        {
           return;
        }

        ...
    }

    public void Dispose()
    {
        TokenSource.Cancel();
    }
}

Undvik händelser som producerar stora mängder data

Vissa DOM-händelser, till exempel oninput eller onscroll, kan generera en stor mängd data. Undvik att använda dessa händelser på serversidan Blazor server.

Ytterligare säkerhetsvägledning

Vägledningen för att skydda ASP.NET Core-appar gäller för Blazor appar på serversidan och beskrivs i följande avsnitt i den här artikeln:

Loggning och känsliga data

JS interop-interaktioner mellan klienten och servern registreras i serverns loggar med ILogger instanser. Blazor undviker loggning av känslig information, till exempel faktiska händelser eller JS interop-indata och utdata.

När ett fel inträffar på servern meddelar ramverket klienten och river ned sessionen. Klienten får ett allmänt felmeddelande som kan visas i webbläsarens utvecklarverktyg.

Felet på klientsidan innehåller inte anropsstacken och ger ingen information om orsaken till felet, men serverloggarna innehåller sådan information. I utvecklingssyfte kan känslig felinformation göras tillgänglig för klienten genom att aktivera detaljerade fel.

Varning

Att exponera felinformation för klienter på Internet är en säkerhetsrisk som alltid bör undvikas.

Skydda information under överföring med HTTPS

Blazor använder SignalR för kommunikation mellan klienten och servern. Blazor använder normalt transporten som SignalR förhandlar om, vilket vanligtvis är WebSockets.

Blazor säkerställer inte integriteten och konfidentialiteten för de data som skickas mellan servern och klienten. Använd alltid HTTPS.

Skript mellan webbplatser (XSS)

Med XSS (Cross-Site Scripting) kan en obehörig part köra godtycklig logik i webbläsarens kontext. En komprometterad app kan potentiellt köra godtycklig kod på klienten. Säkerhetsrisken kan användas för att potentiellt utföra ett antal skadliga åtgärder mot servern:

  • Skicka falska/ogiltiga händelser till servern.
  • Misslyckad distribution/ogiltiga renderingsfärdigställanden.
  • Undvik att skicka renderingskompletteringar.
  • Skicka interop-anrop från JavaScript till .NET.
  • Ändra svaret för interop-anrop från .NET till JavaScript.
  • Undvik att anropa .NET till JS interop-resultat.

Det Blazor ramverket vidtar åtgärder för att skydda mot några av de föregående hoten:

  • Slutar producera nya uppdateringar av användargränssnittet om klienten inte bekräftar återgivningsbatcherna. Konfigurerad med CircuitOptions.MaxBufferedUnacknowledgedRenderBatches.
  • Avbryter ett .NET-till-JavaScript- anrop efter en minut om inget svar mottas från klienten. Konfigurerad med CircuitOptions.JSInteropDefaultCallTimeout.
  • Utför grundläggande validering på alla indata som kommer från webbläsaren under JS interop:
    • .NET-referenser är giltiga och av den typ som förväntas av .NET-metoden.
    • Data är inte felaktigt formaterad.
    • Rätt antal argument för metoden finns i nyttolasten.
    • Argumenten eller resultatet kan deserialiseras korrekt innan metoden anropas.
  • Utför grundläggande validering i alla indata som kommer från webbläsaren från skickade händelser:
    • Händelsen har en giltig typ.
    • Data för händelsen kan deserialiseras.
    • Det finns en händelsehanterare som är associerad med händelsen.

Förutom de skyddsåtgärder som ramverket implementerar måste appen kodas av utvecklaren för att skydda mot hot och vidta lämpliga åtgärder:

  • Verifiera alltid data vid hantering av händelser.
  • Vidta lämpliga åtgärder när du tar emot ogiltiga data:
    • Ignorera datan och returnera. Detta gör att appen kan fortsätta bearbeta begäranden.
    • Om appen fastställer att indata är olagliga och inte kunde skapas av en legitim klient utlöser du ett undantag. Kastar ett undantag som bryter kretsen och avslutar sessionen.
  • Lita inte på felmeddelandet som tillhandahålls av återgivningen av batchavslut som ingår i loggarna. Felet är som tillhandahålls av klienten och kan vanligtvis inte vara betrodd eftersom klienten kan komprometteras.
  • Lita inte på ingående data i JS interop-anrop i någon riktning mellan JavaScript- och .NET-metoder.
  • Appen ansvarar för att verifiera att innehållet i argument och resultat är giltigt, även om argumenten eller resultaten är korrekt deserialiserade.

För att en XSS-säkerhetsrisk ska finnas måste appen innehålla användarindata på den renderade sidan. Blazor kör ett kompileringssteg där markering i en .razor fil omvandlas till procedurmässig C#-logik. När programmet körs bygger C#-logiken en renderingsstruktur som beskriver element, text och barnkomponenter. Detta tillämpas på webbläsarens DOM via en sekvens med JavaScript-instruktioner (eller serialiseras till HTML i händelse av prerendering):

  • Användarindata som återges via normal Razor syntax (till exempel @someStringValue) exponerar inte en XSS-sårbarhet eftersom Razor syntax läggs till i DOM via kommandon som bara kan skriva text. Även om värdet innehåller HTML-kod visas värdet som statisk text. Vid prerendering är utdata HTML-kodade, vilket också visar innehållet som statisk text.
  • Komponentförfattare kan skapa komponenter i C# utan att använda Razor. Komponentförfattaren ansvarar för att använda rätt API:er när utdata genereras. Använd till exempel builder.AddContent(0, someUserSuppliedString) och intebuilder.AddMarkupContent(0, someUserSuppliedString)eftersom det senare kan skapa en XSS-säkerhetsrisk.
  • Användarindata som återges via normal Razor syntax (till exempel @someStringValue) exponerar inte en XSS-sårbarhet eftersom Razor syntax läggs till i DOM via kommandon som bara kan skriva text. Även om värdet innehåller HTML-kod visas värdet som statisk text. Vid prerendering är utdata HTML-kodade, vilket också visar innehållet som statisk text.
  • Skripttaggar tillåts inte och bör inte ingå i appens komponentåtergivningsträd. Om en skripttagg ingår i en komponents markering genereras ett kompileringsfel.
  • Komponentförfattare kan skapa komponenter i C# utan att använda Razor. Komponentförfattaren ansvarar för att använda rätt API:er när utdata genereras. Använd till exempel builder.AddContent(0, someUserSuppliedString) och intebuilder.AddMarkupContent(0, someUserSuppliedString)eftersom det senare kan skapa en XSS-säkerhetsrisk.

Överväg att ytterligare minimera XSS-sårbarheter. Implementera till exempel en restriktiv innehållssäkerhetsprincip (CSP). Mer information finns i Framtvinga en innehållssäkerhetsprincip för ASP.NET Core Blazor.

Mer information finns i Prevent Cross-Site Scripting (XSS) i ASP.NET Core.

Skydd mot korsande ursprung

Attacker mellan ursprung omfattar en klient från ett annat ursprung som utför en åtgärd mot servern. Den skadliga åtgärden är vanligtvis en GET-begäran eller ett postformulär (förfalskning av begäranden mellan webbplatser, CSRF), men det är också möjligt att öppna en skadlig WebSocket. Blazor appar erbjuder samma garantier som andra SignalR appar som använder hubbprotokollerbjudandet:

  • Appar kan nås med korsande ursprung såvida inte ytterligare åtgärder vidtas för att förhindra det. Om du vill inaktivera åtkomst mellan ursprung inaktiverar du CORS i slutpunkten genom att lägga till CORS Middleware i pipelinen och lägga till DisableCorsAttribute i Blazor slutpunktsmetadata eller begränsa uppsättningen tillåtna ursprung genom att konfigurera SignalR för resursdelning mellan ursprung. Mer information om begränsningar för WebSocket-ursprung finns i WebSockets-stöd i ASP.NET Core.
  • Om CORS är aktiverat kan extra steg krävas för att skydda appen beroende på CORS-konfigurationen. Om CORS är globalt aktiverat kan CORS inaktiveras för BlazorSignalR-hubben genom att lägga till DisableCorsAttribute-metadata till slutpunktsmetadata efter att ha anropat MapBlazorHub på slutpunktsrutbyggaren.

Mer information finns i Förhindra XSRF-/CSRF-attacker (Cross-Site Request Forgery) i ASP.NET Core.

Klickkapning

Klicka-jacking innebär att återge en webbplats som en <iframe> inuti en webbplats från ett annat ursprung för att lura användaren att utföra åtgärder på den webbplats som attackeras.

För att skydda en app från att visas i en <iframe>, använd CSP (Content Security Policy) och X-Frame-Options-huvudet.

Mer information finns i följande resurser:

Öppna omdirigeringar

När en appsession startar utför servern grundläggande validering av url:erna som skickas som en del av starten av sessionen. Ramverket kontrollerar att bas-URL:en är överordnad den aktuella URL:en innan kretsen upprättas. Inga ytterligare kontroller utförs av ramverket.

När en användare väljer en länk på klienten skickas URL:en för länken till servern, vilket avgör vilken åtgärd som ska vidtas. Appen kan till exempel utföra en navigering på klientsidan eller ange för webbläsaren att gå till den nya platsen.

Komponenter kan också utlösa navigeringsbegäranden programmatiskt med hjälp av NavigationManager. I sådana scenarier kan appen utföra en navigering på klientsidan eller ange för webbläsaren att gå till den nya platsen.

Komponenter måste:

  • Undvik att använda användarindata som en del av argumenten för navigeringsanrop.
  • Verifiera argument för att säkerställa att målet tillåts av appen.

Annars kan en obehörig användare tvinga webbläsaren att gå till en cyberattackerkontrollerad webbplats. I det här scenariot lurar cyberangriparen appen att använda användarindata som en del av anropet av NavigationManager.NavigateTo-metoden.

Det här rådet gäller även när du återger länkar som en del av appen:

  • Använd om möjligt relativa länkar.
  • Kontrollera att absoluta länkmål är giltiga innan du inkluderar dem på en sida.

Mer information finns i Förhindra öppna omdirigeringsattacker i ASP.NET Core.

Säkerhetschecklista

Följande lista över säkerhetsöverväganden är inte omfattande:

  • Verifiera argument från händelser.
  • Verifiera indata och resultat från JS interop-anrop.
  • Undvik att använda (eller verifiera i förväg) användarindata vid .NET till JS interop-anrop.
  • Förhindra att klienten allokerar en obundet mängd minne.
  • Skydda mot flera sändningar.
  • Avbryt långvariga åtgärder när komponenten tas bort.
  • Undvik händelser som producerar stora mängder data.
  • Undvik att använda användarinput som en del av anrop till NavigationManager.NavigateTo. Om det inte går att undvika, validera användarinputens URL:er mot en uppsättning tillåtna ursprung först.
  • Fatta inte auktoriseringsbeslut baserat på användargränssnittets tillstånd, utan endast från komponenttillståndet.
  • Överväg att använda CSP(Content Security Policy) för att skydda mot XSS-attacker. Mer information finns i Framtvinga en innehållssäkerhetsprincip för ASP.NET Core Blazor.
  • Överväg att använda CSP och X-Frame-Options för att skydda mot klickkapning.
  • Se till att CORS-inställningarna är lämpliga när du aktiverar CORS eller uttryckligen inaktiverar CORS för Blazor appar.
  • Testa för att säkerställa att gränserna på serversidan för Blazor-appen ger en acceptabel användarupplevelse utan oacceptabla risknivåer.