Les champs de tableau ne doivent pas être en lecture seule
Mise à jour : novembre 2007
TypeName |
ArrayFieldsShouldNotBeReadOnly |
CheckId |
CA2105 |
Catégorie |
Microsoft.Security |
Modification avec rupture |
Oui |
Cause
Un champ public ou protégé qui contient un tableau est déclaré en lecture seule.
Description de la règle
Lorsque vous appliquez le modificateur readonly (ReadOnly en Visual Basic) à un champ qui contient un tableau, ce champ ne peut pas être modifié pour référencer un tableau différent. Toutefois, les éléments du tableau stockés dans un champ en lecture seule peuvent être modifiés. Un code qui prend des décisions ou exécute des opérations en fonction des éléments d'un tableau en lecture seule accessible publiquement peut présenter une faille de sécurité exploitable.
Notez que la présence d'un champ public viole également la règle de conception Ne pas déclarer de champs d'instances visibles.
Comment corriger les violations
Pour corriger la faille de sécurité identifiée par cette règle, ne vous fondez pas sur le contenu d'un tableau en lecture seule accessible publiquement. Il est fortement recommandé d'utiliser l'une des procédures suivantes :
Remplacez le tableau par une collection fortement typée qui ne peut pas être modifiée. Pour plus d'informations, consultez System.Collections.ReadOnlyCollectionBase
Remplacez le champ public par une méthode qui retourne un clone d'un tableau privé. Votre code ne repose pas sur le clone ; aussi, n'y a-t-il aucun danger si les éléments sont modifiés.
Si vous avez opté pour la deuxième approche, ne remplacez pas le champ par une propriété ; les propriétés qui retournent des tableaux influencent défavorablement les performances. Pour plus d'informations, consultez Les propriétés ne doivent pas retourner des tableaux.
Quand supprimer les avertissements
L'exclusion d'un avertissement issu de cette règle est fortement déconseillée. Il n'existe pratiquement aucun scénario dans lequel le contenu d'un champ en lecture seule est d'importance négligeable. Si c'est le cas dans votre scénario, supprimez le modificateur readonly au lieu d'exclure le message.
Exemple
Cet exemple montre les dangers inhérents à la violation de cette règle. La première partie présente l'exemple d'une bibliothèque dotée d'un type, MyClassWithReadOnlyArrayField, contenant deux champs (grades et privateGrades) non sécurisés. Le champ grades est public, et par conséquent vulnérable pour tout appelant. Le champ privateGrades est privé, mais reste vulnérable parce qu'il est retourné aux appelants par la méthode GetPrivateGrades. Le champ securePrivateGrades est exposé de manière sûre par la méthode GetSecurePrivateGrades. Il est déclaré comme privé pour respecter des pratiques conceptuelles optimales. La deuxième partie affiche un code qui modifie des valeurs stockées dans les membres grades et privateGrades.
L'exemple de bibliothèque de classes apparaît dans l'exemple suivant.
using System;
namespace SecurityRulesLibrary
{
public class MyClassWithReadOnlyArrayField
{
public readonly int[] grades = {90, 90, 90};
private readonly int[] privateGrades = {90, 90, 90};
private readonly int[] securePrivateGrades = {90, 90, 90};
// Making the array private does not protect it because it is passed to others.
public int[] GetPrivateGrades()
{
return privateGrades;
}
//This method secures the array by cloning it.
public int[] GetSecurePrivateGrades()
{
return (int[])securePrivateGrades.Clone();
}
public override string ToString()
{
return String.Format("Grades: {0}, {1}, {2} Private Grades: {3}, {4}, {5} Secure Grades, {6}, {7}, {8}",
grades[0], grades[1], grades[2], privateGrades[0], privateGrades[1], privateGrades[2], securePrivateGrades[0], securePrivateGrades[1], securePrivateGrades[2]);
}
}
}
Le code suivant utilise la bibliothèque de classes exemple pour illustrer les problèmes de sécurité liés aux tableaux en lecture seule.
using System;
using SecurityRulesLibrary;
namespace TestSecRulesLibrary
{
public class TestArrayReadOnlyRule
{
[STAThread]
public static void Main()
{
MyClassWithReadOnlyArrayField dataHolder =
new MyClassWithReadOnlyArrayField();
// Get references to the library's readonly arrays.
int[] theGrades = dataHolder.grades;
int[] thePrivateGrades = dataHolder.GetPrivateGrades();
int[] theSecureGrades = dataHolder.GetSecurePrivateGrades();
Console.WriteLine(
"Before tampering: {0}", dataHolder.ToString());
// Overwrite the contents of the "readonly" array.
theGrades[1]= 555;
thePrivateGrades[1]= 555;
theSecureGrades[1]= 555;
Console.WriteLine(
"After tampering: {0}",dataHolder.ToString());
}
}
}
Le résultat généré par cet exemple est le suivant :
Before tampering: Grades: 90, 90, 90 Private Grades: 90, 90, 90 Secure Grades, 90, 90, 90
After tampering: Grades: 90, 555, 90 Private Grades: 90, 555, 90 Secure Grades, 90, 90, 90