反映的安全性考量Security Considerations for Reflection

反映可讓您取得類型和成員的相關資訊,以及存取成員 (也就是呼叫方法和建構函式、取得和設定屬性值、加入和移除事件處理常式等等)。Reflection provides the ability to obtain information about types and members, and to access members (that is, to call methods and constructors, to get and set property values, to add and remove event handlers, and so on). 不限制使用反映來取得類型和成員的相關資訊。The use of reflection to obtain information about types and members is not restricted. 所有程式碼都可以使用反映來執行下列工作:All code can use reflection to perform the following tasks:

  • 列舉類型和成員,並檢查其中繼資料。Enumerate types and members, and examine their metadata.

  • 列舉及檢查組件和模組。Enumerate and examine assemblies and modules.

相對地,使用反映來存取成員有所限制。Using reflection to access members, by contrast, is subject to restrictions. 從 .NET Framework 4 開始,只有受信任的程式碼才能使用反映存取安全性關鍵成員。Beginning with the .NET Framework 4, only trusted code can use reflection to access security-critical members. 此外,只有受信任的程式碼能夠使用反映來存取已編譯程式碼無法直接存取的非公用成員。Furthermore, only trusted code can use reflection to access nonpublic members that would not be directly accessible to compiled code. 最後,使用反映存取安全性關鍵成員的程式碼必須擁有安全關鍵成員所要求的任何權限,就如同編譯的程式碼。Finally, code that uses reflection to access a safe-critical member must have whatever permissions the safe-critical member demands, just as with compiled code.

受限於所需的權限,程式碼可以使用反映來執行下列類型的存取:Subject to necessary permissions, code can use reflection to perform the following kinds of access:

  • 存取非安全性關鍵的公用成員。Access public members that are not security-critical.

  • 存取可供已編譯程式碼存取的非公用成員 (前提是這些成員不是安全性關鍵成員)。Access nonpublic members that would be accessible to compiled code, if those members are not security-critical. 這類非公用成員的範例包括:Examples of such nonpublic members include:

    • 呼叫程式碼基底類別的 Protected 成員。Protected members of the calling code's base classes. (在反映中,這稱為系列層級的存取。)(In reflection, this is referred to as family-level access.)

    • 呼叫程式碼組件中的 internal 成員 (在 Visual Basic 中為 Friend 成員)。internal members (Friend members in Visual Basic) in the calling code's assembly. (在反映中,這稱為組件層級存取。)(In reflection, this is referred to as assembly-level access.)

    • 包含呼叫程式碼之類別的其他執行個體的私用成員。Private members of other instances of the class that contains the calling code.

例如,在沙箱化應用程式定義域中執行的程式碼,僅限於此清單中所描述的存取權,除非應用程式定義域授與其他權限。For example, code that is run in a sandboxed application domain is limited to the access described in this list, unless the application domain grants additional permissions.

從 .NET Framework 2.0 Service Pack 1 開始,嘗試存取通常無法存取的成員時,系統會要求目標物件的授權集,加上具有 ReflectionPermissionFlag.MemberAccess 旗標的 ReflectionPermissionStarting with the .NET Framework 2.0 Service Pack 1, attempting to access members that are normally inaccessible generates a demand for the grant set of the target object plus ReflectionPermission with the ReflectionPermissionFlag.MemberAccess flag. 以完全信任執行的程式碼 (例如從命令列啟動之應用程式中的程式碼),一律可以滿足這些權限。Code that is running with full trust (for example, code in an application that is launched from the command line) can always satisfy these permissions. (這取決於存取安全性關鍵成員時的限制,本文稍後將會說明)。(This is subject to limitations in accessing security-critical members, as described later in this article.)

(選擇性) 沙箱應用程式定義域可以授權有 ReflectionPermissionFlag.MemberAccess 旗標的 ReflectionPermission,本文稍後的存取通常無法存取的成員一節將會說明。Optionally, a sandboxed application domain can grant ReflectionPermission with the ReflectionPermissionFlag.MemberAccess flag, as described in the section Accessing Members That Are Normally Inaccessible, later in this article.

存取安全性關鍵成員Accessing Security-Critical Members

如果成員有 SecurityCriticalAttribute、屬於具有 SecurityCriticalAttribute 的類型,或位於安全性關鍵組件中,就是安全性關鍵成員。A member is security-critical if it has the SecurityCriticalAttribute, if it belongs to a type that has the SecurityCriticalAttribute, or if it is in a security-critical assembly. 從 .NET Framework 4 開始,存取安全性關鍵成員的規則如下:Beginning with the .NET Framework 4, the rules for accessing security-critical members are as follows:

無論是由已編譯程式碼直接存取安全性關鍵成員,或是使用反映來存取安全性關鍵成員,這些規則都一樣。These rules are the same whether a security-critical member is accessed directly by compiled code, or accessed by using reflection.

從命令列執行的應用程式程式碼會以完全信任來執行。Application code that is run from the command line runs with full trust. 只要不是標示為透明,就可以使用反映來存取安全性關鍵成員。As long as it is not marked as transparent, it can use reflection to access security-critical members. 以部分信任來執行相同的程式碼時 (例如,在沙箱化應用程式定義域中),組件的信任層級可決定它是否能夠存取安全性關鍵程式碼:如果組件有強式名稱,並安裝在全域組件快取中,則其為受信任的組件,可以呼叫安全性關鍵成員。When the same code is run with partial trust (for example, in a sandboxed application domain) the assembly's trust level determines whether it can access security-critical code: If the assembly has a strong name and is installed in the global assembly cache, it is a trusted assembly and can call security-critical members. 如果不受信任,則會變成透明 (即使它不是標示為透明),而且不能存取安全性關鍵成員。If it is not trusted, it becomes transparent even though it was not marked as transparent, and it cannot access security-critical members.

如需 .NET Framework 4 的安全模型詳細資訊,請參閱安全性變更For more information about the security model in the .NET Framework 4, see Security Changes.

反映和透明度Reflection and Transparency

從 .NET Framework 4 開始,通用語言執行平台可以從數個因素來決定型別或成員的透明度,包括組件和應用程式定義域二者的信任層級。Beginning with the .NET Framework 4, the common language runtime determines the transparency level of a type or member from several factors, including the trust level of the assembly and the trust level of the application domain. 反映提供 IsSecurityCriticalIsSecuritySafeCriticalIsSecurityTransparent 屬性,可讓您探索類型的透明度。Reflection provides the IsSecurityCritical, IsSecuritySafeCritical, and IsSecurityTransparent properties to enable you to discover the transparency level of a type. 下表顯示這些屬性的有效組合。The following table shows the valid combinations of these properties.

安全性層級Security level IsSecurityCriticalIsSecurityCritical IsSecuritySafeCriticalIsSecuritySafeCritical IsSecurityTransparentIsSecurityTransparent
CriticalCritical true false false
安全關鍵Safe-critical true true false
透明Transparent false false true

使用這些屬性會比檢查組件及其類型的安全性註釋、檢查目前的信任層級,以及嘗試複製執行階段規則更簡單。Using these properties is much simpler than examining the security annotations of an assembly and its types, checking the current trust level, and attempting to duplicate the runtime's rules. 例如,相同的類型從命令列執行時,就是安全性關鍵,在沙箱化應用程式定義域中執行時,就是安全性透明。For example, the same type can be security-critical when it is run from the command line, or security-transparent when it is run in a sandboxed application domain.

MethodBaseFieldInfoTypeBuilderMethodBuilderDynamicMethod 類別上有類似的屬性。There are similar properties on the MethodBase, FieldInfo, TypeBuilder, MethodBuilder, and DynamicMethod classes. (針對其他反映和反映發出抽象,安全性屬性 (security attribute) 會套用至相關聯的方法;例如,以屬性 (property) 來說,安全性屬性會套用至屬性存取子 (property accessor)。(For other reflection and reflection emit abstractions, security attributes are applied to the associated methods; for example, in the case of properties they are applied to the property accessors.)

存取通常無法存取的成員Accessing Members That Are Normally Inaccessible

若要使用反映來叫用無法存取的成員 (根據 Common Language Runtime 的存取範圍規則),您的程式碼必須被授與下列兩個權限之一:To use reflection to invoke members that are inaccessible according to the accessibility rules of the common language runtime, your code must be granted one of two permissions:

  • 若要允許程式碼叫用任何非公用成員:您的程式碼必須被授與具有 ReflectionPermissionFlag.MemberAccess 旗標的 ReflectionPermissionTo allow code to invoke any nonpublic member:Your code must be granted ReflectionPermission with the ReflectionPermissionFlag.MemberAccess flag.

    注意

    根據預設,安全性原則會拒絕將此權限授與源自網際網路的程式碼。By default, security policy denies this permission to code that originates from the Internet. 此權限絕不能授與源自網際網路的程式碼。This permission should never be granted to code that originates from the Internet.

  • 若要允許程式碼叫用任何非公用成員,只要包含被叫用成員的組件授與集,與包含叫用程式碼的組件授與集相同,或是其授權集的子集:您的程式碼必須被授與具有 ReflectionPermissionFlag.RestrictedMemberAccess 旗標的 ReflectionPermissionTo allow code to invoke any nonpublic member, as long as the grant set of the assembly that contains the invoked member is the same as, or a subset of, the grant set of the assembly that contains the invoking code: Your code must be granted ReflectionPermission with the ReflectionPermissionFlag.RestrictedMemberAccess flag.

例如,假設您將網際網路權限,以及具有 ReflectionPermissionFlag.RestrictedMemberAccess 旗標的 ReflectionPermission,授與應用程式定義域,然後執行網際網路應用程式來搭配兩個組件 A 和 B。For example, suppose you grant an application domain Internet permissions plus ReflectionPermission with the ReflectionPermissionFlag.RestrictedMemberAccess flag, and then run an Internet application with two assemblies, A and B.

  • 組件 A 可以使用反映來存取組件 B 的私用成員,因為組件 B 的授權集不包含未授與 A 的任何權限。Assembly A can use reflection to access private members of assembly B, because the grant set of assembly B does not include any permissions that A has not been granted.

  • 組件 A 無法使用反射來存取 .NET Framework 組件的私有成員 (例如 mscorlib.dll),因為 mscorlib.dll 為完全受信任,擁有尚未授與組件 A 的權限。當程式碼存取安全性查核在執行階段查核堆疊時,會擲回 MemberAccessExceptionAssembly A cannot use reflection to access private members of .NET Framework assemblies such as mscorlib.dll, because mscorlib.dll is fully trusted and therefore has permissions that have not been granted to assembly A. A MemberAccessException is thrown when code access security walks the stack at run time.

序列化Serialization

進行序列化時,不論存取範圍為何,具有 SecurityPermissionAttribute.SerializationFormatter 旗標的 SecurityPermission 都可讓您取得或設定可序列化類型的成員。For serialization, SecurityPermission with the SecurityPermissionAttribute.SerializationFormatter flag provides the ability to get and set members of serializable types, regardless of accessibility. 此權限可讓程式碼探索及變更執行個體的私用狀態。This permission enables code to discover and change the private state of an instance. (除了授與適當的權限,也必須在中繼資料中將該類型標示為可序列化。)(In addition to being granted the appropriate permissions, the type must be marked as serializable in metadata.)

MethodInfo 類型的參數Parameters of Type MethodInfo

避免撰寫採用 MethodInfo 參數的公用成員,特別是針對受信任的程式碼。Avoid writing public members that take MethodInfo parameters, especially for trusted code. 這類成員比較容易受到惡意程式碼攻擊。Such members might be more vulnerable to malicious code. 例如,請考慮採用 MethodInfo 參數之高度信任程式碼中的公用成員。For example, consider a public member in highly trusted code that takes a MethodInfo parameter. 假設公用成員在所提供的參數上間接呼叫 Invoke 方法。Assume that the public member indirectly calls the Invoke method on the supplied parameter. 如果公用成員沒有執行必要的權限檢查,呼叫 Invoke 方法一定會成功,因為安全性系統會判定呼叫者是受高度信任。If the public member does not perform the necessary permission checks, the call to the Invoke method will always succeed, because the security system determines that the caller is highly trusted. 即使惡意程式碼沒有直接叫用方法的權限,它還是可以藉由呼叫公用成員來間接執行。Even if malicious code does not have the permission to directly invoke the method, it can still do so indirectly by calling the public member.

版本資訊Version Information

請參閱See also