리플렉션의 보안 고려 사항

리플렉션은 형식 및 멤버에 대한 정보를 얻고 멤버에 액세스하는 기능을 제공합니다(즉, 메서드 및 생성자를 호출하고, 속성 값을 가져오거나 설정하고, 이벤트 처리기를 추가 및 제거하는 등의 기능). 형식 및 멤버에 대한 정보를 얻기 위한 리플렉션 사용에는 제한이 없습니다. 모든 코드에서 리플렉션을 사용하여 다음 작업을 수행할 수 있습니다.

  • 형식과 멤버를 열거하고 해당 메타데이터를 검사합니다.

  • 어셈블리 및 모듈을 열거하고 검사합니다.

반면 멤버에 액세스하기 위한 리플렉션 사용에는 제한이 따릅니다. .NET Framework 버전 4부터는 신뢰 코드만 리플렉션을 사용하여 보안에 중요한 멤버에 액세스할 수 있습니다. 또한 컴파일된 코드에서 직접 액세스할 수 없는, public이 아닌 멤버에도 신뢰 코드만 리플렉션을 사용하여 액세스할 수 있습니다. 마지막으로, 안전상 중요한 멤버에 액세스하기 위해 리플렉션을 사용하는 코드는 컴파일된 코드와 마찬가지로 안전상 중요한 멤버에서 요구하는 권한을 가져야 합니다.

필요한 권한에 따라 코드는 리플렉션을 사용하여 다음과 같은 종류의 액세스를 수행할 수 있습니다.

  • 보안에 중요한 멤버가 아닌 public 멤버에 액세스합니다.

  • 컴파일된 코드에서 액세스할 수 있는 public이 아닌 멤버에 액세스합니다(이러한 멤버가 보안에 중요한 멤버가 아닌 경우). 다음은 이러한 public이 아닌 멤버의 예제입니다.

    • 호출 코드 기본 클래스의 보호된 멤버. 리플렉션에서는 이를 패밀리 수준 액세스라고 합니다.

    • 호출 코드의 어셈블리에 있는 internal 멤버(Visual Basic의 경우 Friend 멤버). 리플렉션에서는 이를 어셈블리 수준 액세스라고 합니다.

    • 호출 코드를 포함하는 클래스의 다른 인스턴스에 있는 private 멤버.

예를 들어 샌드박스가 적용된 응용 프로그램 도메인에서 실행되는 코드는 응용 프로그램 도메인에서 추가 권한을 부여하지 않는 한 이 목록에 설명된 액세스로 제한됩니다.

.NET Framework 버전 2.0 서비스 팩 1부터는 일반적으로 액세스할 수 없는 멤버에 액세스를 시도할 경우 대상 개체의 부여 집합과 ReflectionPermissionFlag.MemberAccess 플래그가 지정된 ReflectionPermission에 대한 요구가 생성됩니다. 완전 신뢰로 실행되는 코드(예: 명령줄에서 시작된 응용 프로그램의 코드)는 이러한 권한을 항상 충족합니다. (여기에는 이 문서의 뒷부분에 설명된 대로 보안에 중요한 멤버에 대한 액세스 제한이 적용됩니다.)

필요한 경우 샌드박스가 적용된 응용 프로그램 도메인은 이 문서 뒷부분의 일반적으로 액세스할 수 없는 멤버에 액세스 단원에 설명된 대로 ReflectionPermissionFlag.MemberAccess 플래그가 지정된 ReflectionPermission을 부여할 수 있습니다.

보안에 중요한 멤버에 액세스

멤버는 SecurityCriticalAttribute를 가진 경우, SecurityCriticalAttribute를 가진 형식에 속하는 경우 또는 보안에 중요한 어셈블리에 포함되어 있는 경우 보안에 중요합니다. .NET Framework 버전 4부터 보안에 중요한 멤버에 액세스하기 위한 규칙은 다음과 같습니다.

  • 투명 코드는 리플렉션을 사용하여 보안에 중요한 멤버에 액세스할 수 없습니다. 코드가 완전 신뢰 코드라도 마찬가지입니다. MethodAccessException, FieldAccessException 또는 TypeAccessException이 throw됩니다.

  • 부분 신뢰로 실행되는 코드는 투명한 것으로 취급됩니다.

이러한 규칙은 보안에 중요한 멤버가 컴파일된 코드에서 직접 액세스되든 리플렉션을 사용하여 액세스되든 동일하게 적용됩니다.

명령줄에서 실행되는 응용 프로그램 코드는 완전 신뢰로 실행됩니다. 투명한 것으로 표시되지 않는 한 이 코드는 리플렉션을 사용하여 보안에 중요한 멤버에 액세스할 수 있습니다. 동일한 코드가 부분 신뢰로 실행되는 경우(예: 샌드박스가 적용된 응용 프로그램 도메인에서 실행) 어셈블리의 신뢰 수준에 따라 이 코드가 보안에 중요한 멤버에 액세스할 수 있는지 여부가 결정됩니다. 어셈블리가 강력한 이름을 가졌고 전역 어셈블리 캐시에 설치된 경우 이는 신뢰 어셈블리이며 보안에 중요한 멤버를 호출할 수 있습니다. 신뢰할 수 없는 어셈블리인 경우 투명한 것으로 표시되지 않았더라도 투명하게 되며 보안에 중요한 멤버에 액세스할 수 없습니다.

.NET Framework 4의 보안 모델에 대한 자세한 내용은 .NET Framework 4의 보안 변경 내용을 참조하십시오.

리플렉션 및 투명성

.NET Framework 4부터 공용 언어 런타임이 어셈블리의 신뢰 수준과 응용 프로그램 도메인의 신뢰 수준을 포함한 여러 가지 요소를 통해 형식 또는 멤버의 투명성을 판단합니다. 리플렉션은 IsSecurityCritical, IsSecuritySafeCriticalIsSecurityTransparent 속성을 제공하여 형식의 투명성 수준을 파악할 수 있도록 합니다. 다음 표에서는 이러한 속성의 유효한 조합을 보여 줍니다.

보안 수준

IsSecurityCritical

IsSecuritySafeCritical

IsSecurityTransparent

Critical

true

false

false

안전상 중요

true

true

false

투명

false

false

true

이러한 속성을 사용하는 것이 어셈블리의 보안 주석 및 해당 형식을 검사하고 현재 신뢰 수준을 확인한 다음 런타임의 규칙을 복제하는 것보다 훨씬 간단합니다. 예를 들어 동일한 형식이 명령줄에서 실행될 때는 보안에 중요하게 되고 샌드박스가 적용된 응용 프로그램 도메인에서 실행될 때는 보안에 투명하게 될 수 있습니다.

MethodBase, FieldInfo, TypeBuilder, MethodBuilderDynamicMethod 클래스에는 유사한 속성이 있습니다. 기타 리플렉션 및 리플렉션 내보내기 추상화의 경우 연결된 메서드에 보안 특성이 적용됩니다(예: 속성의 경우 속성 접근자에 적용됨).

일반적으로 액세스할 수 없는 멤버에 액세스

리플렉션을 사용하여 공용 언어 런타임의 액세스 가능성 규칙에 따라 액세스할 수 없는 멤버를 호출하려면 코드에 다음 두 권한 중 하나를 부여해야 합니다.

  • 코드에서 public이 아닌 멤버를 호출할 수 있게 하려면 코드에 ReflectionPermissionFlag.MemberAccess 플래그가 지정된 ReflectionPermission을 부여해야 합니다.

    참고참고

    기본적으로 보안 정책은 인터넷에서 발생한 코드에 대해 이 권한을 거부합니다.인터넷에서 발생한 코드에는 이 권한을 부여하면 안 됩니다.

  • 호출된 멤버를 포함하는 어셈블리의 부여 집합이 호출 코드를 포함하는 어셈블리의 부여 집합과 같거나 그 하위 집합인 경우 코드에서 public이 아닌 멤버를 호출할 수 있게 하려면 코드에 ReflectionPermissionFlag.RestrictedMemberAccess 플래그가 지정된 ReflectionPermission을 부여해야 합니다.

예를 들어 응용 프로그램 도메인에 인터넷 권한과 ReflectionPermissionFlag.RestrictedMemberAccess 플래그가 지정된 ReflectionPermission을 부여한 다음 두 개의 어셈블리 A와 B를 사용하여 인터넷 응용 프로그램을 실행한다고 가정합니다.

  • A에 부여되지 않은 권한이 어셈블리 B의 권한 집합에도 포함되어 있지 않으므로 어셈블리 A는 리플렉션을 사용하여 어셈블리 B의 private 멤버에 액세스할 수 있습니다.

  • 어셈블리 A가 리플렉션을 사용하여 .NET Framework 어셈블리의 private 멤버(예: mscorlib.dll)에 액세스할 수 없다면 mscorlib.dll이 완전히 신뢰되어 있고 어셈블리 A에 부여된 권한이 없기 때문입니다. 코드 액세스 보안이 런타임에 스택을 워크하면 MemberAccessException이 throw됩니다.

Serialization

serialization의 경우 SecurityPermissionAttribute.SerializationFormatter 플래그가 지정된 SecurityPermission은 액세스 가능성에 관계없이 serialize할 수 있는 형식의 멤버를 가져오고 설정하는 기능을 제공합니다. 이 권한이 있으면 코드에서 인스턴스의 전용 상태를 검색하고 변경할 수 있습니다. 적절한 권한이 부여되는 것 이외에도, 해당 형식이 메타데이터에서 serialize할 수 있는 것으로 표시되어 있어야 합니다.

MethodInfo 형식의 매개 변수

특히 신뢰 코드의 경우 MethodInfo 매개 변수를 사용하는 public 멤버를 작성하지 마십시오. 이러한 멤버는 악성 코드에 더욱 노출되기 쉬울 수 있습니다. 예를 들어 MethodInfo 매개 변수를 사용하는 신뢰 수준이 높은 코드의 public 멤버를 생각해 보겠습니다. public 멤버가 제공된 매개 변수에 대해 간접적으로 Invoke 메서드를 호출한다고 가정합니다. public 멤버가 필요한 권한 검사를 수행하지 않으면 보안 시스템에서는 호출자의 신뢰 수준이 높다고 결정하기 때문에 Invoke 메서드에 대한 호출이 항상 성공적으로 수행됩니다. 악성 코드는 이 메서드를 직접 호출하는 권한이 없어도 public 멤버를 호출하여 간접적으로 이 메서드를 호출할 수 있습니다.

버전 정보

  • .NET Framework 버전 4부터 투명 코드는 리플렉션을 사용하여 보안에 중요한 멤버에 액세스할 수 없습니다.

  • .NET Framework 버전 2.0 서비스 팩 1에서는 ReflectionPermissionFlag.RestrictedMemberAccess 플래그가 도입되었습니다. .NET Framework 이전 버전에서 리플렉션을 사용하여 public이 아닌 멤버에 액세스하는 코드의 경우 ReflectionPermissionFlag.MemberAccess 플래그가 필요합니다. 이렇게 부분 신뢰 코드에는 이 권한을 부여하면 안 됩니다.

  • .NET Framework 2.0부터 시작하여 리플렉션을 통해 public이 아닌 형식과 멤버에 대한 정보를 가져오는 데 권한이 필요하지 않습니다. 이전 버전에는 ReflectionPermissionFlag.TypeInformation 플래그가 지정된 ReflectionPermission이 필요합니다.

참고 항목

참조

ReflectionPermissionFlag

ReflectionPermission

SecurityPermission

개념

.NET Framework 4의 보안 변경 내용

코드 액세스 보안

리플렉션 내보내기의 보안 문제점

형식 정보 보기

특성 적용

사용자 지정 특성 액세스