리플렉션 내보내기의 보안 문제점
업데이트: 2007년 11월
.NET Framework는 MSIL(Microsoft Intermediate Language)을 내보내는 세 가지 방법을 제공합니다. 각 방법에는 고유한 보안 문제가 있습니다.
동적 어셈블리
익명으로 호스팅된 동적 메서드
기존 어셈블리와 관련된 동적 메서드
동적 코드를 생성하는 방법에 관계없이 생성된 코드를 실행하려면 생성된 코드에서 사용하는 형식과 메서드에 필요한 모든 권한이 있어야 합니다.
참고: |
---|
코드에 반영하고 코드를 생성하는 데 필요한 권한이 .NET Framework의 이후 릴리스에서는 변경되었습니다. 이 항목의 뒷부분에 나오는 버전 정보를 참조하십시오. |
동적 어셈블리
동적 어셈블리는 AppDomain.DefineDynamicAssembly 메서드의 오버로드를 사용하여 만들어집니다. 필요한 권한은 사용되는 오버로드에 따라 달라집니다. 예를 들어 증명 정보를 제공하는 오버로드에는 SecurityPermissionFlag.ControlEvidence 플래그가 지정된 SecurityPermission이 필요합니다. 일부 오버로드에는 권한이 필요하지 않으며 인터넷 권한만 있는 코드에서 호출할 수 있습니다.
동적 어셈블리의 코드는 다른 어셈블리의 노출 형식과 멤버에 액세스할 수 있습니다.
참고: |
---|
동적 어셈블리는 동적 메서드가 public이 아닌 형식과 멤버에 액세스할 수 있도록 하는 ReflectionPermissionFlag.MemberAccess 및 ReflectionPermissionFlag.RestrictedMemberAccess 플래그를 사용하지 않습니다. |
디버그 기호가 있는 코드를 생성하려면 ReflectionPermissionFlag.ReflectionEmit 플래그가 지정된 ReflectionPermission이 필요합니다.
임시 동적 어셈블리는 메모리에서 만들어지며 디스크에 저장되지 않으므로 파일 액세스 권한이 필요하지 않습니다. 동적 어셈블리를 디스크에 저장하려면 해당 플래그가 지정된 FileIOPermission이 필요합니다.
부분적으로 신뢰할 수 있는 코드에서 동적 어셈블리 생성
인터넷 권한이 있는 어셈블리에서 임시 동적 어셈블리를 생성하고 해당 코드를 실행할 수 있는 다음 조건을 확인해 보십시오.
동적 어셈블리에서 다른 어셈블리의 public 형식과 멤버만 사용합니다.
이러한 형식과 멤버에 필요한 권한이 부분적으로 신뢰할 수 있는 어셈블리의 부여 집합에 들어 있습니다.
동적 어셈블리를 만드는 데 사용되는 DefineDynamicAssembly 메서드 오버로드에 특별한 권한이 필요하지 않습니다. 즉, 증명 정보가 제공되거나 하지 않습니다.
어셈블리가 디스크에 저장되지 않습니다.
디버그 기호가 생성되지 않습니다. Internet 및 LocalIntranet 권한 집합에는 ReflectionPermissionFlag.ReflectionEmit 플래그가 포함되지 않습니다.
동적 어셈블리에 대한 권한 설정
다음 목록에서 "생성기"는 동적 어셈블리를 생성하는 어셈블리입니다.
SecurityPermissionFlag.ControlEvidence 플래그가 지정된 SecurityPermission이 있는 생성기는 생성된 코드에 대한 증명 정보를 제공할 수 있습니다. 이 증명 정보는 정책을 통해 매핑되어 부여된 권한을 확인합니다.
생성기는 null 증명 정보를 제공할 수 있습니다. 이 경우 어셈블리는 생성기의 권한 집합을 가져옵니다. 그러면 생성된 코드가 생성기보다 더 많은 권한을 가질 수 없습니다.
권한 집합에 SecurityAction.RequestMinimum, SecurityAction.RequestOptional 또는 SecurityAction.RequestRefuse를 제공하면 어셈블리가 디스크에 저장된 후 디스크에서 로드될 때까지 해당 권한 집합이 사용되지 않습니다.
동적 어셈블리가 디스크에 저장된 후 어셈블리는 디스크에서 로드된 다른 어셈블리처럼 처리됩니다.
부분적으로 신뢰할 수 있는 생성기에 의해 생성된 코드는 항상 확인 과정을 거칩니다. 특히 SecurityPermissionFlag.SkipVerification 플래그가 지정된 SecurityPermission이 없는 코드는 런타임에서 항상 확인됩니다. 완전히 신뢰할 수 있는 생성기인 경우 생성된 코드의 확인 과정을 요청하거나 건너뛸 수 있습니다.
익명으로 호스팅된 동적 메서드
연결된 형식이나 모듈을 지정하지 않는 두 개의 DynamicMethod 생성자(DynamicMethod(String, Type, array<Type[]) 및 DynamicMethod(String, Type, array<Type[], Boolean))를 사용하여 익명으로 호스팅된 동적 메서드를 만듭니다. 이 생성자는 시스템에서 제공된 완전히 신뢰할 수 있는 보안 투명 어셈블리에 동적 메서드를 넣습니다. 이러한 생성자를 사용하거나 동적 메서드에 대한 코드를 생성하는 경우에는 권한이 필요하지 않습니다.
대신 익명으로 호스팅된 동적 메서드를 만들 때 호출 스택이 캡처됩니다. 메서드를 생성하면 캡처된 호출 스택에 대해 보안 요청이 수행됩니다.
참고: |
---|
개념적으로 메서드를 생성하는 동안 요청이 수행됩니다. 즉, 각 MSIL 명령을 내보낼 때 요청을 수행할 수 있습니다. 현재 구현에서는 DynamicMethod.CreateDelegate 메서드를 호출할 때 또는 CreateDelegate를 호출하지 않고 메서드를 호출하는 경우 JIT(Just-In-Time) 컴파일러를 호출할 때 모든 요청이 수행됩니다. |
익명으로 호스팅된 동적 메서드는 JIT 가시성 검사를 건너뛸 수 있지만 다음 제한이 적용됩니다. 익명으로 호스팅된 동적 메서드에서 액세스하는 public이 아닌 형식과 멤버는 부여 집합이 내보내는 호출 스택의 부여 집합과 같거나 그 하위 집합인 어셈블리에 있어야 합니다. JIT 가시성 검사를 건너뛰는 이 제한된 기능에는 ReflectionPermissionFlag.RestrictedMemberAccess 플래그가 지정된 ReflectionPermission이 필요합니다.
메서드가 public 형식과 멤버만 사용하는 경우에는 생성 중에 권한이 필요하지 않습니다.
JIT 가시성 검사를 건너뛰도록 지정하면 메서드를 생성할 때 수행되는 요청에 ReflectionPermissionFlag.RestrictedMemberAccess 플래그가 지정된 ReflectionPermission 및 액세스되는 public이 아닌 멤버가 있는 어셈블리의 부여 집합이 포함됩니다.
public이 아닌 멤버의 부여 집합을 고려하기 때문에 ReflectionPermissionFlag.RestrictedMemberAccess가 부여된 부분적으로 신뢰할 수 있는 코드는 신뢰할 수 있는 어셈블리의 public이 아닌 멤버를 실행하여 권한을 올릴 수 없습니다.
다른 생성된 코드와 마찬가지로 동적 메서드를 실행하려면 동적 메서드에서 사용하는 메서드에 필요한 모든 권한이 있어야 합니다.
자세한 내용은 DynamicMethod 클래스를 참조하십시오.
부분적으로 신뢰할 수 있는 코드에서 익명으로 호스팅된 동적 메서드 생성
인터넷 권한이 있는 어셈블리에서 익명으로 호스팅된 동적 메서드를 생성하고 실행할 수 있는 다음 조건을 확인해 보십시오.
동적 메서드에서 public 형식과 멤버만 사용합니다. 부여 집합에 ReflectionPermissionFlag.RestrictedMemberAccess가 있으면 해당 부여 집합이 내보내는 어셈블리의 부여 집합과 같거나 그 하위 집합인 모든 어셈블리의 public이 아닌 형식과 멤버를 사용할 수 있습니다.
동적 메서드에서 사용하는 모든 형식과 멤버에 필요한 권한이 부분적으로 신뢰할 수 있는 어셈블리의 부여 집합에 들어 있습니다.
참고: |
---|
동적 메서드는 디버그 기호를 지원하지 않습니다. |
기존 어셈블리와 관련된 동적 메서드
동적 메서드를 기존 어셈블리의 형식이나 모듈과 연결하려면 관련된 형식 또는 모듈을 지정하는 DynamicMethod 생성자를 사용합니다. 동적 메서드를 기존 형식 또는 모듈과 연결하면 public이 아닌 형식과 멤버에 대한 액세스 권한이 동적 메서드에 제공되므로 이 생성자를 호출하는 데 필요한 권한은 달라질 수 있습니다.
특정 형식과 관련된 동적 메서드는 해당 형식의 모든 멤버(private 멤버 포함) 및 관련된 형식을 포함하는 어셈블리의 모든 내부 형식과 멤버에 액세스할 수 있습니다.
모듈과 관련된 동적 메서드는 모듈의 모든 internal 형식과 멤버(Visual Basic의 경우 Friend, 공용 언어 런타임 메타데이터의 경우 assembly)에 액세스할 수 있습니다.
또한 JIT 컴파일러의 가시성 검사를 건너뛰는 기능을 지정하는 생성자를 사용할 수 있습니다. 이렇게 하면 동적 메서드가 액세스 수준에 관계없이 모든 어셈블리의 모든 형식과 멤버에 액세스할 수 있습니다.
생성자에 필요한 권한은 동적 메서드에 제공하려는 액세스 권한에 따라 달라집니다.
메서드에서 public 형식과 메서드만 사용하고 해당 메서드를 고유한 형식이나 모듈과 연결하려는 경우에는 권한이 필요하지 않습니다.
JIT 가시성 검사를 건너뛰도록 지정하면 생성자는 ReflectionPermissionFlag.MemberAccess 플래그가 지정된 ReflectionPermission을 요청합니다.
동적 메서드를 다른 형식과 연결하는 경우 이 형식이 사용자 자체 어셈블리에 있는 형식인 경우에도 생성자에서 ReflectionPermissionFlag.MemberAccess 플래그가 지정된 ReflectionPermission과 SecurityPermissionFlag.ControlEvidence 플래그가 지정된 SecurityPermission을 요청합니다.
동적 메서드를 다른 어셈블리의 형식이나 모듈과 연결하는 경우 생성자에서 두 가지 사항, 즉 ReflectionPermissionFlag.RestrictedMemberAccess 플래그가 지정된 ReflectionPermission과 다른 모듈을 포함하는 어셈블리의 부여 집합을 요청합니다. 즉, 호출 스택에 대상 모듈의 부여 집합에 있는 모든 권한과 ReflectionPermissionFlag.RestrictedMemberAccess가 있어야 합니다.
참고: 이전 버전과의 호환성을 위해 대상 부여 집합 및 ReflectionPermissionFlag.RestrictedMemberAccess에 대한 요청이 실패할 경우 생성자에서 SecurityPermissionFlag.ControlEvidence 플래그가 지정된 SecurityPermission을 요청합니다.
이 목록의 항목은 내보내는 어셈블리의 부여 집합과 관련해서 설명되어 있지만 요청은 응용 프로그램 도메인 경계를 비롯한 전체 호출 스택에 대해 수행됩니다.
자세한 내용은 DynamicMethod 클래스를 참조하십시오.
부분적으로 신뢰할 수 있는 코드에서 동적 메서드 생성
참고: |
---|
부분적으로 신뢰할 수 있는 코드에서 동적 메서드를 생성하려는 경우 익명으로 호스팅된 동적 메서드를 사용하는 것이 좋습니다. |
인터넷 권한이 있는 어셈블리에서 동적 메서드를 생성하고 실행할 수 있는 다음 조건을 확인해 보십시오.
동적 메서드가 해당 메서드를 내보내는 모듈 또는 형식과 관련이 있거나 부여 집합에 ReflectionPermissionFlag.RestrictedMemberAccess가 있고 해당 부여 집합이 내보내는 어셈블리의 부여 집합과 같거나 그 하위 집합인 어셈블리의 모듈과 관련이 있습니다.
동적 메서드에서 public 형식과 멤버만 사용합니다. 부여 집합에 ReflectionPermissionFlag.RestrictedMemberAccess가 있고 해당 부여 집합이 내보내는 어셈블리의 부여 집합과 같거나 그 하위 집합인 어셈블리의 모듈과 관련이 있는 경우 관련된 모듈에서 internal(Visual Basic의 경우 Friend, 공용 언어 런타임 메타데이터의 경우 assembly)로 표시된 형식과 멤버를 사용할 수 있습니다.
동적 메서드에서 사용하는 모든 형식과 멤버에 필요한 권한이 부분적으로 신뢰할 수 있는 어셈블리의 부여 집합에 들어 있습니다.
동적 메서드에서 JIT 가시성 검사를 건너뛰지 않습니다.
참고: |
---|
동적 메서드는 디버그 기호를 지원하지 않습니다. |
버전 정보
.NET Framework 버전 2.0 서비스 팩 1부터 시작하여 동적 어셈블리와 동적 메서드를 내보낼 때 ReflectionPermissionFlag.ReflectionEmit 플래그가 지정된 ReflectionPermission은 더 이상 필요하지 않습니다. 이 플래그는 .NET Framework의 모든 이전 버전에서 필요합니다.
참고: |
---|
ReflectionPermissionFlag.ReflectionEmit 플래그가 지정된 ReflectionPermission은 기본적으로 FullTrust 및 LocalIntranet 명명된 권한 집합에 있지만 Internet 권한 집합에는 포함되지 않습니다. 따라서 .NET Framework의 이전 버전에서는 라이브러리가 ReflectionEmit에 대해 Assert를 실행하는 경우에만 인터넷 권한으로 라이브러리를 사용할 수 있습니다. 코드 오류가 있으면 보안에 문제가 생길 수 있으므로 이러한 라이브러리를 보안 측면에서 자세히 검토해야 합니다. .NET Framework 2.0 SP1의 경우에는 기본적으로 코드를 생성하는 데 권한이 필요하지 않으므로 부분 신뢰 시나리오에서 보안 요구 사항 없이 코드를 생성할 수 있습니다. 즉, 생성된 코드에는 이를 내보내는 어셈블리보다 많은 권한이 부여되지 않습니다. 따라서 코드를 생성하는 라이브러리의 보안이 투명하게 유지되고 ReflectionEmit을 어설션할 필요가 없으므로 보안 라이브러리를 간편하게 작성할 수 있습니다. |
또한 .NET Framework 2.0 SP1에서는 부분적으로 신뢰할 수 있는 동적 메서드에서 public이 아닌 형식과 멤버에 액세스하기 위한 ReflectionPermissionFlag.RestrictedMemberAccess 플래그가 도입되었습니다. .NET Framework의 이전 버전에서는 public이 아닌 형식과 멤버에 액세스하는 동적 메서드에 대해 ReflectionPermissionFlag.MemberAccess 플래그가 필요한데, 이는 부분적으로 신뢰할 수 있는 코드에 부여하면 안 되는 권한입니다.
마지막으로 .NET Framework 2.0 SP1에서는 익명으로 호스팅된 메서드가 도입되었습니다.
이 기능을 사용하려면 응용 프로그램이 .NET Framework 버전 3.5를 대상으로 해야 합니다. 자세한 내용은 .NET Framework 3.5 아키텍처를 참조하십시오.
형식 및 멤버에 대한 정보 가져오기
.NET Framework 2.0부터 시작하여 public이 아닌 형식과 멤버에 대한 정보를 가져오는 데 권한이 필요하지 않습니다. 리플렉션을 통해 동적 메서드를 내보내는 데 필요한 정보를 가져옵니다. 예를 들어 MethodInfo 개체를 사용하여 메서드 호출을 내보냅니다. .NET Framework의 이전 버전에는 ReflectionPermissionFlag.TypeInformation 플래그가 지정된 ReflectionPermission이 필요합니다. 자세한 내용은 리플렉션의 보안 고려 사항을 참조하십시오.