Delen via


Richtlijnen voor bedreigingsbeperking voor ASP.NET Core Blazor interactieve rendering aan serverzijde

Notitie

Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikelvoor de huidige release.

Waarschuwing

Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie de .NET- en .NET Core-ondersteuningsbeleidvoor meer informatie. Zie de .NET 9-versie van dit artikelvoor de huidige release.

Belangrijk

Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.

Zie de .NET 9-versie van dit artikelvoor de huidige release.

In dit artikel wordt uitgelegd hoe beveiligingsrisico's beperkt kunnen worden in interactieve server-side Blazor.

Apps gebruiken een stateful gegevensverwerkingsmodel, waarbij de server en client een langdurige relatie onderhouden. De permanente status wordt onderhouden door een circuit, dat verbindingen kan omvatten die mogelijk ook een lange levensduur hebben.

Wanneer een gebruiker een site bezoekt, maakt de server een circuit in het geheugen van de server. Het circuit geeft aan in de browser welke inhoud moet worden weergegeven en reageert op gebeurtenissen, zoals wanneer de gebruiker een knop in de gebruikersinterface selecteert. Om deze acties uit te voeren, roept een circuit JavaScript-functies aan in de browser van de gebruiker en .NET-methoden op de server. Deze op JavaScript gebaseerde interactie in twee richtingen wordt JavaScript-interop (JS interop)genoemd.

Omdat JS interop plaatsvindt via internet en de client een externe browser gebruikt, delen apps de meeste beveiligingsproblemen voor web-apps. In dit onderwerp worden veelvoorkomende bedreigingen voor Blazor apps aan de serverzijde beschreven en worden richtlijnen voor het beperken van bedreigingen beschreven die gericht zijn op internetgerichte apps.

In beperkte omgevingen, zoals binnen bedrijfsnetwerken of intranetten, zijn enkele van de richtlijnen voor risicobeperking:

  • Is niet van toepassing in de beperkte omgeving.
  • Is de kosten die u moet implementeren niet waard omdat het beveiligingsrisico laag is in een beperkte omgeving.

Interactieve serveronderdelen waarvoor WebSocket-compressie is ingeschakeld

Compressie kan de app blootstellen aan side-channel-aanvallen op de TLS-versleuteling van de verbinding, zoals CRIME- en BREACH-aanvallen. Dergelijke typen aanvallen vereisen dat de cyberaanvaller:

  • Dwing een browser om verzoeken met een payload die de cyberaanvaller beheert naar een kwetsbare site te sturen via cross-site form posting of door de site in een iframe van een andere site te embedden.
  • Bekijk de lengte van het gecomprimeerde en versleutelde antwoord via het netwerk.

Voor de app kwetsbaar te zijn, moet deze de payload van de cyberaanvaller in de respons terugkaatsen, bijvoorbeeld door het pad of de querytekenreeks in de respons weer te geven. Met behulp van de lengte van het antwoord kan de cyberaanval alle informatie over het antwoord "raden", waardoor de versleuteling van de verbinding wordt overgeslagen.

Over het algemeen kunnen Blazor apps compressie via de WebSocket-verbinding inschakelen met de juiste beveiligingsmaatregelen:

  • De app kan kwetsbaar zijn wanneer er inhoud van de aanvraag wordt opgehaald (bijvoorbeeld het pad of de querytekenreeks) die kan worden beïnvloed door een cyberaanval en deze in de HTML van de pagina wordt gereproduceerd of anderszins deel uitmaakt van het antwoord.

  • Blazor past de volgende beveiligingsmaatregelen automatisch toe:

    • Wanneer compressie is geconfigureerd, blokkeert Blazor automatisch het insluiten van de app in een iframe, waardoor het eerste (niet-gecomprimeerde) antwoord van de server niet kan worden weergegeven en wordt voorkomen dat de WebSocket-verbinding ooit wordt gestart.

    • De beperking voor het insluiten van de app in een iframe kan worden versoepeld. Door de beperking te versoepelen, wordt de app echter blootgesteld aan aanvallen als het insluitdocument wordt aangetast via een kwetsbaarheid voor cross-site scripting, omdat dat de cyberaanvaller een manier biedt om de aanval uit te voeren.

  • Voor dit type aanval plaatsvindt, moet de app normaal gesproken de inhoud in de antwoorden herhaaldelijk reproduceren, zodat de cyber-aanvaller het antwoord kan raden. Gegeven hoe Blazor rendert (het rendert eenmaal en produceert vervolgens alleen veranderingen in de inhoud voor de elementen die zijn gewijzigd) is het moeilijk voor een cyberaanvaller om dit te bewerkstelligen. Het is echter niet onmogelijk voor een cyberaanval, dus zorg ervoor dat gevoelige informatie niet wordt weergegeven naast externe informatie die kan worden gemanipuleerd door een cyberaanval. Enkele voorbeelden hiervan zijn:

    • Geef PII- (Personally Identifiable Information) op de pagina op hetzelfde moment weer als het weergeven van databasegegevens die door een andere gebruiker zijn toegevoegd.

    • PII-informatie gelijktijdig met gegevens die afkomstig zijn van een andere gebruiker via JS-interoperabiliteit of een lokale singleton-service op de server op de pagina weergeven.

Over het algemeen raden we u aan om te voorkomen dat onderdelen worden weergegeven die gevoelige informatie bevatten naast onderdelen die gegevens uit niet-vertrouwde bronnen kunnen weergeven als onderdeel van dezelfde renderbatch. Niet-vertrouwde bronnen omvatten routeparameters, queryreeksen, gegevens uit JS interop en andere gegevensbronnen die een externe gebruiker kan beheren (databases, externe services).

Gedeelde staat

Server-side Blazor apps draaien in het servergeheugen en meerdere app-sessies worden gehost binnen hetzelfde proces. Voor elke app-sessie start Blazor een circuit met een eigen scope voor afhankelijkheidsinjectiecontainers, waardoor scoped services uniek zijn per Blazor sessie.

Waarschuwing

We raden het af om apps op dezelfde server de status te laten delen met behulp van singleton-services, tenzij er uiterste zorg wordt betracht, omdat dit beveiligingsproblemen kan veroorzaken, zoals het lekken van de gebruikersstatus over circuits heen.

U kunt stateful singletonservices gebruiken in Blazor-apps als ze er speciaal voor zijn ontworpen. Het gebruik van een singleton-geheugencache is bijvoorbeeld acceptabel omdat voor een geheugencache een sleutel is vereist voor toegang tot een bepaalde vermelding. Ervan uitgaande dat gebruikers geen controle hebben over de cachesleutels die worden gebruikt met de cache, lekt de status die is opgeslagen in de cache niet over circuits.

Zie ASP.NET Core Blazor state managementvoor algemene richtlijnen voor statusbeheer.

IHttpContextAccessor / HttpContext in Razor onderdelen

IHttpContextAccessor moet worden vermeden met interactieve rendering omdat er geen geldige HttpContext beschikbaar is.

IHttpContextAccessor kunnen worden gebruikt voor onderdelen die statisch worden weergegeven op de server. We raden u echter aan deze indien mogelijk te vermijden.

HttpContext kan worden gebruikt als een trapsgewijze parameter alleen in statisch gerenderde hoofdonderdelen voor algemene taken, zoals het inspecteren en wijzigen van headers of andere eigenschappen in het App onderdeel (Components/App.razor). De waarde wordt altijd null voor interactieve rendering.

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

Voor scenario's waarbij de HttpContext vereist is in interactieve onderdelen, raden we u aan om de gegevens via de status van een permanent onderdeel vanaf de server te laten stromen. Zie ASP.NET Core-serverzijde en Blazor Web App aanvullende beveiligingsscenario'svoor meer informatie.

Gebruik IHttpContextAccessor/HttpContext niet direct of indirect in de Razor onderdelen van Blazor-apps aan de serverzijde. Blazor apps worden uitgevoerd buiten de context van de ASP.NET Core-pijplijn. De HttpContext is niet gegarandeerd beschikbaar binnen de IHttpContextAccessor, en het is niet gegarandeerd dat HttpContext de context behoudt waarmee de Blazor-app is gestart.

De aanbevolen methode voor het doorgeven van de status van de aanvraag aan de Blazor-app is via de parameters van het hoofdonderdeel tijdens de eerste rendering van de app. De app kan de gegevens ook kopiëren naar een scoped service in de initialisatielevenscyclusgebeurtenis van het hoofdonderdeel voor gebruik in de app. Zie ASP.NET Core-serverzijde en Blazor Web App aanvullende beveiligingsscenario'svoor meer informatie.

Een essentieel aspect van Blazor beveiliging aan de serverzijde is dat de gebruiker die aan een bepaald circuit is gekoppeld, op een bepaald moment kan worden bijgewerkt nadat het Blazor circuit tot stand is gebracht, maar de IHttpContextAccessorniet wordt bijgewerkt. Zie ASP.NET Core-serverzijde en Blazor Web App aanvullende beveiligingsscenario'svoor meer informatie over het aanpakken van deze situatie met aangepaste services.

Uitputting van middelen

Resourceuitputting kan optreden wanneer een client communiceert met de server en ervoor zorgt dat de server overmatige resources verbruikt. Overmatig resourceverbruik is voornamelijk van invloed op:

DoS-aanvallen (Denial of Service) proberen meestal de resources van een app of server uit te putten. Resourceuitputting is echter niet noodzakelijkerwijs het resultaat van een aanval op het systeem. Eindige resources kunnen bijvoorbeeld worden uitgeput vanwege een hoge vraag naar gebruikers. DoS wordt verder behandeld in de DoS-sectie.

Resources buiten het Blazor framework, zoals databases en bestandsingangen (gebruikt voor het lezen en schrijven van bestanden), kunnen ook uitputting van resources ervaren. Zie ASP.NET Core Best Practicesvoor meer informatie.

CPU

CPU-uitputting kan optreden wanneer een of meer clients de server dwingen intensief CPU-werk uit te voeren.

Denk bijvoorbeeld aan een app waarmee een Fibonnacci-getal wordt berekend. Een Fibonnacci-getal wordt geproduceerd uit een Fibonnacci-reeks, waarbij elk getal in de reeks de som is van de twee voorgaande getallen. De hoeveelheid werk die nodig is om het antwoord te bereiken, is afhankelijk van de lengte van de reeks en de grootte van de initiële waarde. Als de app geen limieten voor de aanvraag van een client plaatst, kunnen de CPU-intensieve berekeningen de tijd van de CPU overheersten en de prestaties van andere taken verminderen. Overmatig resourceverbruik is een beveiligingsprobleem dat van invloed is op de beschikbaarheid.

CPU-uitputting is een probleem voor alle openbare apps. In normale web-apps treedt er een time-out op voor aanvragen en verbindingen als een beveiliging, maar Blazor apps bieden niet dezelfde beveiliging. Blazor apps moeten de juiste controles en limieten bevatten voordat mogelijk CPU-intensief werk wordt uitgevoerd.

Geheugen

Geheugenuitputting kan optreden wanneer een of meer clients afdwingen dat de server een grote hoeveelheid geheugen verbruikt.

Denk bijvoorbeeld aan een app met een onderdeel dat een lijst met items accepteert en weergeeft. Als de Blazor-app geen limieten plaatst voor het aantal toegestane items of het aantal items dat aan de client wordt weergegeven, kan de geheugenintensieve verwerking en rendering het geheugen van de server overheerst tot het punt waar de prestaties van de server lijden. De server kan vastlopen of zo langzaam worden dat het lijkt alsof hij is gecrasht.

Houd rekening met het volgende scenario voor het onderhouden en weergeven van een lijst met items die betrekking hebben op een potentieel geheugenuitputtingsscenario op de server:

  • De items in een List<T> eigenschap of veld maken gebruik van het geheugen van de server. Als de app toestaat dat de lijst met items onbegrensd groeit, is er een risico dat de server onvoldoende geheugen heeft. Als er onvoldoende geheugen beschikbaar is, wordt de huidige sessie beëindigd (crash) en ontvangen alle gelijktijdige sessies in dat serverexemplaren een uitzondering voor onvoldoende geheugen. Om te voorkomen dat dit scenario optreedt, moet de app een gegevensstructuur gebruiken die een itemlimiet voor gelijktijdige gebruikers oplegt.
  • Als er geen pagingschema wordt gebruikt voor rendering, gebruikt de server extra geheugen voor objecten die niet zichtbaar zijn in de gebruikersinterface. Zonder een limiet voor het aantal items kan de geheugenvraag het beschikbare servergeheugen uitputten. Gebruik een van de volgende methoden om dit scenario te voorkomen:
    • Gepagineerde lijsten gebruiken bij het weergeven.
    • Alleen de eerste 100 tot 1000 items weergeven en vereisen dat de gebruiker zoekcriteria invoert om items te vinden buiten de weergegeven items.
    • Implementeer lijsten of rasters die ondersteuning bieden voor virtualisatievoor een geavanceerder renderingscenario. Met behulp van virtualisatie worden alleen een subset van items weergegeven die momenteel zichtbaar zijn voor de gebruiker. Wanneer de gebruiker interactie heeft met de schuifbalk in de gebruikersinterface, worden alleen de items weergegeven die nodig zijn voor weergave. De items die momenteel niet nodig zijn voor weergave, kunnen worden opgeslagen in secundaire opslag. Dit is de ideale benadering. Niet-weergegeven items kunnen ook in het geheugen worden bewaard, wat minder ideaal is.

Notitie

Blazor heeft ingebouwde ondersteuning voor virtualisatie. Zie ASP.NET Core Razor componentvirtualisatievoor meer informatie.

Blazor apps bieden een vergelijkbaar programmeermodel aan andere UI-frameworks voor stateful apps, zoals WPF, Windows Forms of Blazor WebAssembly. Het belangrijkste verschil is dat in verschillende ui-frameworks het geheugen dat door de app wordt verbruikt, tot de client behoort en alleen van invloed is op die afzonderlijke client. Een Blazor WebAssembly-app wordt bijvoorbeeld volledig op de client uitgevoerd en maakt alleen gebruik van clientgeheugenbronnen. Voor een server-side Blazor-app behoort het geheugen dat door de app wordt gebruikt, tot de server en wordt het gedeeld tussen clients op het serverexemplaar.

Geheugenvereisten aan de serverzijde zijn een overweging voor alle Blazor-apps aan de serverzijde. De meeste web-apps zijn echter staatloos en het geheugen dat wordt gebruikt tijdens het verwerken van een aanvraag, wordt vrijgegeven wanneer het antwoord wordt geretourneerd. Als algemene aanbeveling staat u clients niet toe om een niet-afhankelijke hoeveelheid geheugen toe te wijzen, net als in een andere app aan de serverzijde die clientverbindingen persistent maakt. Het geheugen dat door een Blazor-app aan de serverzijde wordt verbruikt, blijft langer aanwezig dan bij een enkele aanvraag.

Notitie

Tijdens de ontwikkeling kan een profiler worden gebruikt of kan een trace worden vastgelegd om de geheugenvereisten van klanten te beoordelen. Een profiler of tracering legt het geheugen dat aan een specifieke client is toegewezen, niet vast. Als u het geheugengebruik van een specifieke client tijdens de ontwikkeling wilt vastleggen, legt u een dump vast en onderzoekt u de geheugenvraag van alle objecten die zijn geroot op het circuit van een gebruiker.

Clientverbindingen

Verbindingsuitputting kan optreden wanneer een of meer clients te veel gelijktijdige verbindingen met de server openen, waardoor andere clients geen nieuwe verbindingen tot stand kunnen brengen.

Blazor clients één verbinding per sessie tot stand brengen en de verbinding open houden zolang het browservenster is geopend. Gezien de permanente aard van de verbindingen en de met toestand werkende aard van server-side Blazor-apps, is de uitputting van verbindingen een groter risico voor de beschikbaarheid van de app.

Er is geen limiet voor het aantal verbindingen per gebruiker voor een app. Als voor de app een verbindingslimiet is vereist, voert u een of meer van de volgende methoden uit:

  • Verificatie vereisen, waardoor niet-geautoriseerde gebruikers natuurlijk geen verbinding kunnen maken met de app. Als dit scenario effectief is, moeten gebruikers niet op aanvraag nieuwe gebruikers inrichten.
  • Beperk het aantal verbindingen per gebruiker. Het beperken van verbindingen kan worden bereikt via de volgende methoden. Wees voorzichtig om legitieme gebruikers toegang te geven tot de app (bijvoorbeeld wanneer een verbindingslimiet tot stand is gebracht op basis van het IP-adres van de client).
    • Toepassingsniveau
      • Uitbreidbaarheid van eindpuntroutering.
      • Verificatie vereisen om verbinding te maken met de app en de actieve sessies per gebruiker bij te houden.
      • Nieuwe sessies weigeren bij het bereiken van een limiet.
      • Proxy WebSocket-verbindingen naar een app door gebruik te maken van een proxy, zoals de Azure SignalR Service die verbindingen van clients naar een app multiplexeert. Dit biedt een app met meer verbindingscapaciteit dan één client kan tot stand brengen, waardoor een client de verbindingen met de server niet kan uitputten.
    • Serverniveau
  • Verificatie vereisen, waardoor niet-geautoriseerde gebruikers natuurlijk geen verbinding kunnen maken met de app. Als dit scenario effectief is, moeten gebruikers niet op aanvraag nieuwe gebruikers inrichten.
  • Beperk het aantal verbindingen per gebruiker. Het beperken van verbindingen kan worden bereikt via de volgende methoden. Wees voorzichtig om legitieme gebruikers toegang te geven tot de app (bijvoorbeeld wanneer een verbindingslimiet tot stand is gebracht op basis van het IP-adres van de client).
    • Toepassingsniveau
      • Uitbreidbaarheid van eindpuntroutering.
      • Verificatie vereisen om verbinding te maken met de app en de actieve sessies per gebruiker bij te houden.
      • Nieuwe sessies weigeren bij het bereiken van een limiet.
      • Proxy WebSocket-verbindingen naar een app met een proxy, zoals de Azure SignalR Service die verbindingen van clients naar een app multiplexeert. Dit biedt een app met meer verbindingscapaciteit dan één client kan tot stand brengen, waardoor een client de verbindingen met de server niet kan uitputten.
    • Serverniveau
      • Gebruik een proxy/gateway vóór de app.
      • Hoewel Long Polling wordt ondersteund voor Blazor apps, is WebSockets het aanbevolen transportprotocol. U wordt aangeraden een proxy/gateway te selecteren die WebSockets ondersteunt.

DoS-aanvallen (Denial of Service)

DoS-aanvallen (Denial of Service) houden in dat een client ervoor zorgt dat de server een of meer van zijn hulpbronnen uitput, waardoor de app ontoegankelijk wordt. Blazor apps standaardlimieten bevatten en afhankelijk zijn van andere ASP.NET Core- en SignalR-limieten die zijn ingesteld op CircuitOptions ter bescherming tegen DoS-aanvallen:

Zie de volgende artikelen voor meer informatie en configuratiecodering:

Interacties met de browser (client)

Een client communiceert met de server via JS interop-gebeurtenisverzending en het voltooien van rendering. JS communicatie tussen JavaScript en .NET verloopt op beide manieren:

  • Browsergebeurtenissen worden op asynchrone wijze van de client naar de server verzonden.
  • De server reageert asynchroon en hertekent indien nodig de gebruikersinterface.

JavaScript-functies die worden aangeroepen vanuit .NET

Voor aanroepen van .NET-methoden naar JavaScript:

  • Alle aanroepen hebben een configureerbare time-out waarna ze mislukken, waardoor een OperationCanceledException naar de beller wordt geretourneerd.
  • Het resultaat van een JavaScript-aanroep kan niet worden vertrouwd. De Blazor app-client die wordt uitgevoerd in de browser zoekt naar de JavaScript-functie die moet worden aangeroepen. De functie wordt aangeroepen en het resultaat of een fout wordt gegenereerd. Een kwaadwillende client kan proberen het volgende te doen:
    • Veroorzaak een probleem in de app door een fout terug te geven vanuit de JavaScript-functie.
    • Een onbedoeld gedrag op de server veroorzaken door een onverwacht resultaat van de JavaScript-functie te retourneren.

Neem de volgende voorzorgsmaatregelen om u te beschermen tegen de voorgaande scenario's:

  • Verpakt JS interop-aanroepen binnen try-catch instructies om rekening te houden met fouten die kunnen optreden tijdens de aanroepen. Zie Fouten afhandelen in ASP.NET Core Blazor-appsvoor meer informatie.
  • Valideer gegevens die worden geretourneerd door JS inroepacties, inclusief foutberichten, voordat u actie onderneemt.

.NET-methoden die vanuit de browser worden aangeroepen

Vertrouw geen aanroepen van JavaScript naar .NET-methoden. Wanneer een .NET-methode beschikbaar wordt gesteld aan JavaScript, kunt u overwegen hoe de .NET-methode wordt aangeroepen:

  • Behandel elke .NET-methode die beschikbaar is voor JavaScript, zoals u een openbaar eindpunt voor de app zou doen.
    • Valideer invoer.
      • Zorg ervoor dat waarden zich binnen het verwachte bereik bevinden.
      • Zorg ervoor dat de gebruiker gemachtigd is om de aangevraagde actie uit te voeren.
    • Wijs geen overmatige hoeveelheid resources toe als onderdeel van de aanroep van de .NET-methode. Voer bijvoorbeeld controles uit en plaats limieten voor CPU- en geheugengebruik.
    • Houd er rekening mee dat statische en exemplaarmethoden beschikbaar kunnen worden gesteld aan JavaScript-clients. Vermijd het delen van status tussen sessies, tenzij het ontwerp het vereist met de juiste beperkingen.
      • Methoden die worden weergegeven via DotNetObjectReference-objecten, die oorspronkelijk zijn gemaakt via afhankelijkheidsinjectie (DI), moeten als scoped objecten worden geregistreerd. Dit geldt voor elke DI-service die door de app wordt gebruikt.
      • Voor statische methoden moet u voorkomen dat er status wordt vastgesteld die niet beperkt kan worden tot de client, tenzij de app de status expliciet ontwerpmatig deelt met alle gebruikers op een serverexemplaar.
    • Vermijd het doorgeven van door de gebruiker opgegeven gegevens in parameters aan JavaScript-aanroepen. Als het doorgeven van gegevens in parameters absoluut vereist is, moet u ervoor zorgen dat de JavaScript-code de gegevens doorgeeft zonder Cross-site scripting (XSS) kwetsbaarheden te introduceren. Schrijf bijvoorbeeld geen door de gebruiker opgegeven gegevens naar de DOM door de innerHTML eigenschap van een element in te stellen. Overweeg het gebruik van CSP- (Content Security Policy) om eval en andere onveilige JavaScript-primitieven uit te schakelen. Zie Een inhoudsbeveiligingsbeleid afdwingen voor ASP.NET Core Blazorvoor meer informatie.
  • Vermijd het implementeren van aangepaste dispatch van .NET-aanroepen bovenop de dispatch-implementatie van het framework. Het blootstellen van .NET-methoden aan de browser is een geavanceerd scenario, niet aanbevolen voor algemene Blazor ontwikkeling.

Gebeurtenissen

Gebeurtenissen bieden een toegangspunt voor een app. Dezelfde regels voor het beveiligen van eindpunten in web-apps zijn van toepassing op gebeurtenisafhandeling in Blazor-apps. Een kwaadwillende client kan alle gegevens verzenden die ze als nettolading voor een gebeurtenis willen verzenden.

Bijvoorbeeld:

  • Een wijzigingsbeurtenis voor een <select> kan een waarde verzenden die niet binnen de opties valt die de app aan de client heeft gepresenteerd.
  • Een <input> kan tekstgegevens naar de server verzenden, waardoor validatie aan de clientzijde wordt overgeslagen.

De app moet de gegevens valideren voor elke gebeurtenis die door de app wordt verwerkt. Het Blazor-framework laat componenten basisvalidaties uitvoeren. Als de app gebruikmaakt van aangepaste formulieronderdelen, moet aangepaste code zo nodig worden geschreven om gebeurtenisgegevens te valideren.

Gebeurtenissen zijn asynchroon, zodat meerdere gebeurtenissen naar de server kunnen worden verzonden voordat de app tijd heeft om te reageren door een nieuwe render te produceren. Dit heeft enkele gevolgen voor de beveiliging. Het beperken van clientacties in de app moet binnen evenement handlers worden uitgevoerd en mag niet afhangen van de huidige weergegeven weergavestatus.

Overweeg een telleronderdeel waarmee een gebruiker een teller maximaal drie keer kan verhogen. De knop voor het verhogen van de teller is voorwaardelijk gebaseerd op de waarde van count:

<p>Count: @count</p>

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

@code 
{
    private int count = 0;

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

Een client kan een of meer incrementele gebeurtenissen verzenden voordat het framework een nieuwe weergave van dit onderdeel produceert. Het resultaat is dat de count kan worden verhoogd meer dan drie keer door de gebruiker, omdat de knop niet snel genoeg door de gebruikersinterface wordt verwijderd. De juiste manier om de limiet van drie count stappen te bereiken, wordt weergegeven in het volgende voorbeeld:

<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++;
        }
    }
}

Door de if (count < 3) { ... } controle toe te voegen aan de handler, wordt de beslissing om count te verhogen gebaseerd op de huidige app-status. De beslissing is niet gebaseerd op de status van de gebruikersinterface, zoals in het vorige voorbeeld, wat tijdelijk verouderd kan zijn.

Beschermen tegen meerdere verzendingen

Als een gebeurtenisaanroep een langdurige bewerking asynchroon aanroept, zoals het ophalen van gegevens uit een externe service of database, kunt u overwegen een beveiliging te gebruiken. De beveiliging kan voorkomen dat de gebruiker meerdere bewerkingen in de wachtrij zet terwijl de bewerking wordt uitgevoerd met visuele feedback. Met de volgende onderdeelcode wordt isLoading ingesteld op true terwijl DataService.GetDataAsync gegevens van de server ophaalt. Wanneer isLoadingtrueis, is de knop uitgeschakeld in de gebruikersinterface.

<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;
        }
    }
}

Het beveiligingspatroon dat in het voorgaande voorbeeld wordt gedemonstreerd, werkt als de achtergrondbewerking asynchroon wordt uitgevoerd met het async-await patroon.

Eerder annuleren en gebruik na verwijdering vermijden

Naast het gebruik van een beveiliging zoals beschreven in de sectie Beveiligen tegen meerdere verzendingen, kunt u overwegen een CancellationToken te gebruiken om langdurige bewerkingen te annuleren wanneer het onderdeel wordt verwijderd. Deze aanpak heeft het extra voordeel dat gebruik na verwijdering in componenten wordt vermeden.

@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();
    }
}

Vermijd gebeurtenissen die grote hoeveelheden gegevens produceren

Sommige DOM-gebeurtenissen, zoals oninput of onscroll, kunnen een grote hoeveelheid gegevens produceren. Vermijd het gebruik van deze gebeurtenissen op Blazor server aan de serverzijde.

Aanvullende beveiligingsrichtlijnen

De richtlijnen voor het beveiligen van ASP.NET Core-apps zijn van toepassing op Blazor-apps aan de serverzijde en worden behandeld in de volgende secties van dit artikel:

Logboekregistratie en gevoelige gegevens

JS interacties tussen de client en de server worden vastgelegd in de logboeken van de server met ILogger exemplaren. Blazor voorkomt logboekregistratie van gevoelige informatie, zoals werkelijke gebeurtenissen of JS invoer en uitvoer van interop.

Wanneer er een fout optreedt op de server, meldt het framework de client en scheurt het de sessie uit. De client ontvangt een algemeen foutbericht dat kan worden weergegeven in de ontwikkelhulpprogramma's van de browser.

De fout aan de clientzijde bevat niet de aanroepstack en bevat geen details over de oorzaak van de fout, maar serverlogboeken bevatten dergelijke informatie. Voor ontwikkelingsdoeleinden kan gevoelige foutinformatie beschikbaar worden gesteld aan de client door gedetailleerde fouten in te schakelen.

Waarschuwing

Het blootstellen van foutinformatie aan clients op internet is een beveiligingsrisico dat altijd moet worden vermeden.

Informatie tijdens overdracht beveiligen met HTTPS

Blazor gebruikt SignalR voor communicatie tussen de client en de server. Blazor gebruikt normaal gesproken het transport dat SignalR onderhandelt, meestal WebSockets.

Blazor garandeert niet de integriteit en vertrouwelijkheid van de gegevens die worden verzonden tussen de server en de client. Gebruik altijd HTTPS.

Cross-site scripting (XSS)

Met CROSS-site scripting (XSS) kan een onbevoegde partij willekeurige logica uitvoeren in de context van de browser. Een aangetaste app kan mogelijk willekeurige code uitvoeren op de client. Het beveiligingsprobleem kan worden gebruikt om mogelijk een aantal schadelijke acties op de server uit te voeren:

  • Verzend valse/ongeldige gebeurtenissen naar de server.
  • Verzenden mislukt/ongeldige weergavevoltooiingen.
  • Vermijd het verzenden van render-voltooiingen.
  • Verzend interop-aanroepen van JavaScript naar .NET.
  • Wijzig het antwoord van interop-aanroepen van .NET naar JavaScript.
  • Vermijd het verzenden van .NET naar JS interop-resultaten.

Het Blazor framework neemt stappen om te beschermen tegen enkele van de voorgaande bedreigingen:

  • Stopt met het produceren van nieuwe UI-updates als de client geen renderbatches erkent. Geconfigureerd met CircuitOptions.MaxBufferedUnacknowledgedRenderBatches.
  • Er treedt een time-out op van een .NET-aan javaScript-aanroep na één minuut zonder een reactie van de client te ontvangen. Geconfigureerd met CircuitOptions.JSInteropDefaultCallTimeout.
  • Voert basisvalidatie uit op alle invoer die afkomstig is van de browser tijdens JS interop:
    • .NET-verwijzingen zijn geldig en van het type dat wordt verwacht door de .NET-methode.
    • De gegevens zijn niet vervormd.
    • Het juiste aantal argumenten voor de methode zijn aanwezig in de payload.
    • De argumenten of het resultaat kunnen correct worden gedeserialiseerd voordat u de methode aanroept.
  • Voert basisvalidatie uit in alle invoer die afkomstig is van de browser van verzonden gebeurtenissen:
    • De gebeurtenis heeft een geldig type.
    • De gegevens voor de gebeurtenis kunnen worden gedeserialiseerd.
    • Er is een event handler gekoppeld aan een gebeurtenis.

Naast de beveiligingsmaatregelen die door het framework worden geïmplementeerd, moet de app worden gecodeerd door de ontwikkelaar om bedreigingen te beschermen en passende acties uit te voeren:

  • Valideer altijd gegevens bij het verwerken van gebeurtenissen.
  • Voer de juiste actie uit bij het ontvangen van ongeldige gegevens:
    • Negeer de gegevens en keer terug. Hierdoor kan de app aanvragen blijven verwerken.
    • Als de app bepaalt dat de invoer niet-legitiem is en niet geproduceerd kan worden door een legitieme client, gooi dan een uitzondering. Als u een uitzondering opwerpt, vernietigt u het circuit en beëindigt u de sessie.
  • Vertrouw het foutbericht dat is opgegeven door batchvoltooiingen weer te geven die zijn opgenomen in de logboeken niet. De fout wordt geleverd door de client en is over het algemeen niet te vertrouwen, omdat de client mogelijk in gevaar is.
  • Vertrouw de invoer van JS interop-aanroepen niet, in welke richting dan ook, tussen JavaScript- en .NET-methoden.
  • De app is verantwoordelijk voor het valideren van de inhoud van argumenten en resultaten, zelfs als de argumenten of resultaten correct gedeserialiseerd zijn.

Als er een XSS-beveiligingsprobleem bestaat, moet de app gebruikersinvoer opnemen op de weergegeven pagina. Blazor voert een compilatiestap uit waarbij de markeringen in een .razor-bestand worden omgezet in procedurele C#-logica. Tijdens de uitvoeringstijd bouwt de C#-logica een renderstructuur die de elementen, tekst en onderliggende componenten beschrijft. Dit wordt toegepast op de DOM van de browser via een reeks JavaScript-instructies (of wordt geserialiseerd naar HTML in het geval van prerendering):

  • Gebruikersinvoer die wordt weergegeven via normale Razor syntaxis (bijvoorbeeld @someStringValue) biedt geen XSS-beveiligingsprobleem omdat de Razor syntaxis wordt toegevoegd aan de DOM via opdrachten die alleen tekst kunnen schrijven. Zelfs als de waarde HTML-markeringen bevat, wordt de waarde weergegeven als statische tekst. Bij het prerenderen is de uitvoer HTML-gecodeerd, waarmee ook de inhoud wordt weergegeven als statische tekst.
  • Auteurs van onderdelen kunnen onderdelen maken in C# zonder Razorte gebruiken. De auteur van het onderdeel is verantwoordelijk voor het gebruik van de juiste API's bij het verzenden van uitvoer. Gebruik bijvoorbeeld builder.AddContent(0, someUserSuppliedString) en nietbuilder.AddMarkupContent(0, someUserSuppliedString), omdat deze laatste een XSS-beveiligingsprobleem kan maken.
  • Gebruikersinvoer die wordt weergegeven via normale Razor syntaxis (bijvoorbeeld @someStringValue) biedt geen XSS-beveiligingsprobleem omdat de Razor syntaxis wordt toegevoegd aan de DOM via opdrachten die alleen tekst kunnen schrijven. Zelfs als de waarde HTML-markeringen bevat, wordt de waarde weergegeven als statische tekst. Bij het prerenderen is de uitvoer HTML-gecodeerd, waarmee ook de inhoud wordt weergegeven als statische tekst.
  • Scripttags zijn niet toegestaan en mogen niet worden opgenomen in de renderstructuur van het onderdeel van de app. Als een scripttag is opgenomen in de markeringen van een onderdeel, wordt er een compileertijdfout gegenereerd.
  • Auteurs van onderdelen kunnen onderdelen maken in C# zonder Razorte gebruiken. De auteur van het onderdeel is verantwoordelijk voor het gebruik van de juiste API's bij het verzenden van uitvoer. Gebruik bijvoorbeeld builder.AddContent(0, someUserSuppliedString) en nietbuilder.AddMarkupContent(0, someUserSuppliedString), omdat deze laatste een XSS-beveiligingsprobleem kan maken.

Overweeg xss-beveiligingsproblemen verder te beperken. Implementeer bijvoorbeeld een beperkend Content Security Policy (CSP) . Zie Een inhoudsbeveiligingsbeleid afdwingen voor ASP.NET Core Blazorvoor meer informatie.

Zie Cross-Site Scripting (XSS) voorkomen in ASP.NET Corevoor meer informatie.

Bescherming tegen cross-origin-aanvallen

Cross-origin-aanvallen hebben betrekking op een client van een andere oorsprong die een actie uitvoert op de server. De schadelijke actie is doorgaans een GET-aanvraag of een formulier POST (Cross-Site Request Forgery, CSRF), maar het openen van een kwaadwillende WebSocket is ook mogelijk. Blazor apps bieden dezelfde garanties als iedere andere SignalR app die het hubprotocol gebruikt:

  • Apps kunnen worden geopend via meerdere origins, tenzij er aanvullende maatregelen worden genomen om dit te voorkomen. Als u cross-origin-toegang wilt uitschakelen, schakelt u CORS in het eindpunt uit door de CORS-middleware toe te voegen aan de pijplijn en de DisableCorsAttribute toe te voegen aan de metagegevens van het Blazor eindpunt of de set toegestane oorsprongen te beperken door SignalR te configureren voor cross-origin resource sharing. Zie WebSockets-ondersteuning in ASP.NET Corevoor hulp bij websocket-oorsprongsbeperkingen.
  • Als CORS is ingeschakeld, zijn er mogelijk extra stappen vereist om de app te beveiligen, afhankelijk van de CORS-configuratie. Als CORS globaal is ingeschakeld, kan CORS worden uitgeschakeld voor de BlazorSignalR hub door de DisableCorsAttribute metagegevens toe te voegen aan de eindpuntmetagegevens nadat MapBlazorHub is aangeroepen in de opbouwfunctie voor eindpuntroute.

Zie Cross-Site Request Forgery -aanvallen (XSRF/CSRF) voorkomen in ASP.NET Corevoor meer informatie.

Click-jacking (klikmisleiding)

Klik-jacking omvat het weergeven van een site als een <iframe> binnen een site van een andere oorsprong om de gebruiker te misleiden om acties uit te voeren op de site die wordt aangevallen.

Als u een app wilt beschermen tegen weergave in een <iframe>, gebruikt u Content Security Policy (CSP) en de X-Frame-Options-header.

Zie de volgende bronnen voor meer informatie:

Omleidingen openen

Wanneer een app-sessie wordt gestart, voert de server basisvalidatie uit van de URL's die worden verzonden als onderdeel van het starten van de sessie. Het framework controleert of de basis-URL een bovenliggende URL van de huidige URL is voordat het circuit tot stand wordt gebracht. Er worden geen extra controles uitgevoerd door het framework.

Wanneer een gebruiker een koppeling op de client selecteert, wordt de URL voor de koppeling naar de server verzonden, waarmee wordt bepaald welke actie moet worden ondernomen. De app kan bijvoorbeeld een navigatie aan de clientzijde uitvoeren of aangeven dat de browser naar de nieuwe locatie moet gaan.

Onderdelen kunnen ook programmatisch navigatieaanvragen activeren via het gebruik van NavigationManager. In dergelijke scenario's kan de app een navigatie aan de clientzijde uitvoeren of aangeven dat de browser naar de nieuwe locatie gaat.

Onderdelen moeten:

  • Vermijd het gebruik van gebruikersinvoer als onderdeel van de argumenten voor de navigatieaanroep.
  • Valideer argumenten om ervoor te zorgen dat het doel is toegestaan door de app.

Anders kan een kwaadwillende gebruiker afdwingen dat de browser naar een door cyberaanval beheerde site gaat. In dit scenario misleidt de cyberaanvaller de app om gebruikersinvoer te gebruiken als onderdeel van de aanroep van methode NavigationManager.NavigateTo.

Dit advies is ook van toepassing wanneer koppelingen worden weergegeven als onderdeel van de app:

  • Gebruik indien mogelijk relatieve koppelingen.
  • Controleer of absolute koppelingsbestemmingen geldig zijn voordat ze op een pagina worden opgenomen.

Zie Open redirect-aanvallen voorkomen in ASP.NET Corevoor meer informatie.

Controlelijst voor beveiliging

De volgende lijst met beveiligingsoverwegingen is niet volledig:

  • Argumenten van gebeurtenissen valideren.
  • Valideer invoer en resultaten van JS interop-aanroepen.
  • Vermijd het gebruik van (of valideer vooraf) gebruikersinvoer voor .NET naar JS interop-aanroepen.
  • Voorkom dat de client een niet-afhankelijke hoeveelheid geheugen toedeelt.
  • Bescherm tegen meerdere verzendingen.
  • Langlopende bewerkingen annuleren wanneer de component wordt verwijderd.
  • Vermijd gebeurtenissen die grote hoeveelheden gegevens produceren.
  • Vermijd het gebruik van gebruikersinvoer als onderdeel van aanroepen voor NavigationManager.NavigateTo en valideer gebruikersinvoer voor URL's eerst op basis van een set toegestane oorsprongen als dit onvermijdelijk is.
  • Neem geen autorisatiebeslissingen op basis van de status van de gebruikersinterface, maar alleen vanuit de onderdeelstatus.
  • Overweeg het gebruik van CSP- (Content Security Policy) om te beschermen tegen XSS-aanvallen. Zie Een inhoudsbeveiligingsbeleid afdwingen voor ASP.NET Core Blazorvoor meer informatie.
  • Overweeg het gebruik van CSP en X-Frame-Options om te beschermen tegen click-jacking.
  • Zorg ervoor dat CORS-instellingen geschikt zijn wanneer u CORS inschakelt of CORS expliciet uitschakelt voor Blazor-apps.
  • Test om ervoor te zorgen dat de limieten aan de serverzijde voor de Blazor-app een acceptabele gebruikerservaring bieden zonder onaanvaardbare risiconiveaus.