CA2105: Pola tablicy nie powinny być tylko do odczytu

Pozycja Wartość
Ruleid CA2105
Kategoria Microsoft.Security
Zmiana powodująca niezgodność Kluczowa

Przyczyna

Pole publiczne lub chronione, które zawiera tablicę, jest zadeklarowane tylko do odczytu.

Uwaga

Ta reguła została przestarzała. Aby uzyskać więcej informacji, zobacz Przestarzałe reguły.

Opis reguły

Po zastosowaniu readonly modyfikatora (ReadOnly w Visual Basic) do pola zawierającego tablicę nie można zmienić pola w celu odwoływania się do innej tablicy. Można jednak zmienić elementy tablicy, które są przechowywane w polu tylko do odczytu. Kod, który podejmuje decyzje lub wykonuje operacje oparte na elementach tablicy tylko do odczytu, do których można uzyskać dostęp publicznie, może zawierać lukę w zabezpieczeniach umożliwiającą wykorzystanie.

Należy pamiętać, że posiadanie pola publicznego narusza również regułę projektowania CA1051: Nie deklaruj widocznych pól wystąpienia.

Jak naprawić naruszenia

Aby naprawić lukę w zabezpieczeniach zidentyfikowaną przez tę regułę, nie należy polegać na zawartości tablicy tylko do odczytu, do których można uzyskać dostęp publicznie. Zdecydowanie zaleca się użycie jednej z następujących procedur:

  • Zastąp tablicę silnie typizowanym kolekcją, której nie można zmienić. W celu uzyskania więcej informacji, zobacz następujący temat: System.Collections.ReadOnlyCollectionBase.

  • Zastąp pole publiczne metodą zwracającą klon tablicy prywatnej. Ponieważ kod nie opiera się na klonie, nie ma żadnego zagrożenia, jeśli elementy zostaną zmodyfikowane.

Jeśli wybrano drugie podejście, nie zastąp pola właściwością; właściwości zwracające tablice niekorzystnie wpływają na wydajność. Aby uzyskać więcej informacji, zobacz CA1819: Właściwości nie powinny zwracać tablic.

Kiedy pomijać ostrzeżenia

Wykluczenie ostrzeżenia z tej reguły jest zdecydowanie odradzane. Prawie nie ma scenariuszy, w których zawartość pola tylko do odczytu jest nieistotna. Jeśli tak jest w przypadku scenariusza, usuń readonly modyfikator zamiast wykluczać komunikat.

Przykład 1

W tym przykładzie pokazano niebezpieczeństwa naruszenia tej reguły. W pierwszej części przedstawiono przykładową bibliotekę z typem , MyClassWithReadOnlyArrayFieldktóra zawiera dwa pola (grades i privateGrades), które nie są bezpieczne. Pole grades jest publiczne i dlatego narażone na wszelkie osoby wywołujące. Pole privateGrades jest prywatne, ale nadal jest podatne na zagrożenia, ponieważ jest zwracane do obiektów wywołujących przez metodę GetPrivateGrades . Pole securePrivateGrades jest uwidocznione w bezpieczny sposób przez metodę GetSecurePrivateGrades . Jest zadeklarowana jako prywatna, aby przestrzegać dobrych praktyk projektowych. Druga część przedstawia kod, który zmienia wartości przechowywane w elementach grades i privateGrades .

Przykładowa biblioteka klas zostanie wyświetlona w poniższym przykładzie.

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]);
      }     
   }
}

Przykład 2

Poniższy kod używa przykładowej biblioteki klas do zilustrowania problemów z zabezpieczeniami tablic tylko do odczytu.

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());
      }
   }
}

Dane wyjściowe z tego przykładu to:

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

Zobacz też