rspec/rules/S5766/csharp/rule.adoc

168 lines
4.9 KiB
Plaintext
Raw Normal View History

2020-06-30 12:50:28 +02:00
include::../description.adoc[]
include::../ask-yourself.adoc[]
include::../recommended.adoc[]
== Sensitive Code Example
2020-12-23 14:59:06 +01:00
When a ``serializable`` class doesn't inherit from https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.iserializable?view=netframework-4.8[ISerializable] or https://docs.microsoft.com/fr-fr/dotnet/api/system.runtime.serialization.ideserializationcallback?view=netframework-4.8[IDeserializationCallback] types and has a constructor using its parameters in conditions:
2020-06-30 12:50:28 +02:00
----
[Serializable]
public class InternalUrl
{
private string url;
public InternalUrl(string tmpUrl) // Sensitive
{
if(!tmpUrl.StartsWith("http://localhost/")) // there is some input validation
{
2020-06-30 12:50:28 +02:00
url= "http://localhost/default";
}
else
{
2020-06-30 12:50:28 +02:00
url= tmpUrl;
}
}
}
----
When a class inherit from https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.iserializable?view=netframework-4.8[ISerializable] type, has a regular constructor using its parameters in conditions, but doesn't perform the same validation after deserialization:
2020-06-30 12:50:28 +02:00
----
[Serializable]
public class InternalUrl : ISerializable
{
private string url;
public InternalUrl(string tmpUrl) // Sensitive
{
if(!tmpUrl.StartsWith("http://localhost/")) // there is some input validation
{
url= "http://localhost/default";
}
else
{
url= tmpUrl;
}
2020-06-30 12:50:28 +02:00
}
// special constructor used during deserialization
protected InternalUrl(SerializationInfo info, StreamingContext context) // Sensitive
{
url= (string) info.GetValue("url", typeof(string));
// the same validation as seen in the regular constructor is not performed
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("url", url);
}
}
----
2020-12-23 14:59:06 +01:00
When a class inherit from https://docs.microsoft.com/fr-fr/dotnet/api/system.runtime.serialization.ideserializationcallback?view=netframework-4.8[IDeserializationCallback] type, has a constructor using its parameters in conditions but the ``IDeserializationCallback.OnDeserialization`` method doesn't perform any conditional checks:
2020-06-30 12:50:28 +02:00
----
[Serializable]
public class InternalUrl : IDeserializationCallback
{
private string url;
public InternalUrl(string tmpUrl) // Sensitive
{
if(!tmpUrl.StartsWith("http://localhost/")) // there is some input validation
{
url= "http://localhost/default";
}
else
{
url= tmpUrl;
}
2020-06-30 12:50:28 +02:00
}
void IDeserializationCallback.OnDeserialization(object sender) // Sensitive
{
// the same validation as seen in the constructor is not performed
}
}
----
== Compliant Solution
2020-12-23 14:59:06 +01:00
When using https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.iserializable?view=netframework-4.8[ISerializable] type to control deserialization, perform the same checks inside regular constructors than in the special constructor ``SerializationInfo info, StreamingContext context`` used during deserialization:
2020-06-30 12:50:28 +02:00
----
[Serializable]
public class InternalUrl : ISerializable
{
private string url;
public InternalUrl(string tmpUrl)
{
if(!tmpUrl.StartsWith("http://localhost/")) // there is some input validation
{
url= "http://localhost/default";
}
else
{
url= tmpUrl;
}
2020-06-30 12:50:28 +02:00
}
// special constructor used during deserialization
protected InternalUrl(SerializationInfo info, StreamingContext context)
{
string tmpUrl= (string) info.GetValue("url", typeof(string));
if(!tmpUrl.StartsWith("http://localhost/") { // Compliant
url= "http://localhost/default";
}
else {
url= tmpUrl;
}
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("url", url);
}
}
----
2020-12-23 14:59:06 +01:00
When using https://docs.microsoft.com/fr-fr/dotnet/api/system.runtime.serialization.ideserializationcallback?view=netframework-4.8[IDeserializationCallback] type to control deserialization, perform the same checks inside regular constructors than after deserialization with ``IDeserializationCallback.OnDeserialization`` method:
2020-06-30 12:50:28 +02:00
----
[Serializable]
public class InternalUrl : IDeserializationCallback
{
private string url;
public InternalUrl(string tmpUrl)
{
if(!tmpUrl.StartsWith("http://localhost/")) // there is some input validation
{
2020-06-30 12:50:28 +02:00
url= "http://localhost/default";
}
else
{
2020-06-30 12:50:28 +02:00
url= tmpUrl;
}
}
void IDeserializationCallback.OnDeserialization(object sender) // Compliant
{
if(!url.StartsWith("http://localhost/"))
{
url= "http://localhost/default";
}
else
{
}
2020-06-30 12:50:28 +02:00
}
}
----
include::../see.adoc[]