diff --git a/docs/client-api/security/_category_.json b/docs/client-api/security/_category_.json index e9e2bab6c4..360f66e504 100644 --- a/docs/client-api/security/_category_.json +++ b/docs/client-api/security/_category_.json @@ -1,4 +1,4 @@ { "position": 14, - "label": Security, + "label": "Security", } \ No newline at end of file diff --git a/docs/client-api/security/content/_deserialization-security-csharp.mdx b/docs/client-api/security/content/_deserialization-security-csharp.mdx index 21635f49c7..c4d5002aa6 100644 --- a/docs/client-api/security/content/_deserialization-security-csharp.mdx +++ b/docs/client-api/security/content/_deserialization-security-csharp.mdx @@ -2,202 +2,223 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; -* Data deserialization can trigger the execution of gadgets that - may initiate RCE attacks on the client machine. -* To handle this threat, RavenDB's default deserializer blocks the - deserialization of known [`.NET` RCE gadgets](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#known-net-rce-gadgets). -* Users can easily modify the list of namespaces and object types - that deserialization is forbidden or allowed for. - -* In this page: - * [Securing Deserialization](../../../client-api/security/deserialization-security.mdx#securing-deserialization) - * [Invoking a Gadget](../../../client-api/security/deserialization-security.mdx#invoking-a-gadget) - * [DefaultRavenSerializationBinder](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) - * [RegisterForbiddenNamespace](../../../client-api/security/deserialization-security.mdx#section) - * [RegisterForbiddenType](../../../client-api/security/deserialization-security.mdx#section-1) - * [RegisterSafeType](../../../client-api/security/deserialization-security.mdx#section-2) - * [Example](../../../client-api/security/deserialization-security.mdx#example) +* Deserializing data can trigger the execution of gadgets that may initiate RCE (Remote Code Execution) attacks on the client machine. +* To handle this threat, RavenDB's default deserializer blocks the deserialization of known [.NET RCE gadgets](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#known-net-rce-gadgets). +* Users can customize the list of namespaces and types for which deserialization is forbidden or allowed. + +* In this article: + * [Securing deserialization](../../../client-api/security/deserialization-security.mdx#securing-deserialization) + * [The deserialization risk](../../../client-api/security/deserialization-security.mdx#the-deserialization-risk) + * [Direct vs. indirect gadget loading](../../../client-api/security/deserialization-security.mdx#direct-vs-indirect-gadget-loading) + * [DefaultRavenSerializationBinder](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) + * [RegisterForbiddenNamespace](../../../client-api/security/deserialization-security.mdx#registerforbiddennamespace) + * [RegisterForbiddenType](../../../client-api/security/deserialization-security.mdx#registerforbiddentype) + * [RegisterSafeType](../../../client-api/security/deserialization-security.mdx#registersafetype) + * [Example](../../../client-api/security/deserialization-security.mdx#example) -## Securing Deserialization - -* When a RavenDB client uses the [Newtonsoft library](https://www.newtonsoft.com/json/help/html/SerializingJSON.htm) - to deserialize a JSON string to a `.NET` object, the object may include - a reference to a **gadget** (a code segment) and the deserialization - process may execute this gadget. -* Some gadgets attempt to exploit the deserialization process and initiate - an RCE (Remote Code Execution) attack that may, for example, inject the - system with malicious code. RCE attacks may sabotage the system, gain - control over it, steal information, and so on. -* To prevent such exploitation, RavenDB's default deserializer - blocks deserialization for suspicious namespaces and - [known `.NET` RCE gadgets](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#known-net-rce-gadgets): - `System.Configuration.Install.AssemblyInstaller` - `System.Activities.Presentation.WorkflowDesigner` - `System.Windows.ResourceDictionary` - `System.Windows.Data.ObjectDataProvider` - `System.Windows.Forms.BindingSource` - `Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvider` - `System.Data.DataViewManager, System.Xml.XmlDocument/XmlDataDocument` - `System.Management.Automation.PSObject` - -* Users can easily [modify](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) - the list of namespaces and object types for which deserialization is forbidden - or allowed. - - - -## Invoking a Gadget - -* **Directly-loaded gadgets Cannot be blocked using the default binder**. - When a gadget is loaded directly its loading and execution during - deserialization is **permitted** regardless of the content of the - default deserializer list. - - E.g., the following segment will be executed, - - -{`// The object will be allowed to be deserialized -// regardless of the default binder list. + + + + + +## The deserialization risk + +* When a RavenDB client uses the [Newtonsoft library](https://www.newtonsoft.com/json/help/html/SerializingJSON.htm) to deserialize a JSON string to a .NET object, + the object may include a reference to a **gadget** (a code segment) and the deserialization process may execute it. +* Some gadgets attempt to exploit the deserialization process and initiate an RCE (Remote Code Execution) attack that may, + for example, inject the system with malicious code, steal information, or take control of the machine. +* To prevent such exploitation, RavenDB's default deserializer blocks deserialization for the `Microsoft.VisualStudio` namespace + and for the following known .NET RCE gadgets: + + - `System.Configuration.Install.AssemblyInstaller` + - `System.Activities.Presentation.WorkflowDesigner` + - `System.Windows.ResourceDictionary` + - `System.Windows.Data.ObjectDataProvider` + - `System.Windows.Forms.BindingSource` + - `Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvider` + - `System.Data.DataViewManager` + - `System.Xml.XmlDocument` + - `System.Xml.XmlDataDocument` + - `System.Management.Automation.PSObject` + +* Users can [customize](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) the list of namespaces and types for which deserialization is forbidden or allowed. + + + +--- + + + +## Direct vs. indirect gadget loading + +**Directly-loaded gadgets cannot be blocked** using `DefaultRavenSerializationBinder`. +When a gadget is loaded directly, its execution during deserialization is permitted regardless of the binder's forbidden list. + +For example, the following `Load` call will succeed regardless of the binder configuration: + +```csharp +// The object will be allowed to be deserialized +// regardless of the binder list. session.Load("Gadget"); -`} - - - -* **Indirectly-loaded gadgets Can be blocked using the default binder**. - When a gadget is loaded indirectly its loading and execution during - deserialization **can be blocked** using the default deserializer list. - - E.g., in the following sample, taken [from here](https://book.hacktricks.xyz/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net#abusing-json.net), - a gadget is loaded indirectly: its name is included as a value - and will only take its place and be used to execute the gadget - during deserialization. - Including this type in the default deserialization list will - prevent the gadget's deserialization and execution. - - -{`string userdata = @"\{ - '$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, - Culture=neutral, PublicKeyToken=31bf3856ad364e35', - 'MethodName':'Start', - 'MethodParameters':\{ - '$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, - Culture=neutral, PublicKeyToken=b77a5c561934e089', - '$values':['cmd', '/c calc.exe'] - \}, - 'ObjectInstance':\{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, - Culture=neutral, PublicKeyToken=b77a5c561934e089'\} -\}"; -`} - - - - - - -## `DefaultRavenSerializationBinder` - -Use the `DefaultRavenSerializationBinder` convention and its methods to -block the deserialization of suspicious namespaces and object types or -allow the deserialization of trusted object types. - -Define a `DefaultRavenSerializationBinder` instance, use the dedicated -methods to forbid or allow the deserialization of entities, and register -the defined instance as a serialization convention as shown -[below](../../../client-api/security/deserialization-security.mdx#example). +``` + +
+ +**Indirectly-loaded gadgets can be blocked** using `DefaultRavenSerializationBinder`. +When a gadget type name is embedded as a value inside a JSON string, it is resolved only at deserialization time. At that point the binder can intercept and block it. + +For example, in the following payload (taken from [this source](https://book.hacktricks.xyz/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net#abusing-json.net)), the type is not loaded directly but appears as a JSON value and is resolved only during deserialization: + +```json +{ + "$type": "System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35", + "MethodName": "Start", + "MethodParameters": { + "$type": "System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", + "$values": ["cmd", "/c calc.exe"] + }, + "ObjectInstance": { + "$type": "System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" + } +} +``` + +
+ +Including `System.Windows.Data.ObjectDataProvider` in the forbidden list prevents this payload from being deserialized and executed. + + + + + + + +Use `DefaultRavenSerializationBinder` and its methods to block the deserialization of suspicious namespaces and types, +or to explicitly allow the deserialization of trusted types. + +Create a new `DefaultRavenSerializationBinder` instance, call the registration methods to define your overrides, +then configure the instance as a serialization convention as shown in the [example](../../../client-api/security/deserialization-security.mdx#example). -Be sure to update the default deserializer list **before** the initialization -of the document that you want the list to apply to. + +All `Register*` methods must be called **before** the binder processes its first type. +Calling any registration method after the binder has been used throws: +`InvalidOperationException: "Cannot perform this operation, because binder was already used."` + +Note that `DefaultRavenSerializationBinder.Instance` is a shared static singleton. +Always create your own `new DefaultRavenSerializationBinder()` instance; do not call registration methods on the static instance. + -### `RegisterForbiddenNamespace` -Use `RegisterForbiddenNamespace` to prevent the deserialization of objects loaded from a given namespace. - - - -{`public void RegisterForbiddenNamespace(string @namespace) -`} - - - - | Parameter | Type | Description | - |:-------------:|:-------------:|-------------| - | **@namespace** | `string` | The name of a namespace from which deserialization won't be allowed. | - - - Attempting to deserialize a forbidden namespace will throw an - `InvalidOperationException` exception with the following details: - _"Cannot resolve type" + `type.FullName` + "because the namespace is on a blacklist due to - security reasons. Please customize json deserializer in the conventions and override SerializationBinder - with your own logic if you want to allow this type."_ - -### `RegisterForbiddenType` -Use `RegisterForbiddenType` to prevent the deserialization of a given object type. - - - -{`public void RegisterForbiddenType(Type type) -`} - - - - | Parameter | Type | Description | - |:-------------:|:-------------:|-------------| - | **type** | `Type` | An object type whose deserialization won't be allowed. | - - - Attempting to deserialize a forbidden object type will throw an - `InvalidOperationException` exception with the following details: - _"Cannot resolve type" + `type.FullName` + "because the type is on a blacklist due to - security reasons. - Please customize json deserializer in the conventions and override SerializationBinder - with your own logic if you want to allow this type."_ - -### `RegisterSafeType` -Use `RegisterSafeType` to **allow** the deserialization of a given object type. - - - -{`public void RegisterSafeType(Type type) -`} - - - - | Parameter | Type | Description | - |:-------------:|:-------------:|-------------| - | **type** | `Type` | An object type whose deserialization **will** be allowed. | - -## Example - - - -{`// Create a default serialization binder -var binder = new DefaultRavenSerializationBinder(); -// Register a forbidden namespace -binder.RegisterForbiddenNamespace("SuspiciousNamespace"); -// Register a forbidden object type -binder.RegisterForbiddenType(suspiciousObject.GetType()); -// Register a trusted object type -binder.RegisterSafeType(trustedObject.GetType()); -var store = new DocumentStore() -\{ - Conventions = - \{ - Serialization = new NewtonsoftJsonSerializationConventions - \{ - // Customize store deserialization using the defined binder - CustomizeJsonDeserializer = deserializer => deserializer.SerializationBinder = binder - \} - \} -\}; -`} - - + + +## RegisterForbiddenNamespace + +Use `RegisterForbiddenNamespace` to prevent the deserialization of any type belonging to the given namespace. + +```csharp +public void RegisterForbiddenNamespace(string @namespace) +``` +
+| Parameter | Type | Description | +|-----------|------|-------------| +| **@namespace** | `string` | The namespace from which deserialization will be blocked. | + +Attempting to deserialize a type whose namespace is forbidden throws: +`InvalidOperationException: "Cannot resolve type '' because the namespace is on a blacklist due to security reasons. Please customize json deserializer in the conventions and override SerializationBinder with your own logic if you want to allow this type."` + + + +
+ +--- + + + +## RegisterForbiddenType + +Use `RegisterForbiddenType` to prevent the deserialization of a specific type. + +```csharp +public void RegisterForbiddenType(Type type) +``` + +
+ +| Parameter | Type | Description | +|-----------|------|-------------| +| **type** | `Type` | The type whose deserialization will be blocked. | + + + +Attempting to deserialize a forbidden type throws: +`InvalidOperationException: "Cannot resolve type '' because the type is on a blacklist due to security reasons. Please customize json deserializer in the conventions and override SerializationBinder with your own logic if you want to allow this type."` + + + +
+ +--- + + + +## RegisterSafeType + +Use `RegisterSafeType` to explicitly allow the deserialization of a specific type, overriding any namespace-level block that would otherwise apply. + +```csharp +public void RegisterSafeType(Type type) +``` + +
+ +| Parameter | Type | Description | +|-----------|------|-------------| +| **type** | `Type` | The type whose deserialization will be permitted. | + +
+ +
+ + + +The following example creates a `DefaultRavenSerializationBinder` instance, registers a forbidden namespace, a forbidden type, and a trusted type, then applies it to the document store: + +```csharp +// Create a new deserialization binder instance +var binder = new DefaultRavenSerializationBinder(); + +// Block all types in this namespace +binder.RegisterForbiddenNamespace("SuspiciousNamespace"); + +// Block a specific type +binder.RegisterForbiddenType(typeof(SuspiciousClass)); + +// Explicitly allow a specific type (overrides any namespace block) +binder.RegisterSafeType(typeof(TrustedClass)); + +var store = new DocumentStore +{ + Conventions = + { + Serialization = new NewtonsoftJsonSerializationConventions + { + // Apply the binder to the deserializer + CustomizeJsonDeserializer = deserializer => + deserializer.SerializationBinder = binder + } + } +}; +``` + + diff --git a/versioned_docs/version-6.2/client-api/security/_category_.json b/versioned_docs/version-6.2/client-api/security/_category_.json index e9e2bab6c4..360f66e504 100644 --- a/versioned_docs/version-6.2/client-api/security/_category_.json +++ b/versioned_docs/version-6.2/client-api/security/_category_.json @@ -1,4 +1,4 @@ { "position": 14, - "label": Security, + "label": "Security", } \ No newline at end of file diff --git a/versioned_docs/version-6.2/client-api/security/content/_deserialization-security-csharp.mdx b/versioned_docs/version-6.2/client-api/security/content/_deserialization-security-csharp.mdx index 21635f49c7..c4d5002aa6 100644 --- a/versioned_docs/version-6.2/client-api/security/content/_deserialization-security-csharp.mdx +++ b/versioned_docs/version-6.2/client-api/security/content/_deserialization-security-csharp.mdx @@ -2,202 +2,223 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; -* Data deserialization can trigger the execution of gadgets that - may initiate RCE attacks on the client machine. -* To handle this threat, RavenDB's default deserializer blocks the - deserialization of known [`.NET` RCE gadgets](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#known-net-rce-gadgets). -* Users can easily modify the list of namespaces and object types - that deserialization is forbidden or allowed for. - -* In this page: - * [Securing Deserialization](../../../client-api/security/deserialization-security.mdx#securing-deserialization) - * [Invoking a Gadget](../../../client-api/security/deserialization-security.mdx#invoking-a-gadget) - * [DefaultRavenSerializationBinder](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) - * [RegisterForbiddenNamespace](../../../client-api/security/deserialization-security.mdx#section) - * [RegisterForbiddenType](../../../client-api/security/deserialization-security.mdx#section-1) - * [RegisterSafeType](../../../client-api/security/deserialization-security.mdx#section-2) - * [Example](../../../client-api/security/deserialization-security.mdx#example) +* Deserializing data can trigger the execution of gadgets that may initiate RCE (Remote Code Execution) attacks on the client machine. +* To handle this threat, RavenDB's default deserializer blocks the deserialization of known [.NET RCE gadgets](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#known-net-rce-gadgets). +* Users can customize the list of namespaces and types for which deserialization is forbidden or allowed. + +* In this article: + * [Securing deserialization](../../../client-api/security/deserialization-security.mdx#securing-deserialization) + * [The deserialization risk](../../../client-api/security/deserialization-security.mdx#the-deserialization-risk) + * [Direct vs. indirect gadget loading](../../../client-api/security/deserialization-security.mdx#direct-vs-indirect-gadget-loading) + * [DefaultRavenSerializationBinder](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) + * [RegisterForbiddenNamespace](../../../client-api/security/deserialization-security.mdx#registerforbiddennamespace) + * [RegisterForbiddenType](../../../client-api/security/deserialization-security.mdx#registerforbiddentype) + * [RegisterSafeType](../../../client-api/security/deserialization-security.mdx#registersafetype) + * [Example](../../../client-api/security/deserialization-security.mdx#example) -## Securing Deserialization - -* When a RavenDB client uses the [Newtonsoft library](https://www.newtonsoft.com/json/help/html/SerializingJSON.htm) - to deserialize a JSON string to a `.NET` object, the object may include - a reference to a **gadget** (a code segment) and the deserialization - process may execute this gadget. -* Some gadgets attempt to exploit the deserialization process and initiate - an RCE (Remote Code Execution) attack that may, for example, inject the - system with malicious code. RCE attacks may sabotage the system, gain - control over it, steal information, and so on. -* To prevent such exploitation, RavenDB's default deserializer - blocks deserialization for suspicious namespaces and - [known `.NET` RCE gadgets](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#known-net-rce-gadgets): - `System.Configuration.Install.AssemblyInstaller` - `System.Activities.Presentation.WorkflowDesigner` - `System.Windows.ResourceDictionary` - `System.Windows.Data.ObjectDataProvider` - `System.Windows.Forms.BindingSource` - `Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvider` - `System.Data.DataViewManager, System.Xml.XmlDocument/XmlDataDocument` - `System.Management.Automation.PSObject` - -* Users can easily [modify](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) - the list of namespaces and object types for which deserialization is forbidden - or allowed. - - - -## Invoking a Gadget - -* **Directly-loaded gadgets Cannot be blocked using the default binder**. - When a gadget is loaded directly its loading and execution during - deserialization is **permitted** regardless of the content of the - default deserializer list. - - E.g., the following segment will be executed, - - -{`// The object will be allowed to be deserialized -// regardless of the default binder list. + + + + + +## The deserialization risk + +* When a RavenDB client uses the [Newtonsoft library](https://www.newtonsoft.com/json/help/html/SerializingJSON.htm) to deserialize a JSON string to a .NET object, + the object may include a reference to a **gadget** (a code segment) and the deserialization process may execute it. +* Some gadgets attempt to exploit the deserialization process and initiate an RCE (Remote Code Execution) attack that may, + for example, inject the system with malicious code, steal information, or take control of the machine. +* To prevent such exploitation, RavenDB's default deserializer blocks deserialization for the `Microsoft.VisualStudio` namespace + and for the following known .NET RCE gadgets: + + - `System.Configuration.Install.AssemblyInstaller` + - `System.Activities.Presentation.WorkflowDesigner` + - `System.Windows.ResourceDictionary` + - `System.Windows.Data.ObjectDataProvider` + - `System.Windows.Forms.BindingSource` + - `Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvider` + - `System.Data.DataViewManager` + - `System.Xml.XmlDocument` + - `System.Xml.XmlDataDocument` + - `System.Management.Automation.PSObject` + +* Users can [customize](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) the list of namespaces and types for which deserialization is forbidden or allowed. + + + +--- + + + +## Direct vs. indirect gadget loading + +**Directly-loaded gadgets cannot be blocked** using `DefaultRavenSerializationBinder`. +When a gadget is loaded directly, its execution during deserialization is permitted regardless of the binder's forbidden list. + +For example, the following `Load` call will succeed regardless of the binder configuration: + +```csharp +// The object will be allowed to be deserialized +// regardless of the binder list. session.Load("Gadget"); -`} - - - -* **Indirectly-loaded gadgets Can be blocked using the default binder**. - When a gadget is loaded indirectly its loading and execution during - deserialization **can be blocked** using the default deserializer list. - - E.g., in the following sample, taken [from here](https://book.hacktricks.xyz/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net#abusing-json.net), - a gadget is loaded indirectly: its name is included as a value - and will only take its place and be used to execute the gadget - during deserialization. - Including this type in the default deserialization list will - prevent the gadget's deserialization and execution. - - -{`string userdata = @"\{ - '$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, - Culture=neutral, PublicKeyToken=31bf3856ad364e35', - 'MethodName':'Start', - 'MethodParameters':\{ - '$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, - Culture=neutral, PublicKeyToken=b77a5c561934e089', - '$values':['cmd', '/c calc.exe'] - \}, - 'ObjectInstance':\{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, - Culture=neutral, PublicKeyToken=b77a5c561934e089'\} -\}"; -`} - - - - - - -## `DefaultRavenSerializationBinder` - -Use the `DefaultRavenSerializationBinder` convention and its methods to -block the deserialization of suspicious namespaces and object types or -allow the deserialization of trusted object types. - -Define a `DefaultRavenSerializationBinder` instance, use the dedicated -methods to forbid or allow the deserialization of entities, and register -the defined instance as a serialization convention as shown -[below](../../../client-api/security/deserialization-security.mdx#example). +``` + +
+ +**Indirectly-loaded gadgets can be blocked** using `DefaultRavenSerializationBinder`. +When a gadget type name is embedded as a value inside a JSON string, it is resolved only at deserialization time. At that point the binder can intercept and block it. + +For example, in the following payload (taken from [this source](https://book.hacktricks.xyz/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net#abusing-json.net)), the type is not loaded directly but appears as a JSON value and is resolved only during deserialization: + +```json +{ + "$type": "System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35", + "MethodName": "Start", + "MethodParameters": { + "$type": "System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", + "$values": ["cmd", "/c calc.exe"] + }, + "ObjectInstance": { + "$type": "System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" + } +} +``` + +
+ +Including `System.Windows.Data.ObjectDataProvider` in the forbidden list prevents this payload from being deserialized and executed. + + + + + + + +Use `DefaultRavenSerializationBinder` and its methods to block the deserialization of suspicious namespaces and types, +or to explicitly allow the deserialization of trusted types. + +Create a new `DefaultRavenSerializationBinder` instance, call the registration methods to define your overrides, +then configure the instance as a serialization convention as shown in the [example](../../../client-api/security/deserialization-security.mdx#example). -Be sure to update the default deserializer list **before** the initialization -of the document that you want the list to apply to. + +All `Register*` methods must be called **before** the binder processes its first type. +Calling any registration method after the binder has been used throws: +`InvalidOperationException: "Cannot perform this operation, because binder was already used."` + +Note that `DefaultRavenSerializationBinder.Instance` is a shared static singleton. +Always create your own `new DefaultRavenSerializationBinder()` instance; do not call registration methods on the static instance. + -### `RegisterForbiddenNamespace` -Use `RegisterForbiddenNamespace` to prevent the deserialization of objects loaded from a given namespace. - - - -{`public void RegisterForbiddenNamespace(string @namespace) -`} - - - - | Parameter | Type | Description | - |:-------------:|:-------------:|-------------| - | **@namespace** | `string` | The name of a namespace from which deserialization won't be allowed. | - - - Attempting to deserialize a forbidden namespace will throw an - `InvalidOperationException` exception with the following details: - _"Cannot resolve type" + `type.FullName` + "because the namespace is on a blacklist due to - security reasons. Please customize json deserializer in the conventions and override SerializationBinder - with your own logic if you want to allow this type."_ - -### `RegisterForbiddenType` -Use `RegisterForbiddenType` to prevent the deserialization of a given object type. - - - -{`public void RegisterForbiddenType(Type type) -`} - - - - | Parameter | Type | Description | - |:-------------:|:-------------:|-------------| - | **type** | `Type` | An object type whose deserialization won't be allowed. | - - - Attempting to deserialize a forbidden object type will throw an - `InvalidOperationException` exception with the following details: - _"Cannot resolve type" + `type.FullName` + "because the type is on a blacklist due to - security reasons. - Please customize json deserializer in the conventions and override SerializationBinder - with your own logic if you want to allow this type."_ - -### `RegisterSafeType` -Use `RegisterSafeType` to **allow** the deserialization of a given object type. - - - -{`public void RegisterSafeType(Type type) -`} - - - - | Parameter | Type | Description | - |:-------------:|:-------------:|-------------| - | **type** | `Type` | An object type whose deserialization **will** be allowed. | - -## Example - - - -{`// Create a default serialization binder -var binder = new DefaultRavenSerializationBinder(); -// Register a forbidden namespace -binder.RegisterForbiddenNamespace("SuspiciousNamespace"); -// Register a forbidden object type -binder.RegisterForbiddenType(suspiciousObject.GetType()); -// Register a trusted object type -binder.RegisterSafeType(trustedObject.GetType()); -var store = new DocumentStore() -\{ - Conventions = - \{ - Serialization = new NewtonsoftJsonSerializationConventions - \{ - // Customize store deserialization using the defined binder - CustomizeJsonDeserializer = deserializer => deserializer.SerializationBinder = binder - \} - \} -\}; -`} - - + + +## RegisterForbiddenNamespace + +Use `RegisterForbiddenNamespace` to prevent the deserialization of any type belonging to the given namespace. + +```csharp +public void RegisterForbiddenNamespace(string @namespace) +``` +
+| Parameter | Type | Description | +|-----------|------|-------------| +| **@namespace** | `string` | The namespace from which deserialization will be blocked. | + +Attempting to deserialize a type whose namespace is forbidden throws: +`InvalidOperationException: "Cannot resolve type '' because the namespace is on a blacklist due to security reasons. Please customize json deserializer in the conventions and override SerializationBinder with your own logic if you want to allow this type."` + + + +
+ +--- + + + +## RegisterForbiddenType + +Use `RegisterForbiddenType` to prevent the deserialization of a specific type. + +```csharp +public void RegisterForbiddenType(Type type) +``` + +
+ +| Parameter | Type | Description | +|-----------|------|-------------| +| **type** | `Type` | The type whose deserialization will be blocked. | + + + +Attempting to deserialize a forbidden type throws: +`InvalidOperationException: "Cannot resolve type '' because the type is on a blacklist due to security reasons. Please customize json deserializer in the conventions and override SerializationBinder with your own logic if you want to allow this type."` + + + +
+ +--- + + + +## RegisterSafeType + +Use `RegisterSafeType` to explicitly allow the deserialization of a specific type, overriding any namespace-level block that would otherwise apply. + +```csharp +public void RegisterSafeType(Type type) +``` + +
+ +| Parameter | Type | Description | +|-----------|------|-------------| +| **type** | `Type` | The type whose deserialization will be permitted. | + +
+ +
+ + + +The following example creates a `DefaultRavenSerializationBinder` instance, registers a forbidden namespace, a forbidden type, and a trusted type, then applies it to the document store: + +```csharp +// Create a new deserialization binder instance +var binder = new DefaultRavenSerializationBinder(); + +// Block all types in this namespace +binder.RegisterForbiddenNamespace("SuspiciousNamespace"); + +// Block a specific type +binder.RegisterForbiddenType(typeof(SuspiciousClass)); + +// Explicitly allow a specific type (overrides any namespace block) +binder.RegisterSafeType(typeof(TrustedClass)); + +var store = new DocumentStore +{ + Conventions = + { + Serialization = new NewtonsoftJsonSerializationConventions + { + // Apply the binder to the deserializer + CustomizeJsonDeserializer = deserializer => + deserializer.SerializationBinder = binder + } + } +}; +``` + + diff --git a/versioned_docs/version-7.0/client-api/security/_category_.json b/versioned_docs/version-7.0/client-api/security/_category_.json index e9e2bab6c4..360f66e504 100644 --- a/versioned_docs/version-7.0/client-api/security/_category_.json +++ b/versioned_docs/version-7.0/client-api/security/_category_.json @@ -1,4 +1,4 @@ { "position": 14, - "label": Security, + "label": "Security", } \ No newline at end of file diff --git a/versioned_docs/version-7.0/client-api/security/content/_deserialization-security-csharp.mdx b/versioned_docs/version-7.0/client-api/security/content/_deserialization-security-csharp.mdx index 21635f49c7..c4d5002aa6 100644 --- a/versioned_docs/version-7.0/client-api/security/content/_deserialization-security-csharp.mdx +++ b/versioned_docs/version-7.0/client-api/security/content/_deserialization-security-csharp.mdx @@ -2,202 +2,223 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; -* Data deserialization can trigger the execution of gadgets that - may initiate RCE attacks on the client machine. -* To handle this threat, RavenDB's default deserializer blocks the - deserialization of known [`.NET` RCE gadgets](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#known-net-rce-gadgets). -* Users can easily modify the list of namespaces and object types - that deserialization is forbidden or allowed for. - -* In this page: - * [Securing Deserialization](../../../client-api/security/deserialization-security.mdx#securing-deserialization) - * [Invoking a Gadget](../../../client-api/security/deserialization-security.mdx#invoking-a-gadget) - * [DefaultRavenSerializationBinder](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) - * [RegisterForbiddenNamespace](../../../client-api/security/deserialization-security.mdx#section) - * [RegisterForbiddenType](../../../client-api/security/deserialization-security.mdx#section-1) - * [RegisterSafeType](../../../client-api/security/deserialization-security.mdx#section-2) - * [Example](../../../client-api/security/deserialization-security.mdx#example) +* Deserializing data can trigger the execution of gadgets that may initiate RCE (Remote Code Execution) attacks on the client machine. +* To handle this threat, RavenDB's default deserializer blocks the deserialization of known [.NET RCE gadgets](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#known-net-rce-gadgets). +* Users can customize the list of namespaces and types for which deserialization is forbidden or allowed. + +* In this article: + * [Securing deserialization](../../../client-api/security/deserialization-security.mdx#securing-deserialization) + * [The deserialization risk](../../../client-api/security/deserialization-security.mdx#the-deserialization-risk) + * [Direct vs. indirect gadget loading](../../../client-api/security/deserialization-security.mdx#direct-vs-indirect-gadget-loading) + * [DefaultRavenSerializationBinder](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) + * [RegisterForbiddenNamespace](../../../client-api/security/deserialization-security.mdx#registerforbiddennamespace) + * [RegisterForbiddenType](../../../client-api/security/deserialization-security.mdx#registerforbiddentype) + * [RegisterSafeType](../../../client-api/security/deserialization-security.mdx#registersafetype) + * [Example](../../../client-api/security/deserialization-security.mdx#example) -## Securing Deserialization - -* When a RavenDB client uses the [Newtonsoft library](https://www.newtonsoft.com/json/help/html/SerializingJSON.htm) - to deserialize a JSON string to a `.NET` object, the object may include - a reference to a **gadget** (a code segment) and the deserialization - process may execute this gadget. -* Some gadgets attempt to exploit the deserialization process and initiate - an RCE (Remote Code Execution) attack that may, for example, inject the - system with malicious code. RCE attacks may sabotage the system, gain - control over it, steal information, and so on. -* To prevent such exploitation, RavenDB's default deserializer - blocks deserialization for suspicious namespaces and - [known `.NET` RCE gadgets](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#known-net-rce-gadgets): - `System.Configuration.Install.AssemblyInstaller` - `System.Activities.Presentation.WorkflowDesigner` - `System.Windows.ResourceDictionary` - `System.Windows.Data.ObjectDataProvider` - `System.Windows.Forms.BindingSource` - `Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvider` - `System.Data.DataViewManager, System.Xml.XmlDocument/XmlDataDocument` - `System.Management.Automation.PSObject` - -* Users can easily [modify](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) - the list of namespaces and object types for which deserialization is forbidden - or allowed. - - - -## Invoking a Gadget - -* **Directly-loaded gadgets Cannot be blocked using the default binder**. - When a gadget is loaded directly its loading and execution during - deserialization is **permitted** regardless of the content of the - default deserializer list. - - E.g., the following segment will be executed, - - -{`// The object will be allowed to be deserialized -// regardless of the default binder list. + + + + + +## The deserialization risk + +* When a RavenDB client uses the [Newtonsoft library](https://www.newtonsoft.com/json/help/html/SerializingJSON.htm) to deserialize a JSON string to a .NET object, + the object may include a reference to a **gadget** (a code segment) and the deserialization process may execute it. +* Some gadgets attempt to exploit the deserialization process and initiate an RCE (Remote Code Execution) attack that may, + for example, inject the system with malicious code, steal information, or take control of the machine. +* To prevent such exploitation, RavenDB's default deserializer blocks deserialization for the `Microsoft.VisualStudio` namespace + and for the following known .NET RCE gadgets: + + - `System.Configuration.Install.AssemblyInstaller` + - `System.Activities.Presentation.WorkflowDesigner` + - `System.Windows.ResourceDictionary` + - `System.Windows.Data.ObjectDataProvider` + - `System.Windows.Forms.BindingSource` + - `Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvider` + - `System.Data.DataViewManager` + - `System.Xml.XmlDocument` + - `System.Xml.XmlDataDocument` + - `System.Management.Automation.PSObject` + +* Users can [customize](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) the list of namespaces and types for which deserialization is forbidden or allowed. + + + +--- + + + +## Direct vs. indirect gadget loading + +**Directly-loaded gadgets cannot be blocked** using `DefaultRavenSerializationBinder`. +When a gadget is loaded directly, its execution during deserialization is permitted regardless of the binder's forbidden list. + +For example, the following `Load` call will succeed regardless of the binder configuration: + +```csharp +// The object will be allowed to be deserialized +// regardless of the binder list. session.Load("Gadget"); -`} - - - -* **Indirectly-loaded gadgets Can be blocked using the default binder**. - When a gadget is loaded indirectly its loading and execution during - deserialization **can be blocked** using the default deserializer list. - - E.g., in the following sample, taken [from here](https://book.hacktricks.xyz/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net#abusing-json.net), - a gadget is loaded indirectly: its name is included as a value - and will only take its place and be used to execute the gadget - during deserialization. - Including this type in the default deserialization list will - prevent the gadget's deserialization and execution. - - -{`string userdata = @"\{ - '$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, - Culture=neutral, PublicKeyToken=31bf3856ad364e35', - 'MethodName':'Start', - 'MethodParameters':\{ - '$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, - Culture=neutral, PublicKeyToken=b77a5c561934e089', - '$values':['cmd', '/c calc.exe'] - \}, - 'ObjectInstance':\{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, - Culture=neutral, PublicKeyToken=b77a5c561934e089'\} -\}"; -`} - - - - - - -## `DefaultRavenSerializationBinder` - -Use the `DefaultRavenSerializationBinder` convention and its methods to -block the deserialization of suspicious namespaces and object types or -allow the deserialization of trusted object types. - -Define a `DefaultRavenSerializationBinder` instance, use the dedicated -methods to forbid or allow the deserialization of entities, and register -the defined instance as a serialization convention as shown -[below](../../../client-api/security/deserialization-security.mdx#example). +``` + +
+ +**Indirectly-loaded gadgets can be blocked** using `DefaultRavenSerializationBinder`. +When a gadget type name is embedded as a value inside a JSON string, it is resolved only at deserialization time. At that point the binder can intercept and block it. + +For example, in the following payload (taken from [this source](https://book.hacktricks.xyz/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net#abusing-json.net)), the type is not loaded directly but appears as a JSON value and is resolved only during deserialization: + +```json +{ + "$type": "System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35", + "MethodName": "Start", + "MethodParameters": { + "$type": "System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", + "$values": ["cmd", "/c calc.exe"] + }, + "ObjectInstance": { + "$type": "System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" + } +} +``` + +
+ +Including `System.Windows.Data.ObjectDataProvider` in the forbidden list prevents this payload from being deserialized and executed. + + + + + + + +Use `DefaultRavenSerializationBinder` and its methods to block the deserialization of suspicious namespaces and types, +or to explicitly allow the deserialization of trusted types. + +Create a new `DefaultRavenSerializationBinder` instance, call the registration methods to define your overrides, +then configure the instance as a serialization convention as shown in the [example](../../../client-api/security/deserialization-security.mdx#example). -Be sure to update the default deserializer list **before** the initialization -of the document that you want the list to apply to. + +All `Register*` methods must be called **before** the binder processes its first type. +Calling any registration method after the binder has been used throws: +`InvalidOperationException: "Cannot perform this operation, because binder was already used."` + +Note that `DefaultRavenSerializationBinder.Instance` is a shared static singleton. +Always create your own `new DefaultRavenSerializationBinder()` instance; do not call registration methods on the static instance. + -### `RegisterForbiddenNamespace` -Use `RegisterForbiddenNamespace` to prevent the deserialization of objects loaded from a given namespace. - - - -{`public void RegisterForbiddenNamespace(string @namespace) -`} - - - - | Parameter | Type | Description | - |:-------------:|:-------------:|-------------| - | **@namespace** | `string` | The name of a namespace from which deserialization won't be allowed. | - - - Attempting to deserialize a forbidden namespace will throw an - `InvalidOperationException` exception with the following details: - _"Cannot resolve type" + `type.FullName` + "because the namespace is on a blacklist due to - security reasons. Please customize json deserializer in the conventions and override SerializationBinder - with your own logic if you want to allow this type."_ - -### `RegisterForbiddenType` -Use `RegisterForbiddenType` to prevent the deserialization of a given object type. - - - -{`public void RegisterForbiddenType(Type type) -`} - - - - | Parameter | Type | Description | - |:-------------:|:-------------:|-------------| - | **type** | `Type` | An object type whose deserialization won't be allowed. | - - - Attempting to deserialize a forbidden object type will throw an - `InvalidOperationException` exception with the following details: - _"Cannot resolve type" + `type.FullName` + "because the type is on a blacklist due to - security reasons. - Please customize json deserializer in the conventions and override SerializationBinder - with your own logic if you want to allow this type."_ - -### `RegisterSafeType` -Use `RegisterSafeType` to **allow** the deserialization of a given object type. - - - -{`public void RegisterSafeType(Type type) -`} - - - - | Parameter | Type | Description | - |:-------------:|:-------------:|-------------| - | **type** | `Type` | An object type whose deserialization **will** be allowed. | - -## Example - - - -{`// Create a default serialization binder -var binder = new DefaultRavenSerializationBinder(); -// Register a forbidden namespace -binder.RegisterForbiddenNamespace("SuspiciousNamespace"); -// Register a forbidden object type -binder.RegisterForbiddenType(suspiciousObject.GetType()); -// Register a trusted object type -binder.RegisterSafeType(trustedObject.GetType()); -var store = new DocumentStore() -\{ - Conventions = - \{ - Serialization = new NewtonsoftJsonSerializationConventions - \{ - // Customize store deserialization using the defined binder - CustomizeJsonDeserializer = deserializer => deserializer.SerializationBinder = binder - \} - \} -\}; -`} - - + + +## RegisterForbiddenNamespace + +Use `RegisterForbiddenNamespace` to prevent the deserialization of any type belonging to the given namespace. + +```csharp +public void RegisterForbiddenNamespace(string @namespace) +``` +
+| Parameter | Type | Description | +|-----------|------|-------------| +| **@namespace** | `string` | The namespace from which deserialization will be blocked. | + +Attempting to deserialize a type whose namespace is forbidden throws: +`InvalidOperationException: "Cannot resolve type '' because the namespace is on a blacklist due to security reasons. Please customize json deserializer in the conventions and override SerializationBinder with your own logic if you want to allow this type."` + + + +
+ +--- + + + +## RegisterForbiddenType + +Use `RegisterForbiddenType` to prevent the deserialization of a specific type. + +```csharp +public void RegisterForbiddenType(Type type) +``` + +
+ +| Parameter | Type | Description | +|-----------|------|-------------| +| **type** | `Type` | The type whose deserialization will be blocked. | + + + +Attempting to deserialize a forbidden type throws: +`InvalidOperationException: "Cannot resolve type '' because the type is on a blacklist due to security reasons. Please customize json deserializer in the conventions and override SerializationBinder with your own logic if you want to allow this type."` + + + +
+ +--- + + + +## RegisterSafeType + +Use `RegisterSafeType` to explicitly allow the deserialization of a specific type, overriding any namespace-level block that would otherwise apply. + +```csharp +public void RegisterSafeType(Type type) +``` + +
+ +| Parameter | Type | Description | +|-----------|------|-------------| +| **type** | `Type` | The type whose deserialization will be permitted. | + +
+ +
+ + + +The following example creates a `DefaultRavenSerializationBinder` instance, registers a forbidden namespace, a forbidden type, and a trusted type, then applies it to the document store: + +```csharp +// Create a new deserialization binder instance +var binder = new DefaultRavenSerializationBinder(); + +// Block all types in this namespace +binder.RegisterForbiddenNamespace("SuspiciousNamespace"); + +// Block a specific type +binder.RegisterForbiddenType(typeof(SuspiciousClass)); + +// Explicitly allow a specific type (overrides any namespace block) +binder.RegisterSafeType(typeof(TrustedClass)); + +var store = new DocumentStore +{ + Conventions = + { + Serialization = new NewtonsoftJsonSerializationConventions + { + // Apply the binder to the deserializer + CustomizeJsonDeserializer = deserializer => + deserializer.SerializationBinder = binder + } + } +}; +``` + + diff --git a/versioned_docs/version-7.1/client-api/security/_category_.json b/versioned_docs/version-7.1/client-api/security/_category_.json index e9e2bab6c4..360f66e504 100644 --- a/versioned_docs/version-7.1/client-api/security/_category_.json +++ b/versioned_docs/version-7.1/client-api/security/_category_.json @@ -1,4 +1,4 @@ { "position": 14, - "label": Security, + "label": "Security", } \ No newline at end of file diff --git a/versioned_docs/version-7.1/client-api/security/content/_deserialization-security-csharp.mdx b/versioned_docs/version-7.1/client-api/security/content/_deserialization-security-csharp.mdx index 21635f49c7..c4d5002aa6 100644 --- a/versioned_docs/version-7.1/client-api/security/content/_deserialization-security-csharp.mdx +++ b/versioned_docs/version-7.1/client-api/security/content/_deserialization-security-csharp.mdx @@ -2,202 +2,223 @@ import Admonition from '@theme/Admonition'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import Panel from "@site/src/components/Panel"; +import ContentFrame from "@site/src/components/ContentFrame"; -* Data deserialization can trigger the execution of gadgets that - may initiate RCE attacks on the client machine. -* To handle this threat, RavenDB's default deserializer blocks the - deserialization of known [`.NET` RCE gadgets](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#known-net-rce-gadgets). -* Users can easily modify the list of namespaces and object types - that deserialization is forbidden or allowed for. - -* In this page: - * [Securing Deserialization](../../../client-api/security/deserialization-security.mdx#securing-deserialization) - * [Invoking a Gadget](../../../client-api/security/deserialization-security.mdx#invoking-a-gadget) - * [DefaultRavenSerializationBinder](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) - * [RegisterForbiddenNamespace](../../../client-api/security/deserialization-security.mdx#section) - * [RegisterForbiddenType](../../../client-api/security/deserialization-security.mdx#section-1) - * [RegisterSafeType](../../../client-api/security/deserialization-security.mdx#section-2) - * [Example](../../../client-api/security/deserialization-security.mdx#example) +* Deserializing data can trigger the execution of gadgets that may initiate RCE (Remote Code Execution) attacks on the client machine. +* To handle this threat, RavenDB's default deserializer blocks the deserialization of known [.NET RCE gadgets](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#known-net-rce-gadgets). +* Users can customize the list of namespaces and types for which deserialization is forbidden or allowed. + +* In this article: + * [Securing deserialization](../../../client-api/security/deserialization-security.mdx#securing-deserialization) + * [The deserialization risk](../../../client-api/security/deserialization-security.mdx#the-deserialization-risk) + * [Direct vs. indirect gadget loading](../../../client-api/security/deserialization-security.mdx#direct-vs-indirect-gadget-loading) + * [DefaultRavenSerializationBinder](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) + * [RegisterForbiddenNamespace](../../../client-api/security/deserialization-security.mdx#registerforbiddennamespace) + * [RegisterForbiddenType](../../../client-api/security/deserialization-security.mdx#registerforbiddentype) + * [RegisterSafeType](../../../client-api/security/deserialization-security.mdx#registersafetype) + * [Example](../../../client-api/security/deserialization-security.mdx#example) -## Securing Deserialization - -* When a RavenDB client uses the [Newtonsoft library](https://www.newtonsoft.com/json/help/html/SerializingJSON.htm) - to deserialize a JSON string to a `.NET` object, the object may include - a reference to a **gadget** (a code segment) and the deserialization - process may execute this gadget. -* Some gadgets attempt to exploit the deserialization process and initiate - an RCE (Remote Code Execution) attack that may, for example, inject the - system with malicious code. RCE attacks may sabotage the system, gain - control over it, steal information, and so on. -* To prevent such exploitation, RavenDB's default deserializer - blocks deserialization for suspicious namespaces and - [known `.NET` RCE gadgets](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#known-net-rce-gadgets): - `System.Configuration.Install.AssemblyInstaller` - `System.Activities.Presentation.WorkflowDesigner` - `System.Windows.ResourceDictionary` - `System.Windows.Data.ObjectDataProvider` - `System.Windows.Forms.BindingSource` - `Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvider` - `System.Data.DataViewManager, System.Xml.XmlDocument/XmlDataDocument` - `System.Management.Automation.PSObject` - -* Users can easily [modify](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) - the list of namespaces and object types for which deserialization is forbidden - or allowed. - - - -## Invoking a Gadget - -* **Directly-loaded gadgets Cannot be blocked using the default binder**. - When a gadget is loaded directly its loading and execution during - deserialization is **permitted** regardless of the content of the - default deserializer list. - - E.g., the following segment will be executed, - - -{`// The object will be allowed to be deserialized -// regardless of the default binder list. + + + + + +## The deserialization risk + +* When a RavenDB client uses the [Newtonsoft library](https://www.newtonsoft.com/json/help/html/SerializingJSON.htm) to deserialize a JSON string to a .NET object, + the object may include a reference to a **gadget** (a code segment) and the deserialization process may execute it. +* Some gadgets attempt to exploit the deserialization process and initiate an RCE (Remote Code Execution) attack that may, + for example, inject the system with malicious code, steal information, or take control of the machine. +* To prevent such exploitation, RavenDB's default deserializer blocks deserialization for the `Microsoft.VisualStudio` namespace + and for the following known .NET RCE gadgets: + + - `System.Configuration.Install.AssemblyInstaller` + - `System.Activities.Presentation.WorkflowDesigner` + - `System.Windows.ResourceDictionary` + - `System.Windows.Data.ObjectDataProvider` + - `System.Windows.Forms.BindingSource` + - `Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvider` + - `System.Data.DataViewManager` + - `System.Xml.XmlDocument` + - `System.Xml.XmlDataDocument` + - `System.Management.Automation.PSObject` + +* Users can [customize](../../../client-api/security/deserialization-security.mdx#defaultravenserializationbinder) the list of namespaces and types for which deserialization is forbidden or allowed. + + + +--- + + + +## Direct vs. indirect gadget loading + +**Directly-loaded gadgets cannot be blocked** using `DefaultRavenSerializationBinder`. +When a gadget is loaded directly, its execution during deserialization is permitted regardless of the binder's forbidden list. + +For example, the following `Load` call will succeed regardless of the binder configuration: + +```csharp +// The object will be allowed to be deserialized +// regardless of the binder list. session.Load("Gadget"); -`} - - - -* **Indirectly-loaded gadgets Can be blocked using the default binder**. - When a gadget is loaded indirectly its loading and execution during - deserialization **can be blocked** using the default deserializer list. - - E.g., in the following sample, taken [from here](https://book.hacktricks.xyz/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net#abusing-json.net), - a gadget is loaded indirectly: its name is included as a value - and will only take its place and be used to execute the gadget - during deserialization. - Including this type in the default deserialization list will - prevent the gadget's deserialization and execution. - - -{`string userdata = @"\{ - '$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, - Culture=neutral, PublicKeyToken=31bf3856ad364e35', - 'MethodName':'Start', - 'MethodParameters':\{ - '$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, - Culture=neutral, PublicKeyToken=b77a5c561934e089', - '$values':['cmd', '/c calc.exe'] - \}, - 'ObjectInstance':\{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, - Culture=neutral, PublicKeyToken=b77a5c561934e089'\} -\}"; -`} - - - - - - -## `DefaultRavenSerializationBinder` - -Use the `DefaultRavenSerializationBinder` convention and its methods to -block the deserialization of suspicious namespaces and object types or -allow the deserialization of trusted object types. - -Define a `DefaultRavenSerializationBinder` instance, use the dedicated -methods to forbid or allow the deserialization of entities, and register -the defined instance as a serialization convention as shown -[below](../../../client-api/security/deserialization-security.mdx#example). +``` + +
+ +**Indirectly-loaded gadgets can be blocked** using `DefaultRavenSerializationBinder`. +When a gadget type name is embedded as a value inside a JSON string, it is resolved only at deserialization time. At that point the binder can intercept and block it. + +For example, in the following payload (taken from [this source](https://book.hacktricks.xyz/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net#abusing-json.net)), the type is not loaded directly but appears as a JSON value and is resolved only during deserialization: + +```json +{ + "$type": "System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35", + "MethodName": "Start", + "MethodParameters": { + "$type": "System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", + "$values": ["cmd", "/c calc.exe"] + }, + "ObjectInstance": { + "$type": "System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" + } +} +``` + +
+ +Including `System.Windows.Data.ObjectDataProvider` in the forbidden list prevents this payload from being deserialized and executed. + + + + + + + +Use `DefaultRavenSerializationBinder` and its methods to block the deserialization of suspicious namespaces and types, +or to explicitly allow the deserialization of trusted types. + +Create a new `DefaultRavenSerializationBinder` instance, call the registration methods to define your overrides, +then configure the instance as a serialization convention as shown in the [example](../../../client-api/security/deserialization-security.mdx#example). -Be sure to update the default deserializer list **before** the initialization -of the document that you want the list to apply to. + +All `Register*` methods must be called **before** the binder processes its first type. +Calling any registration method after the binder has been used throws: +`InvalidOperationException: "Cannot perform this operation, because binder was already used."` + +Note that `DefaultRavenSerializationBinder.Instance` is a shared static singleton. +Always create your own `new DefaultRavenSerializationBinder()` instance; do not call registration methods on the static instance. + -### `RegisterForbiddenNamespace` -Use `RegisterForbiddenNamespace` to prevent the deserialization of objects loaded from a given namespace. - - - -{`public void RegisterForbiddenNamespace(string @namespace) -`} - - - - | Parameter | Type | Description | - |:-------------:|:-------------:|-------------| - | **@namespace** | `string` | The name of a namespace from which deserialization won't be allowed. | - - - Attempting to deserialize a forbidden namespace will throw an - `InvalidOperationException` exception with the following details: - _"Cannot resolve type" + `type.FullName` + "because the namespace is on a blacklist due to - security reasons. Please customize json deserializer in the conventions and override SerializationBinder - with your own logic if you want to allow this type."_ - -### `RegisterForbiddenType` -Use `RegisterForbiddenType` to prevent the deserialization of a given object type. - - - -{`public void RegisterForbiddenType(Type type) -`} - - - - | Parameter | Type | Description | - |:-------------:|:-------------:|-------------| - | **type** | `Type` | An object type whose deserialization won't be allowed. | - - - Attempting to deserialize a forbidden object type will throw an - `InvalidOperationException` exception with the following details: - _"Cannot resolve type" + `type.FullName` + "because the type is on a blacklist due to - security reasons. - Please customize json deserializer in the conventions and override SerializationBinder - with your own logic if you want to allow this type."_ - -### `RegisterSafeType` -Use `RegisterSafeType` to **allow** the deserialization of a given object type. - - - -{`public void RegisterSafeType(Type type) -`} - - - - | Parameter | Type | Description | - |:-------------:|:-------------:|-------------| - | **type** | `Type` | An object type whose deserialization **will** be allowed. | - -## Example - - - -{`// Create a default serialization binder -var binder = new DefaultRavenSerializationBinder(); -// Register a forbidden namespace -binder.RegisterForbiddenNamespace("SuspiciousNamespace"); -// Register a forbidden object type -binder.RegisterForbiddenType(suspiciousObject.GetType()); -// Register a trusted object type -binder.RegisterSafeType(trustedObject.GetType()); -var store = new DocumentStore() -\{ - Conventions = - \{ - Serialization = new NewtonsoftJsonSerializationConventions - \{ - // Customize store deserialization using the defined binder - CustomizeJsonDeserializer = deserializer => deserializer.SerializationBinder = binder - \} - \} -\}; -`} - - + + +## RegisterForbiddenNamespace + +Use `RegisterForbiddenNamespace` to prevent the deserialization of any type belonging to the given namespace. + +```csharp +public void RegisterForbiddenNamespace(string @namespace) +``` +
+| Parameter | Type | Description | +|-----------|------|-------------| +| **@namespace** | `string` | The namespace from which deserialization will be blocked. | + +Attempting to deserialize a type whose namespace is forbidden throws: +`InvalidOperationException: "Cannot resolve type '' because the namespace is on a blacklist due to security reasons. Please customize json deserializer in the conventions and override SerializationBinder with your own logic if you want to allow this type."` + + + +
+ +--- + + + +## RegisterForbiddenType + +Use `RegisterForbiddenType` to prevent the deserialization of a specific type. + +```csharp +public void RegisterForbiddenType(Type type) +``` + +
+ +| Parameter | Type | Description | +|-----------|------|-------------| +| **type** | `Type` | The type whose deserialization will be blocked. | + + + +Attempting to deserialize a forbidden type throws: +`InvalidOperationException: "Cannot resolve type '' because the type is on a blacklist due to security reasons. Please customize json deserializer in the conventions and override SerializationBinder with your own logic if you want to allow this type."` + + + +
+ +--- + + + +## RegisterSafeType + +Use `RegisterSafeType` to explicitly allow the deserialization of a specific type, overriding any namespace-level block that would otherwise apply. + +```csharp +public void RegisterSafeType(Type type) +``` + +
+ +| Parameter | Type | Description | +|-----------|------|-------------| +| **type** | `Type` | The type whose deserialization will be permitted. | + +
+ +
+ + + +The following example creates a `DefaultRavenSerializationBinder` instance, registers a forbidden namespace, a forbidden type, and a trusted type, then applies it to the document store: + +```csharp +// Create a new deserialization binder instance +var binder = new DefaultRavenSerializationBinder(); + +// Block all types in this namespace +binder.RegisterForbiddenNamespace("SuspiciousNamespace"); + +// Block a specific type +binder.RegisterForbiddenType(typeof(SuspiciousClass)); + +// Explicitly allow a specific type (overrides any namespace block) +binder.RegisterSafeType(typeof(TrustedClass)); + +var store = new DocumentStore +{ + Conventions = + { + Serialization = new NewtonsoftJsonSerializationConventions + { + // Apply the binder to the deserializer + CustomizeJsonDeserializer = deserializer => + deserializer.SerializationBinder = binder + } + } +}; +``` + +