Compartilhar via


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

TypeName

ArrayFieldsShouldNotBeReadOnly

CheckId

CA2105

Category (Categoria)

Microsoft.Security

Alteração Significativa

Quebra

Causa

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

Descrição da Regra

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

Observe que ter um campo público também 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 somente leitura que pode ser acessada publicamente.É altamente recomendável que você use um dos seguintes procedimentos:

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

  • Substitua o campo público com um método que retorna um clone de uma matriz particular.Porque seu código não confia no clone, não há risco se os elementos forem alterados.

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

Quando Suprimir Alertas

A exclusão de um aviso dessa regra é fortemente desencorajada.Quase não existe cenário onde o conteúdo de um campo somente leitura não é importante.Se este é o caso com seu cenário, remova o modificador de readonly em vez de excluir a mensagem.

Exemplo

Este exemplo demonstra os perigos de violar esta regra.A primeira parte do exemplo mostra uma biblioteca que tenha um tipo, MyClassWithReadOnlyArrayField, que contém dois campos (grades e privateGrades) que não são seguros.O campo grades é público, e portanto vulnerável a qualquer chamador.O campo privateGrades é particular mas ainda é vulnerável aos chamadores porque é retornado pelo método GetPrivateGrades.O campo securePrivateGrades é exposto de uma maneira segura pelo método GetSecurePrivateGrades.É declarado particular para seguir boas práticas de design.A segunda parte mostra código que modifica valores armazenados nos membros de grades e de privateGrades.

A biblioteca de classes de exemplo é exibido 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 classes de exemplo para ilustrar problemas de segurança com matriz 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 de esse exemplo são:

  

Consulte também

Referência

System.Array

System.Collections.ReadOnlyCollectionBase