다음을 통해 공유


리플렉션에 대한 보안 고려 사항

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

  • 형식 및 멤버를 열거하고 해당 메타데이터를 검사합니다.
  • 어셈블리 및 모듈을 열거하고 검사합니다.

반면 리플렉션을 사용하여 멤버에 액세스하는 것은 제한 사항의 적용을 받습니다. .NET Framework 4부터 신뢰할 수 있는 코드만 리플렉션을 사용하여 보안에 중요한 멤버에 액세스할 수 있습니다. 또한 신뢰할 수 있는 코드만 리플렉션을 사용하여 컴파일된 코드에 직접 액세스할 수 없는 비공개 멤버에 액세스할 수 있습니다. 마지막으로 리플렉션을 사용하여 안전한 중요 멤버에 액세스하는 코드는 컴파일된 코드와 마찬가지로 안전 위험 멤버가 요구하는 모든 권한을 가져야 합니다.

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

  • 보안에 중요하지 않은 공용 멤버에 액세스합니다.

  • 컴파일된 코드에 액세스할 수 있는 게시되지 않은 멤버에 액세스합니다(해당 멤버가 보안에 중요하지 않은 경우). 이러한 비공개 멤버의 예는 다음과 같습니다.

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

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

    • 호출 코드를 포함하는 클래스의 다른 인스턴스에 대한 프라이빗 멤버입니다.

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

.NET Framework 2.0 서비스 팩 1부터 일반적으로 액세스할 수 없는 멤버에 액세스하려고 시도하면 대상 개체의 권한 부여 집합과 ReflectionPermission 플래그가 포함된 ReflectionPermissionFlag.MemberAccess에 대한 요구가 생성됩니다. 완전 신뢰로 실행되는 코드(예: 명령줄에서 시작된 애플리케이션의 코드)는 항상 이러한 권한을 충족할 수 있습니다. (이 문서의 뒷부분에서 설명한 대로 보안에 중요한 멤버에 액세스하는 데 제한 사항이 적용됩니다.)

필요에 따라 샌드박스 애플리케이션 도메인은 이 문서의 뒷부분에 설명된 ReflectionPermission 섹션에 따라 ReflectionPermissionFlag.MemberAccess 플래그를 사용하여, 를 부여할 수 있습니다.

Security-Critical 멤버에 접근

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

  • 투명 코드는 코드를 완전히 신뢰할 수 있더라도 리플렉션을 사용하여 보안에 중요한 멤버에 액세스할 수 없습니다. MethodAccessException, FieldAccessException, 또는 TypeAccessException가 던져집니다.

  • 부분 신뢰로 실행되는 코드는 투명으로 처리됩니다.

이러한 규칙은 보안에 중요한 멤버가 컴파일된 코드에서 직접 액세스하거나 리플렉션을 사용하여 액세스하는지와 동일합니다.

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

리플렉션 및 투명도

.NET Framework 4부터 공용 언어 런타임은 어셈블리의 신뢰 수준 및 애플리케이션 도메인의 신뢰 수준을 포함하여 여러 요인에서 형식 또는 멤버의 투명도 수준을 결정합니다. 리플렉션은 형식의 투명도 수준을 발견할 수 있도록 IsSecurityCritical, IsSecuritySafeCritical, 및 IsSecurityTransparent 속성을 제공합니다. 다음 표에서는 이러한 속성의 유효한 조합을 보여 줍니다.

보안 수준 IsSecurityCritical 보안은 안전하게 중요합니까? IsSecurityTransparent
중요한 true false false
안전 필수 true true false
투명한 false false true

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

, MethodBase, FieldInfoTypeBuilderMethodBuilder 클래스에 DynamicMethod유사한 속성이 있습니다. 다른 리플렉션 및 리플렉션 방출 추상화의 경우, 보안 특성은 연결된 메서드에 적용됩니다. 예를 들어, 속성의 경우에는 속성 접근자에 적용됩니다.

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

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

  • 코드가 비공개 멤버를 호출할 수 있도록 허용하려면 ReflectionPermission 플래그와 함께 ReflectionPermissionFlag.MemberAccess 권한을 코드에 부여해야 합니다.

    비고

    기본적으로 보안 정책은 인터넷에서 시작된 코드에 대한 이 권한을 거부합니다. 이 권한은 인터넷에서 시작된 코드에 부여되어서는 안 됩니다.

  • 호출된 멤버를 포함하는 어셈블리의 권한 부여 집합이 호출 코드를 포함하는 어셈블리의 권한 부여 집합과 같거나 또는 하위 집합인 경우, 코드는 비공개 멤버를 호출할 수 있습니다. 이를 위해서는 플래그 ReflectionPermission와 함께 코드 ReflectionPermissionFlag.RestrictedMemberAccess를 부여받아야 합니다.

예를 들어 애플리케이션 도메인 인터넷 사용 권한과 ReflectionPermissionReflectionPermissionFlag.RestrictedMemberAccess 플래그를 부여한 다음 두 개의 어셈블리 A와 B를 사용하여 인터넷 애플리케이션을 실행한다고 가정합니다.

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

  • 어셈블리 A는 리플렉션을 사용하여 mscorlib.dll같은 .NET Framework 어셈블리의 프라이빗 멤버에 액세스할 수 없습니다. mscorlib.dll 완전히 신뢰할 수 있으므로 어셈블리 A에 부여되지 않은 권한이 있기 때문입니다. 코드 액세스 보안이 런타임에 스택을 걸을 때 A MemberAccessException 가 throw됩니다.

직렬화

SecurityPermission와 함께 SecurityPermissionAttribute.SerializationFormatter 플래그를 사용하면 접근성에 관계없이 직렬화 가능한 형식의 멤버를 가져오고 설정할 수 있습니다. 이 권한을 통해 코드는 인스턴스의 프라이빗 상태를 검색하고 변경할 수 있습니다. 적절한 사용 권한이 부여되는 것 외에도 형식은 메타데이터에서 serialize 가능으로 표시 되어야 합니다.

MethodInfo 형식의 매개 변수

특히 신뢰할 수 있는 코드의 경우 매개 변수를 사용하는 MethodInfo 공용 멤버를 작성하지 마세요. 이러한 멤버는 악성 코드에 더 취약할 수 있습니다. 예를 들어, MethodInfo 매개 변수를 받는 높은 신뢰도의 코드 내 공용 멤버를 고려해 보세요. 공용 멤버가 제공된 매개 변수에서 메서드를 Invoke 간접적으로 호출한다고 가정합니다. 보안 시스템이 호출자를 매우 신뢰할 수 있다고 판단하기 때문에 공용 멤버가 필요한 권한 검사를 수행하지 않으면 Invoke 메서드 호출은 항상 성공합니다. 악성 코드에 메서드를 직접 호출할 수 있는 권한이 없더라도 공용 멤버를 호출하여 간접적으로 호출할 수 있습니다.

버전 정보

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

  • 플래그는 ReflectionPermissionFlag.RestrictedMemberAccess .NET Framework 2.0 서비스 팩 1에 도입되었습니다. 이전 버전의 .NET Framework에는 리플렉션을 ReflectionPermissionFlag.MemberAccess 사용하여 비공개 멤버에 액세스하는 코드에 대한 플래그가 필요합니다. 이는 부분적으로 신뢰할 수 있는 코드에 부여해서는 안 되는 권한입니다.

  • .NET Framework 2.0부터 리플렉션을 사용하여 게시되지 않은 형식 및 멤버에 대한 정보를 가져오려면 권한이 필요하지 않습니다. 이전 버전에는 ReflectionPermissionReflectionPermissionFlag.TypeInformation 플래그가 필요합니다.

참고하십시오