다음을 통해 공유


CA2105: 배열 필드는 읽기 전용이면 안 됩니다.

TypeName

ArrayFieldsShouldNotBeReadOnly

CheckId

CA2105

범주

Microsoft.Security

변경 수준

주요 변경

원인

배열을 보유하는 public 또는 protected 필드가 읽기 전용으로 선언되었습니다.

규칙 설명

배열이 들어 있는 필드에 readonly(Visual Basic의 경우 ReadOnly) 한정자를 적용하면 필드를 변경하여 다른 배열을 참조할 수 없습니다. 그러나 읽기 전용 필드에 저장된 배열의 요소는 변경할 수 있습니다. 공개적으로 액세스할 수 있는 읽기 전용 배열의 요소를 기반으로 결정을 내리거나 작업을 수행하는 코드에는 보안상 취약한 부분이 있을 수 있습니다.

공용 필드를 사용하면 디자인 규칙 CA1051: 표시되는 인스턴스 필드를 선언하지 마십시오.도 위반하게 됩니다.

위반 문제를 해결하는 방법

이 규칙에 의해 식별된 보안 취약점을 해결하려면 공개적으로 액세스할 수 있는 읽기 전용 배열의 내용은 사용하지 않도록 합니다. 다음 절차 중 하나를 사용하는 것이 좋습니다.

  • 배열을 변경할 수 없는 강력한 형식의 컬렉션으로 바꿉니다. 자세한 내용은 System.Collections.ReadOnlyCollectionBase을 참조하십시오.

  • 공용 필드를 private 배열의 복제본을 반환하는 메서드로 바꿉니다. 이렇게 하면 코드에서 복제본을 사용하지 않기 때문에 요소가 수정되더라도 위험하지 않습니다.

두 번째 방법을 선택한 경우 필드를 속성으로 바꾸지 마십시오. 배열을 반환하는 속성을 사용하면 성능이 저하됩니다. 자세한 내용은 CA1819: 속성은 배열을 반환해서는 안 됩니다.을 참조하십시오.

경고를 표시하지 않는 경우

이 규칙에서 경고를 제외하지 않는 것이 좋습니다. 읽기 전용 필드의 내용이 중요하지 않은 경우는 거의 발생하지 않습니다. 그러나 중요하지 않은 경우라면 메시지를 제외하는 대신 readonly 한정자를 제거하십시오.

예제

이 예제에서는 이 규칙을 위반했을 경우의 위험을 보여 줍니다. 첫 번째 부분에서는 MyClassWithReadOnlyArrayField 형식이 있는 예제 라이브러리를 보여 줍니다. 이 형식에는 보안되지 않는 grades 및 privateGrades라는 두 필드가 포함되어 있습니다. grades 필드는 public이기 때문에 모든 호출자에게 노출되어 취약합니다. privateGrades 필드는 private이지만 GetPrivateGrades 메서드가 이를 호출자에게 반환하므로 여전히 취약합니다. securePrivateGrades 필드는 GetSecurePrivateGrades 메서드를 통해 안전한 방식으로 노출됩니다. 이 필드는 권장 디자인 방식에 따라 private으로 선언됩니다. 두 번째 부분에서는 grades 및 privateGrades 멤버에 저장된 값을 변경하는 코드를 보여 줍니다.

다음은 예제 클래스 라이브러리입니다.

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

다음 코드에서는 예제 클래스 라이브러리를 사용하여 읽기 전용 배열 보안 문제를 보여 줍니다.

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

이 예제의 결과는 다음과 같습니다.

  

참고 항목

참조

System.Array

System.Collections.ReadOnlyCollectionBase