
Inline adoc files when they are included exactly once. Also fix language tags because this inlining gives us better information on what language the code is written in.
125 lines
6.5 KiB
Plaintext
125 lines
6.5 KiB
Plaintext
== Why is this an issue?
|
|
|
|
:link-with-uscores1: https://docs.microsoft.com/en-us/dotnet/api/system.codedom.compiler.tempfilecollection.-ctor?view=netframework-4.8#System_CodeDom_Compiler_TempFileCollection__ctor
|
|
|
|
During the deserialization process, the state of an object will be reconstructed from the serialized data stream which can contain dangerous operations.
|
|
|
|
|
|
For example, a well-known attack vector consists in serializing an object of type ``{link-with-uscores1}[TempFileCollection]`` with arbitrary files (defined by an attacker) which will be deleted on the application deserializing this object (when the https://docs.microsoft.com/en-us/dotnet/api/system.codedom.compiler.tempfilecollection.finalize?view=netframework-4.8[finalize() ]method of the TempFileCollection object is called). This kind of types are called "https://github.com/pwntester/ysoserial.net[gadgets]".
|
|
|
|
|
|
Instead of using ``++BinaryFormatter++`` and similar serializers, it is recommended to use safer alternatives in most of the cases, such as https://docs.microsoft.com/en-us/dotnet/api/system.xml.serialization.xmlserializer?view=net-5.0[XmlSerializer] or https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.datacontractserializer?view=net-5.0[DataContractSerializer]. If it's not possible then try to mitigate the risk by restricting the types allowed to be deserialized:
|
|
|
|
* by implementing an "allow-list" of types, but keep in mind that novel dangerous types are regularly discovered and this protection could be insufficient over time.
|
|
* or/and implementing a tamper protection, such as https://en.wikipedia.org/wiki/HMAC[message authentication codes] (MAC). This way only objects serialized with the correct MAC hash will be deserialized.
|
|
|
|
=== Noncompliant code example
|
|
|
|
For https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.formatters.binary.binaryformatter?view=netframework-4.8[BinaryFormatter], https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.netdatacontractserializer?view=netframework-4.8[NetDataContractSerializer], https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.formatters.soap.soapformatter?view=netframework-4.8[SoapFormatter] serializers:
|
|
|
|
[source,csharp]
|
|
----
|
|
var myBinaryFormatter = new BinaryFormatter();
|
|
myBinaryFormatter.Deserialize(stream); // Noncompliant: a binder is not used to limit types during deserialization
|
|
----
|
|
|
|
https://docs.microsoft.com/en-us/dotnet/api/system.web.script.serialization.javascriptserializer?view=netframework-4.8[JavaScriptSerializer] should not use SimpleTypeResolver or other weak resolvers:
|
|
|
|
[source,csharp]
|
|
----
|
|
JavaScriptSerializer serializer1 = new JavaScriptSerializer(new SimpleTypeResolver()); // Noncompliant: SimpleTypeResolver is unsecure (every types is resolved)
|
|
serializer1.Deserialize<ExpectedType>(json);
|
|
----
|
|
|
|
https://docs.microsoft.com/en-us/dotnet/api/system.web.ui.losformatter?view=netframework-4.8[LosFormatter] should not be used without MAC verification:
|
|
|
|
[source,csharp]
|
|
----
|
|
LosFormatter formatter = new LosFormatter(); // Noncompliant
|
|
formatter.Deserialize(fs);
|
|
----
|
|
|
|
=== Compliant solution
|
|
|
|
https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.formatters.binary.binaryformatter?view=netframework-4.8[BinaryFormatter], https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.netdatacontractserializer?view=netframework-4.8[NetDataContractSerializer ], https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.formatters.soap.soapformatter?view=netframework-4.8[SoapFormatter] serializers should use a binder implementing a whitelist approach to limit types during deserialization (at least one exception should be thrown or a null value returned):
|
|
|
|
[source,csharp]
|
|
----
|
|
sealed class CustomBinder : SerializationBinder
|
|
{
|
|
public override Type BindToType(string assemblyName, string typeName)
|
|
{
|
|
if (!(typeName == "type1" || typeName == "type2" || typeName == "type3"))
|
|
{
|
|
throw new SerializationException("Only type1, type2 and type3 are allowed"); // Compliant
|
|
}
|
|
return Assembly.Load(assemblyName).GetType(typeName);
|
|
}
|
|
}
|
|
|
|
var myBinaryFormatter = new BinaryFormatter();
|
|
myBinaryFormatter.Binder = new CustomBinder();
|
|
myBinaryFormatter.Deserialize(stream);
|
|
----
|
|
|
|
https://docs.microsoft.com/en-us/dotnet/api/system.web.script.serialization.javascriptserializer?view=netframework-4.8[JavaScriptSerializer] should use a resolver implementing a whitelist to limit types during deserialization (at least one exception should be thrown or a null value returned):
|
|
|
|
[source,csharp]
|
|
----
|
|
public class CustomSafeTypeResolver : JavaScriptTypeResolver
|
|
{
|
|
public override Type ResolveType(string id)
|
|
{
|
|
if(id != "ExpectedType") {
|
|
throw new ArgumentNullException("Only ExpectedType is allowed during deserialization"); // Compliant
|
|
}
|
|
return Type.GetType(id);
|
|
}
|
|
}
|
|
|
|
JavaScriptSerializer serializer = new JavaScriptSerializer(new CustomSafeTypeResolver()); // Compliant
|
|
serializer.Deserialize<ExpectedType>(json);
|
|
----
|
|
https://docs.microsoft.com/en-us/dotnet/api/system.web.ui.losformatter?view=netframework-4.8[LosFormatter] serializer with MAC verification:
|
|
|
|
[source,csharp]
|
|
----
|
|
LosFormatter formatter = new LosFormatter(true, secret); // Compliant
|
|
formatter.Deserialize(fs);
|
|
----
|
|
|
|
== Resources
|
|
|
|
* https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures/[OWASP Top 10 2021 Category A8] - Software and Data Integrity Failures
|
|
* https://docs.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide?s=03[docs.microsoft.com] - BinaryFormatter security guide
|
|
* https://owasp.org/www-project-top-ten/2017/A8_2017-Insecure_Deserialization[OWASP Top 10 2017 Category A8] - Insecure Deserialization
|
|
* https://cwe.mitre.org/data/definitions/134[MITRE, CWE-134] - Use of Externally-Controlled Format String
|
|
* https://cwe.mitre.org/data/definitions/502[MITRE, CWE-502] - Deserialization of Untrusted Data
|
|
* https://www.sans.org/top25-software-errors/#cat2[SANS Top 25] - Risky Resource Management
|
|
* https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Deserialization_Cheat_Sheet.md[OWASP Deserialization Cheat Sheet]
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
include::../message.adoc[]
|
|
|
|
=== Highlighting
|
|
|
|
Primary: See the code examples
|
|
|
|
Secondary:
|
|
|
|
* When a `JavaScriptTypeResolver` is used, on the `ResolveType` method
|
|
* message: "This method allows all types."
|
|
|
|
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
include::../comments-and-links.adoc[]
|
|
endif::env-github,rspecator-view[]
|