CA2105: Arrayfelder dürfen nicht schreibgeschützt sein
TypeName |
ArrayFieldsShouldNotBeReadOnly |
CheckId |
CA2105 |
Kategorie |
Microsoft.Security |
Unterbrechende Änderung |
Breaking |
Ursache
Ein öffentliches oder geschütztes Feld, das ein Array enthält, ist als schreibgeschützt deklariert.
Regelbeschreibung
Wenn Sie den readonly-Modifizierer (ReadOnly in Visual Basic) auf ein Feld anwenden, das ein Array enthält, kann das Feld nicht dahingehend geändert werden, dass es auf ein anderes Array verweist. Allerdings können die in einem schreibgeschützten Feld des Arrays gespeicherten Elemente geändert werden. Code, von dem auf der Grundlage der Elemente eines öffentlichen schreibgeschützten Arrays Entscheidungen getroffen oder Vorgänge ausgeführt werden, enthält unter Umständen eine Sicherheitslücke.
Das Vorhandensein eines öffentlichen Felds verstößt außerdem gegen die Entwurfsregel CA1051: Sichtbare Instanzfelder nicht deklarieren.
Behandeln von Verstößen
Verlassen Sie sich zum Beheben der durch diese Regel ermittelten Sicherheitslücke nicht auf den Inhalt eines öffentlich zugänglichen schreibgeschützten Arrays. Es wird dringend empfohlen, eines der folgenden Verfahren zu verwenden:
Ersetzen Sie das Array durch eine stark typisierte Auflistung, die nicht geändert werden kann. Weitere Informationen finden Sie unter System.Collections.ReadOnlyCollectionBase.
Ersetzen Sie das öffentliche Feld durch eine Methode, die einen Klon eines privaten Arrays zurückgibt. Da der Code nicht auf den Klon angewiesen ist, besteht keine Gefahr, wenn die Elemente geändert werden.
Wenn Sie den zweiten Ansatz wählen, ersetzen Sie das Feld nicht durch eine Eigenschaft, da die Leistung durch Eigenschaften, die Arrays zurückgeben, beeinträchtigt wird. Weitere Informationen finden Sie unter CA1819: Eigenschaften sollten keine Arrays zurückgeben.
Wann sollten Warnungen unterdrückt werden?
Es wird dringend davon abgeraten, eine Warnung dieser Regel auszuschließen. Es gibt praktisch keine Szenarien, bei denen der Inhalt eines schreibgeschützten Felds unwichtig ist. Wenn dies auf Ihr Szenario zutrifft, entfernen Sie den readonly-Modifizierer, anstatt die Meldung auszuschließen.
Beispiel
In diesem Beispiel werden die Gefahren bei einem Verstoß gegen diese Regel veranschaulicht. Im ersten Teil wird eine Beispielbibliothek mit einem Typ MyClassWithReadOnlyArrayField dargestellt, die zwei Felder (grades und privateGrades) enthält, die nicht sicher sind. Das grades-Feld ist öffentlich und kann daher von jedem Aufrufer angegriffen werden. Das privateGrades-Feld ist privat, aber dennoch gefährdet, da es durch die GetPrivateGrades-Methode an Aufrufer zurückgegeben wird. Das securePrivateGrades-Feld wird auf sichere Weise durch die GetSecurePrivateGrades-Methode verfügbar gemacht. Es ist im Einklang mit empfohlenen Entwurfsvorgehensweisen als privat deklariert. Der zweite Teil enthält Code, der im grades-Member und im privateGrades-Member gespeicherte Werte ändert.
Die Beispielklassenbibliothek wird im folgenden Beispiel angezeigt.
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]);
}
}
}
Im folgenden Code werden anhand der Beispielklassenbibliothek Sicherheitsprobleme schreibgeschützter Arrays veranschaulicht.
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());
}
}
}
Ausgabe dieses Beispiels: