rspec/rules/S5773/csharp/rule.adoc
Alban Auzeill 2c306d110e Fix code block ambiguity with old header style
Ensure blank line before list and clean the one leading space
2020-06-30 17:16:12 +02:00

89 lines
5.7 KiB
Plaintext

Failure to control types during deserialization can lead to runtime errors and vulnerabilities. There are many types, called "gadgets" (see https://github.com/pwntester/ysoserial.net[ysoserial.net]) which are known to be not secure when deserializing.
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 <code>https://docs.microsoft.com/en-us/dotnet/api/system.codedom.compiler.tempfilecollection.-ctor?view=netframework-4.8#System_CodeDom_Compiler_TempFileCollection__ctor[TempFileCollection]</code> with arbitrary files defined by the attacker which will be deleted on the application deserializing this object (more precisely 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).
To restrict the types allowed to be deserialized:
* implement a whitelist of safe and required types that can be deserialized.
* or/and implement 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:
----
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:
----
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:
----
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):
----
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):
----
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:
----
LosFormatter formatter = new LosFormatter(true, secret); // Compliant
formatter.Deserialize(fs);
----
== See
* https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf[Are You My Type?] - James Forshaw - BlackHat 2012
* https://www.youtube.com/watch?v=oxlD8VWWHE8[BlueHat v17 - Dangerous Contents - Securing .Net Deserialization]
* https://www.youtube.com/watch?v=qDoBlLwREYk0[Alvaro Muñoz: .NET Serialization: Detecting and Defending Vulnerable Endpoints]
* https://www.owasp.org/index.php/Top_10-2017_A8-Insecure_Deserialization[OWASP Top 10 2017 Category A8] - Insecure Deserialization
* https://cwe.mitre.org/data/definitions/134.html[MITRE, CWE-134] - Use of Externally-Controlled Format String
* https://cwe.mitre.org/data/definitions/502.html[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]