CA2105: Campos de matriz não devem ser lidos apenas

TypeName

ArrayFieldsShouldNotBeReadOnly

CheckId

CA2105

<strong>Categoria</strong>

Microsoft.Security

Alteração significativa

Quebrando

Causa

Um campo público ou protegido que mantém uma matriz é declarado como somente leitura.

Descrição da regra

Quando você aplica a readonly (ReadOnly na Visual Basic) o modificador de um campo que contém uma matriz, o campo não pode ser alterado para se referir a um array diferente. No entanto, os elementos da matriz são armazenados em um campo somente leitura podem ser alterados. Código que toma decisões ou executa operações que são baseadas nos elementos de uma matriz de somente leitura que podem ser acessadas publicamente pode conter uma vulnerabilidade de segurança pode ser explorada.

Observe que também ter um campo público viola a regra de design CA1051: Não declarar os campos de instância visível.

Como corrigir violações

Para corrigir a vulnerabilidade de segurança que é identificada por esta regra, não confie no conteúdo de uma matriz de somente leitura que podem ser publicamente acessados. É altamente recomendável que você use um dos seguintes procedimentos:

  • Substitua a matriz uma coleção fortemente tipada que não pode ser alterada. Para obter mais informações, consulte System.Collections.ReadOnlyCollectionBase.

  • Substitua o campo público com um método que retorna um clone de um array privado. Como seu código não dependem do clone, não há nenhum risco se os elementos forem modificados.

Se você escolher a segunda abordagem, não substitua o campo com uma propriedade; propriedades que retornam matrizes contrariamente afetam o desempenho. Para obter mais informações, consulte CA1819: Propriedades não devem retornar arrays.

Quando suprimir avisos

Exclusão de um aviso de que essa regra é altamente desencorajado. Quase nenhum cenário ocorre onde o conteúdo de um campo somente leitura não é importante. Se for esse o caso com o seu cenário, remova o readonly modificador em vez de excluir a mensagem.

Exemplo

Este exemplo demonstra os perigos de violar a essa regra. A primeira parte mostra uma biblioteca de exemplo possui um tipo de MyClassWithReadOnlyArrayField, que contém dois campos (grades e privateGrades) que não são seguras. O campo grades é pública e portanto vulnerável a qualquer chamador. O campo privateGrades é privado mas ainda estará vulnerável porque ele é retornado para chamadores pelo GetPrivateGrades método. O securePrivateGrades campo é exposto de maneira segura, o GetSecurePrivateGrades método. Ele é declarado como privado seguir práticas recomendadas de um bom design. A segunda parte mostra o código que altera os valores armazenados na grades e privateGrades membros.

A biblioteca de classe do exemplo é exibida no exemplo a seguir.

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

O código a seguir usa a biblioteca de classe de exemplo para ilustrar os problemas de segurança do array de somente leitura.

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

A saída deste exemplo é:

  

Consulte também

Referência

System.Array

System.Collections.ReadOnlyCollectionBase