CA2114: La sicurezza del metodo deve essere un superset del tipo
TypeName |
MethodSecurityShouldBeASupersetOfType |
CheckId |
CA2114 |
Category |
Microsoft.Security |
Breaking Change |
Breaking |
Causa
Un tipo presenta sicurezza dichiarativa e uno dei relativi metodi presenta sicurezza dichiarativa per la stessa azione di sicurezza la quale non è Richieste di collegamento o Richieste di ereditarietà. Inoltre, le autorizzazioni controllate dal tipo non sono un sottoinsieme delle autorizzazioni controllate dal metodo.
Descrizione della regola
Un metodo non deve presentare sicurezza dichiarativa sia a livello di metodo che a livello di tipo per la stessa azione. I due controlli non sono combinati; viene applicata solo la richiesta a livello di metodo. Se, ad esempio, un tipo richiede l'autorizzazione X e uno dei relativi metodi richiede l'autorizzazione Y, il codice non necessita dell'autorizzazione X per eseguire il metodo.
Come correggere le violazioni
Rivedere il codice per assicurarsi che entrambe le azioni siano necessarie. Se entrambe le azioni sono necessarie, assicurarsi che l'azione a livello di metodo includa la sicurezza specificata a livello di tipo. Se ad esempio il tipo richiede l'autorizzazione X e il relativo metodo deve anche richiedere l'autorizzazione Y, il metodo deve richiedere esplicitamente sia X che Y.
Esclusione di avvisi
L'esclusione di un avviso da questa regola è sicura se il metodo non richiede la sicurezza specificata dal tipo. Si tratta, tuttavia, di uno scenario non comune che può indicare l'esigenza di un'accurata revisione della progettazione.
Esempio
Nell'esempio riportato di seguito vengono utilizzate autorizzazioni di accesso all'ambiente per illustrare i rischi derivanti dalla violazione di questa regola. Nell'esempio, il codice dell'applicazione crea un'istanza del tipo protetto prima di negare l'autorizzazione richiesta dal tipo. In un caso reale di rischio, l'applicazione richiederebbe un altro modo per ottenere un'istanza dell'oggetto.
Nell'esempio riportato di seguito, la libreria richiede l'autorizzazione di scrittura per un tipo e l'autorizzazione di lettura per un metodo.
using System;
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;
namespace SecurityRulesLibrary
{
[EnvironmentPermissionAttribute(SecurityAction.Demand, Write="PersonalInfo")]
public class MyClassWithTypeSecurity
{
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
[return:MarshalAs(UnmanagedType.Bool)]
public static extern bool SetEnvironmentVariable(
string lpName,
string lpValue);
// Constructor.
public MyClassWithTypeSecurity(int year, int month, int day)
{
DateTime birthday = new DateTime(year, month, day);
// Write out PersonalInfo environment variable.
SetEnvironmentVariable("PersonalInfo",birthday.ToString());
}
[EnvironmentPermissionAttribute(SecurityAction.Demand, Read="PersonalInfo")]
public string PersonalInformation ()
{
// Read the variable.
return Environment.GetEnvironmentVariable("PersonalInfo");
}
}
}
Il codice dell'applicazione riportato di seguito dimostra la vulnerabilità della libreria chiamando il metodo anche se non soddisfa il requisito di sicurezza a livello di tipo.
using System;
using System.Security;
using System.Security.Permissions;
using SecurityRulesLibrary;
namespace TestSecRulesLibrary
{
public class TestMethodLevelSecurity
{
MyClassWithTypeSecurity dataHolder;
void RetrievePersonalInformation(string description)
{
try
{
Console.WriteLine(
"{0} Personal information: {1}",
description, dataHolder.PersonalInformation());
}
catch (SecurityException e)
{
Console.WriteLine(
"{0} Could not access personal information: {1}",
description, e.Message);
}
}
[STAThread]
public static void Main()
{
TestMethodLevelSecurity me = new TestMethodLevelSecurity();
me.dataHolder = new MyClassWithTypeSecurity(1964,06,16);
// Local computer zone starts with all environment permissions.
me.RetrievePersonalInformation("[All permissions]");
// Deny the write permission required by the type.
EnvironmentPermission epw = new EnvironmentPermission(
EnvironmentPermissionAccess.Write,"PersonalInfo");
epw.Deny();
// Even though the type requires write permission,
// and you do not have it; you can get the data.
me.RetrievePersonalInformation(
"[No write permission (demanded by type)]");
// Reset the permissions and try to get
// data without read permission.
CodeAccessPermission.RevertAll();
// Deny the read permission required by the method.
EnvironmentPermission epr = new EnvironmentPermission(
EnvironmentPermissionAccess.Read,"PersonalInfo");
epr.Deny();
// The method requires read permission, and you
// do not have it; you cannot get the data.
me.RetrievePersonalInformation(
"[No read permission (demanded by method)]");
}
}
}
Questo esempio produce l'output che segue.
Vedere anche
Concetti
Linee guida per la generazione di codice sicuro