Proteggere gli override di GetObjectData
TypeName |
SecureGetObjectDataOverrides |
CheckId |
CA2110 |
Category |
Microsoft.Security |
Breaking Change |
Breaking |
Causa
Un metodo è denominato GetObjectData
, è dichiarato in un tipo che implementa l'interfaccia System.Runtime.Serialization.ISerializable e accetta un oggetto System.Runtime.Serialization.SerializationInfo e un oggetto System.Runtime.Serialization.StreamingContext come parametri. Il metodo non è protetto da una richiesta per l'autorizzazione di protezione System.Security.Permissions.SecurityPermissionAttribute.SerializationFormatter.
Descrizione della regola
Il metodo System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext) è dichiarato nell'interfaccia ISerializable. Questa interfaccia è implementata da tipi che forniscono logica di serializzazione personalizzata. GetObjectData è protetto da un controllo di protezione per l'autorizzazione di protezione System.Security.Permissions.SecurityPermissionAttribute.SerializationFormatter. Se un'implementazione di GetObjectData non è protetta dallo stesso controllo di protezione, i chiamanti possono chiamare l'implementazione per ignorare la protezione sull'interfaccia e ottenere accesso ai dati serializzati dal tipo.
Correzione di violazioni
Per correggere una violazione di questa regola, applicare il seguente attributo al metodo GetObjectData
:
[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)]
.
Esclusione di avvisi
Non escludere un avviso da questa regola.
Esempio
Nel codice riportato di seguito viene illustrata una libreria che viola la regola e un'applicazione che sfrutta i punti deboli della libreria.
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security;
using System.Security.Permissions;
namespace SecurityRulesLibrary
{
[Serializable]
public class MySerializableObject :ISerializable
{
private int n1;
private DateTime date;
private string str;
private MySerializableObject (){}
public MySerializableObject (string s, int num1)
{
n1 = num1;
str = (s == null ? "<empty>" : s);
// This value is intended to be private and unviewable.
date = DateTime.Today;
}
public MySerializableObject(SerializationInfo info, StreamingContext context)
{
n1 = (int) info.GetValue("n1", typeof(int));
date = (DateTime) info.GetValue("date", typeof(DateTime));
str = (string) info.GetValue("str", typeof(string));
}
// The ISerializable interface member that provides the serialization logic.
// Violates rule: GetObjectDataRequiresSerializationFormatterSecurityPermissionAttribute.
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("n1", n1);
info.AddValue("date", date);
info.AddValue("str", str);
}
}
}
Il codice riportato di seguito sfrutta i punti deboli della libreria.
using System;
using System.Security;
using System.Security.Permissions;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using SecurityRulesLibrary;
using System.Reflection;
[assembly: SecurityPermissionAttribute(
SecurityAction.RequestRefuse, SerializationFormatter=true)]
namespace TestSecurityLibrary
{
public class TestGetObjectData
{
int n1;
DateTime date;
string str;
SerializationInfo info = new SerializationInfo(
typeof(MySerializableObject),
new FormatterConverter());
StreamingContext context = new StreamingContext(
StreamingContextStates.All);
private void GetInformation(SerializationInfo info)
{
// Use the SerializationInfo to look at all of
// the serialized object's private data.
n1 = info.GetInt32("n1");
date = info.GetDateTime("date");
str = info.GetString("str");
}
private void GetTheObjectDirectly (MySerializableObject obj)
{
// Bypasses security that protects the interface.
obj.GetObjectData(info, context);
GetInformation(info);
Console.WriteLine("Directly: {0}, {1}, {2}", str, n1, date);
}
private void GetTheObjectThroughInterface (MySerializableObject obj)
{
// This call causes a security exception in a type that does
// not have SerializationFormatter security permission.
((ISerializable)obj).GetObjectData(info, context);
GetInformation(info);
Console.WriteLine(
"ISerializable: {0}, {1}, {2}", str, n1, date);
}
public static void Main()
{
// Get an instance of the object.
MySerializableObject anObject =
new MySerializableObject("test", 1);
// Call GetObjectData directly and
// then call through the interface.
TestGetObjectData getDirect = new TestGetObjectData();
// Succeeds - Bypasses the security on the interface.
getDirect.GetTheObjectDirectly (anObject);
TestGetObjectData getIndirect = new TestGetObjectData();
try
{
// Fails - Shows the security on the interface.
getIndirect.GetTheObjectThroughInterface (anObject);
}
catch (SecurityException e)
{
Console.WriteLine(
"Object cannot be accessed through the interface - {0}",
e.Message);
}
}
}
}
Questo esempio produce l'output che segue.
Output
Directly: test, 1, 7/30/2002 12:00:00 AM Object cannot be accessed through the interface - Request for the permission of type System.Security.Permissions.SecurityPermission, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 failed.
Regole correlate
Proteggere i costruttori di serializzazione
Implementare costruttori di serializzazione
Contrassegnare i tipi ISerializable con Serializable
Le richieste di collegamento negli override devono essere identiche a quelle nei metodi di base
Vedere anche
Riferimenti
System.Runtime.Serialization.ISerializable
System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)
System.Runtime.Serialization.SerializationInfo
System.Runtime.Serialization.StreamingContext
System.Security.Permissions.SecurityPermissionAttribute.SerializationFormatter