From df348d5fdd4752b4d6cc8a46887084b3ee8067bf Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Tue, 21 Feb 2023 12:50:54 -0600 Subject: [PATCH] Threat mitigation article updates --- .../call-dotnet-from-javascript.md | 4 ++ .../call-javascript-from-dotnet.md | 4 ++ .../security/server/threat-mitigation.md | 38 ++++++++++++------- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/aspnetcore/blazor/javascript-interoperability/call-dotnet-from-javascript.md b/aspnetcore/blazor/javascript-interoperability/call-dotnet-from-javascript.md index aa4169a264f0..3243a69a16a8 100644 --- a/aspnetcore/blazor/javascript-interoperability/call-dotnet-from-javascript.md +++ b/aspnetcore/blazor/javascript-interoperability/call-dotnet-from-javascript.md @@ -886,6 +886,7 @@ The [`MutationObserver`](https://developer.mozilla.org/docs/Web/API/MutationObse * [Interaction with the Document Object Model (DOM)](xref:blazor/js-interop/index#interaction-with-the-document-object-model-dom) * [Blazor samples GitHub repository (`dotnet/blazor-samples`)](https://github.com/dotnet/blazor-samples) * (*JavaScript interop* section) +* [Blazor Server threat mitigation: .NET methods invoked from the browser](xref:blazor/security/server/threat-mitigation#net-methods-invoked-from-the-browser) :::moniker-end @@ -1737,6 +1738,7 @@ The [`MutationObserver`](https://developer.mozilla.org/docs/Web/API/MutationObse * [Interaction with the Document Object Model (DOM)](xref:blazor/js-interop/index#interaction-with-the-document-object-model-dom) * [Blazor samples GitHub repository (`dotnet/blazor-samples`)](https://github.com/dotnet/blazor-samples) * (*JavaScript interop* section) +* [Blazor Server threat mitigation: .NET methods invoked from the browser](xref:blazor/security/server/threat-mitigation#net-methods-invoked-from-the-browser) :::moniker-end @@ -2196,6 +2198,7 @@ The [`MutationObserver`](https://developer.mozilla.org/docs/Web/API/MutationObse * [Interaction with the Document Object Model (DOM)](xref:blazor/js-interop/index#interaction-with-the-document-object-model-dom) * [Blazor samples GitHub repository (`dotnet/blazor-samples`)](https://github.com/dotnet/blazor-samples) * (*JavaScript interop* section) +* [Blazor Server threat mitigation: .NET methods invoked from the browser](xref:blazor/security/server/threat-mitigation#net-methods-invoked-from-the-browser) :::moniker-end @@ -2641,5 +2644,6 @@ The [`MutationObserver`](https://developer.mozilla.org/docs/Web/API/MutationObse * [Interaction with the Document Object Model (DOM)](xref:blazor/js-interop/index#interaction-with-the-document-object-model-dom) * [Blazor samples GitHub repository (`dotnet/blazor-samples`)](https://github.com/dotnet/blazor-samples) * (*JavaScript interop* section) +* [Blazor Server threat mitigation: .NET methods invoked from the browser](xref:blazor/security/server/threat-mitigation#net-methods-invoked-from-the-browser) :::moniker-end diff --git a/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md b/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md index 24fd12d8db7e..a4639861d74d 100644 --- a/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md +++ b/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md @@ -784,6 +784,7 @@ The [`MutationObserver`](https://developer.mozilla.org/docs/Web/API/MutationObse * [`InteropComponent.razor` example (dotnet/AspNetCore GitHub repository `main` branch)](https://github.com/dotnet/AspNetCore/blob/main/src/Components/test/testassets/BasicTestApp/InteropComponent.razor): The `main` branch represents the product unit's current development for the next release of ASP.NET Core. To select the branch for a different release (for example, `release/5.0`), use the **Switch branches or tags** dropdown list to select the branch. * [Blazor samples GitHub repository (`dotnet/blazor-samples`)](https://github.com/dotnet/blazor-samples) * (*JavaScript interop* section) +* [Blazor Server threat mitigation: JavaScript functions invoked from .NET](xref:blazor/security/server/threat-mitigation#javascript-functions-invoked-from-net) :::moniker-end @@ -1608,6 +1609,7 @@ The [`MutationObserver`](https://developer.mozilla.org/docs/Web/API/MutationObse * [`InteropComponent.razor` example (dotnet/AspNetCore GitHub repository `main` branch)](https://github.com/dotnet/AspNetCore/blob/main/src/Components/test/testassets/BasicTestApp/InteropComponent.razor): The `main` branch represents the product unit's current development for the next release of ASP.NET Core. To select the branch for a different release (for example, `release/5.0`), use the **Switch branches or tags** dropdown list to select the branch. * [Blazor samples GitHub repository (`dotnet/blazor-samples`)](https://github.com/dotnet/blazor-samples) * (*JavaScript interop* section) +* [Blazor Server threat mitigation: JavaScript functions invoked from .NET](xref:blazor/security/server/threat-mitigation#javascript-functions-invoked-from-net) :::moniker-end @@ -2241,6 +2243,7 @@ The [`MutationObserver`](https://developer.mozilla.org/docs/Web/API/MutationObse * [`InteropComponent.razor` example (dotnet/AspNetCore GitHub repository `main` branch)](https://github.com/dotnet/AspNetCore/blob/main/src/Components/test/testassets/BasicTestApp/InteropComponent.razor): The `main` branch represents the product unit's current development for the next release of ASP.NET Core. To select the branch for a different release (for example, `release/5.0`), use the **Switch branches or tags** dropdown list to select the branch. * [Blazor samples GitHub repository (`dotnet/blazor-samples`)](https://github.com/dotnet/blazor-samples) * (*JavaScript interop* section) +* [Blazor Server threat mitigation: JavaScript functions invoked from .NET](xref:blazor/security/server/threat-mitigation#javascript-functions-invoked-from-net) :::moniker-end @@ -2668,5 +2671,6 @@ The [`MutationObserver`](https://developer.mozilla.org/docs/Web/API/MutationObse * * [Blazor samples GitHub repository (`dotnet/blazor-samples`)](https://github.com/dotnet/blazor-samples) * (*JavaScript interop* section) +* [Blazor Server threat mitigation: JavaScript functions invoked from .NET](xref:blazor/security/server/threat-mitigation#javascript-functions-invoked-from-net) :::moniker-end diff --git a/aspnetcore/blazor/security/server/threat-mitigation.md b/aspnetcore/blazor/security/server/threat-mitigation.md index 8ab76342c6eb..6ee9fc6f9145 100644 --- a/aspnetcore/blazor/security/server/threat-mitigation.md +++ b/aspnetcore/blazor/security/server/threat-mitigation.md @@ -5,7 +5,7 @@ description: Learn how to mitigate security threats to Blazor Server apps. monikerRange: '>= aspnetcore-3.1' ms.author: riande ms.custom: mvc -ms.date: 02/16/2023 +ms.date: 02/21/2023 uid: blazor/security/server/threat-mitigation --- # Threat mitigation guidance for ASP.NET Core Blazor Server @@ -59,12 +59,19 @@ For example, consider a Blazor-server side app with a component that accepts and Consider the following scenario for maintaining and displaying a list of items that pertain to a potential memory exhaustion scenario on the server: -* The items in a `List` property or field use the server's memory. If the app allows the list of items to grow unbounded, there's a risk of the server running out of memory. Running out of memory causes the current session to end (crash) and all of the concurrent sessions in that server instance receive an out-of-memory exception. To prevent this scenario from occurring, the app must use a data structure that imposes an item limit on concurrent users. +* The items in a `List` property or field use the server's memory. If the app allows the list of items to grow unbounded, there's a risk of the server running out of memory. Running out of memory causes the current session to end (crash) and all of the concurrent sessions in that server instance receive an out-of-memory exception. To prevent this scenario from occurring, the app must use a data structure that imposes an item limit on concurrent users. * If a paging scheme isn't used for rendering, the server uses additional memory for objects that aren't visible in the UI. Without a limit on the number of items, memory demands may exhaust the available server memory. To prevent this scenario, use one of the following approaches: * Use paginated lists when rendering. * Only display the first 100 to 1,000 items and require the user to enter search criteria to find items beyond the items displayed. * For a more advanced rendering scenario, implement lists or grids that support *virtualization*. Using virtualization, lists only render a subset of items currently visible to the user. When the user interacts with the scrollbar in the UI, the component renders only those items required for display. The items that aren't currently required for display can be held in secondary storage, which is the ideal approach. Undisplayed items can also be held in memory, which is less ideal. +:::moniker range=">= aspnetcore-5.0" + +> [!NOTE] +> Blazor has built-in support for virtualization. For more information, see . + +:::moniker-end + Blazor Server apps offer a similar programming model to other UI frameworks for stateful apps, such as WPF, Windows Forms, or Blazor WebAssembly. The main difference is that in several of the UI frameworks the memory consumed by the app belongs to the client and only affects that individual client. For example, a Blazor WebAssembly app runs entirely on the client and only uses client memory resources. In the Blazor Server scenario, the memory consumed by the app belongs to the server and is shared among clients on the server instance. Server-side memory demands are a consideration for all Blazor Server apps. However, most web apps are stateless, and the memory used while processing a request is released when the response is returned. As a general recommendation, don't permit clients to allocate an unbound amount of memory as in any other server-side app that persists client connections. The memory consumed by a Blazor Server app persists for a longer time than a single request. @@ -76,7 +83,7 @@ Server-side memory demands are a consideration for all Blazor Server apps. Howev Connection exhaustion can occur when one or more clients open too many concurrent connections to the server, preventing other clients from establishing new connections. -Blazor clients establish a single connection per session and keep the connection open for as long as the browser window is open. The demands on the server of maintaining all of the connections isn't specific to Blazor apps. Given the persistent nature of the connections and the stateful nature of Blazor Server apps, connection exhaustion is a greater risk to availability of the app. +Blazor clients establish a single connection per session and keep the connection open for as long as the browser window is open. Given the persistent nature of the connections and the stateful nature of Blazor Server apps, connection exhaustion is a greater risk to availability of the app. By default, there's no limit on the number of connections per user for a Blazor Server app. If the app requires a connection limit, take one or more of the following approaches: @@ -92,7 +99,7 @@ By default, there's no limit on the number of connections per user for a Blazor * At the server level: Use a proxy/gateway in front of the app. For example, [Azure Front Door](/azure/frontdoor/front-door-overview) enables you to define, manage, and monitor the global routing of web traffic to an app and works when Blazor Server apps are configured to use Long Polling. > [!NOTE] - > Although Long Polling is supported for Blazor Server apps, [WebSockets is the recommended transport protocol](xref:blazor/host-and-deploy/server#azure-signalr-service). [Azure Front Door](/azure/frontdoor/front-door-overview) doesn't support WebSockets at this time, but support for WebSockets is under consideration for a future release of the service. + > Although Long Polling is supported for Blazor Server apps, [WebSockets is the recommended transport protocol](xref:blazor/host-and-deploy/server#azure-signalr-service). As of February, 2023, [Azure Front Door](/azure/frontdoor/front-door-overview) doesn't support WebSockets, but support for WebSockets is under development for a future release of the service. For more information, see [Support WebSocket connections on Azure Front Door](https://feedback.azure.com/d365community/idea/c8b1d257-8a26-ec11-b6e6-000d3a4f0789). :::moniker-end @@ -160,9 +167,9 @@ Don't trust calls from JavaScript to .NET methods. When a .NET method is exposed * Ensure that the user has permission to perform the action requested. * Don't allocate an excessive quantity of resources as part of the .NET method invocation. For example, perform checks and place limits on CPU and memory use. * Take into account that static and instance methods can be exposed to JavaScript clients. Avoid sharing state across sessions unless the design calls for sharing state with appropriate constraints. - * For instance methods exposed through `DotNetReference` objects that are originally created through dependency injection (DI), the objects should be registered as scoped objects. This applies to any DI service that the Blazor Server app uses. + * For instance methods exposed through objects that are originally created through dependency injection (DI), the objects should be registered as scoped objects. This applies to any DI service that the Blazor Server app uses. * For static methods, avoid establishing state that can't be scoped to the client unless the app is explicitly sharing state by-design across all users on a server instance. - * Avoid passing user-supplied data in parameters to JavaScript calls. If passing data in parameters is absolutely required, ensure that the JavaScript code handles passing the data without introducing [Cross-site scripting (XSS)](#cross-site-scripting-xss) vulnerabilities. For example, don't write user-supplied data to the Document Object Model (DOM) by setting the `innerHTML` property of an element. Consider using [Content Security Policy (CSP)](https://developer.mozilla.org/docs/Web/HTTP/CSP) to disable `eval` and other unsafe JavaScript primitives. + * Avoid passing user-supplied data in parameters to JavaScript calls. If passing data in parameters is absolutely required, ensure that the JavaScript code handles passing the data without introducing [Cross-site scripting (XSS)](#cross-site-scripting-xss) vulnerabilities. For example, don't write user-supplied data to the Document Object Model (DOM) by setting the `innerHTML` property of an element. Consider using [Content Security Policy (CSP)](https://developer.mozilla.org/docs/Web/HTTP/CSP) to disable `eval` and other unsafe JavaScript primitives. For more information, see . * Avoid implementing custom dispatching of .NET invocations on top of the framework's dispatching implementation. Exposing .NET methods to the browser is an advanced scenario, not recommended for general Blazor development. ### Events @@ -290,7 +297,7 @@ Some DOM events, such as `oninput` or `onscroll`, can produce a large amount of ## Additional security guidance -The guidance for securing ASP.NET Core apps apply to Blazor Server apps and are covered in the following sections: +The guidance for securing ASP.NET Core apps apply to Blazor Server apps and are covered in the following sections of this article: * [Logging and sensitive data](#logging-and-sensitive-data) * [Protect information in transit with HTTPS](#protect-information-in-transit-with-https) @@ -347,7 +354,7 @@ In addition to the safeguards that the framework implements, the app must be cod * Take appropriate action upon receiving invalid data: * Ignore the data and return. This allows the app to continue processing requests. * If the app determines that the input is illegitimate and couldn't be produced by legitimate client, throw an exception. Throwing an exception tears down the circuit and ends the session. -* Don't trust the error message provided by render batch completions included in the logs. The error is provided by the client and can't generally be trusted, as the client might be compromised. +* Don't trust the error message provided by render batch completions included in the logs. The error is ***provided by the client*** and can't generally be trusted, as the client might be compromised. * Don't trust the input on JS interop calls in either direction between JavaScript and .NET methods. * The app is responsible for validating that the content of arguments and results are valid, even if the arguments or results are correctly deserialized. @@ -357,7 +364,7 @@ For a XSS vulnerability to exist, the app must incorporate user input in the ren * Script tags aren't allowed and shouldn't be included in the app's component render tree. If a script tag is included in a component's markup, a compile-time error is generated. * Component authors can author components in C# without using Razor. The component author is responsible for using the correct APIs when emitting output. For example, use `builder.AddContent(0, someUserSuppliedString)` and *not* `builder.AddMarkupContent(0, someUserSuppliedString)`, as the latter could create a XSS vulnerability. -As part of protecting against XSS attacks, consider implementing XSS mitigations, such as [Content Security Policy (CSP)](https://developer.mozilla.org/docs/Web/HTTP/CSP). +Consider further mitigating XSS vulnerabilities. For example, implement a restrictive [Content Security Policy (CSP)](https://developer.mozilla.org/docs/Web/HTTP/CSP). For more information, see . For more information, see . @@ -365,7 +372,7 @@ For more information, see . Cross-origin attacks involve a client from a different origin performing an action against the server. The malicious action is typically a GET request or a form POST (Cross-Site Request Forgery, CSRF), but opening a malicious WebSocket is also possible. Blazor Server apps offer [the same guarantees that any other SignalR app using the hub protocol offer](xref:signalr/security): -* Blazor Server apps can be accessed cross-origin unless additional measures are taken to prevent it. To disable cross-origin access, either disable CORS in the endpoint by adding the CORS middleware to the pipeline and adding the to the Blazor endpoint metadata or limit the set of allowed origins by [configuring SignalR for cross-origin resource sharing](xref:signalr/security#cross-origin-resource-sharing). +* Blazor Server apps can be accessed cross-origin unless additional measures are taken to prevent it. To disable cross-origin access, either disable CORS in the endpoint by adding the CORS middleware to the pipeline and adding the to the Blazor endpoint metadata or limit the set of allowed origins by [configuring SignalR for cross-origin resource sharing](xref:signalr/security#cross-origin-resource-sharing). For guidance on WebSocket origin restrictions, see . * If CORS is enabled, extra steps might be required to protect the app depending on the CORS configuration. If CORS is globally enabled, CORS can be disabled for the Blazor Server hub by adding the metadata to the endpoint metadata after calling on the endpoint route builder. For more information, see . @@ -374,7 +381,12 @@ For more information, see . Click-jacking involves rendering a site as an `