CA2117:APTCA 類型應該只擴充 APTCA 基底類型
型別名稱 |
AptcaTypesShouldOnlyExtendAptcaBaseTypes |
CheckId |
CA2117 |
分類 |
Microsoft.Security |
中斷變更 |
中斷 |
原因
在具有 AllowPartiallyTrustedCallersAttribute 屬性 (Attribute) 之組件中之公用或保護的型別,會繼承自不具該屬性之組件中所宣告的型別。
規則描述
根據預設,在具有強式名稱 (Strong Name) 的組件中,公用或保護的型別會受到完全信任所需的繼承要求隱含保護。以 AllowPartiallyTrustedCallersAttribute (APTCA) 屬性標記的強式名稱組件則沒有這種保護。這個屬性會停用繼承要求。這讓組件中所宣告的公開 (Expose) 型別可由不具有完全信任的型別繼承。
當完全受信任的組件中含有 APTCA 屬性,且組件中的型別會繼承自不允許部分信任之呼叫端的型別時,就可能會產生安全性弱點。如果 T1 和 T2 這兩個型別會符合下列條件,則惡意的呼叫端可以使用型別 T1,略過保護 T2 的隱含完全信任繼承要求:
T1 是具有 APTCA 屬性,且會在完全信任之組件中宣告的公用型別。
T1 繼承自組件外部的型別 T2。
T2 的組件不具有 APTCA 屬性,因此部分信任之組件中的型別不得繼承這個組件。
部分信任的型別 X 可以繼承自 T1,讓它可以存取 T2 中所宣告的繼承成員。因為 T2 不具有 APTCA 屬性,所以它的直屬衍生型別 (T1) 必須滿足完全信任所需的繼承要求。T1 具有完全信任,因此可以通過這項檢查。安全性的風險在於 X 並不能滿足可保護 T2 免於未受信任子類別化 (Subclassing) 的繼承要求。基於這個原因,具有 APTCA 屬性的型別不得擴充不具這個屬性的型別。
另一個或許更為常見的安全性問題,在於衍生型別 (T1) 可以透過程式設計人員的錯誤,將需要完全信任之型別 (T2) 的公用成員公開。發生這種情況時,未受信任的呼叫端將可以存取只有完全信任之型別才能取得的資訊。
如何修正違規
如果回報為違規的型別位於不需要 APTCA 屬性的組件,請將該型別移除。
如果組件需要 APTCA 屬性,請將完全信任所需的繼承要求加入至型別,以防止未受信任的型別進行繼承。
您也可以將 APTCA 屬性加入至報告的違規基底型別 (Base Type) 所在的組件,藉此修正違規。如果未先針對組件中的所有程式碼或與組件相依之所有程式碼進行仔細的安全性檢視,則請勿採用此做法。
隱藏警告的時機
若要放心地隱藏這項規則的警告,您必須確保型別所公開的公用成員未直接或間接地允許未受信任之呼叫端存取可能遭到惡意使用的機密資訊、作業或資源。
範例
下列範例會使用兩個組件與一個測試應用程式,說明這項規則所偵測的安全性弱點。第一個組件不具有 APTCA 屬性,因此不可由部分信任的型別 (以前述的 T2 表示) 繼承。
using System;
using System.Security;
using System.Security.Permissions;
using System.Reflection;
// This code is compiled into a strong-named assembly
// that requires full trust.
namespace AptcaTestLibrary
{
public class ClassRequiringFullTrustWhenInherited
{
// This field should be overridable by fully trusted derived types.
protected static string location = "shady glen";
// A trusted type can see the data, but cannot change it.
public virtual string TrustedLocation
{
get
{
return location;
}
}
}
}
第二個組件 (以前述的 T1 表示) 會受到完全信任,因此允許有部分信任的呼叫端。
using System;
using System.Security;
using System.Security.Permissions;
using System.Reflection;
// This class is compiled into an assembly that executes with full
// trust and allows partially trusted callers.
// Violates rule: AptcaTypesShouldOnlyExtendAptcaBaseTypes.
namespace AptcaTestLibrary
{
public class InheritAClassRequiringFullTrust:
ClassRequiringFullTrustWhenInherited
{
private DateTime meetingDay = DateTime.Parse("February 22 2003");
public override string ToString()
{
// Another error:
// This method gives untrusted callers the value
// of TrustedLocation. This information should
// only be seen by trusted callers.
string s = String.Format(
"Meet at the {0} {1}!",
this.TrustedLocation, meetingDay.ToString());
return s;
}
}
}
測試型別 (以前述的 X 表示) 位於部分信任的組件中。
using System;
using AptcaTestLibrary;
// If this test application is run from the local machine,
// it gets full trust by default.
// Remove full trust.
[assembly: System.Security.Permissions.PermissionSetAttribute(
System.Security.Permissions.SecurityAction.RequestRefuse, Name = "FullTrust")]
namespace TestSecLibrary
{
class InheritFromAFullTrustDecendent : ClassRequiringFullTrust
{
public InheritFromAFullTrustDecendent()
{
// This constructor maliciously overwrites the protected
// static member in the fully trusted class.
// Trusted types will now get the wrong information from
// the TrustedLocation property.
InheritFromAFullTrustDecendent.location = "sunny meadow";
}
public override string ToString()
{
return InheritFromAFullTrustDecendent.location;
}
}
class TestApctaInheritRule
{
public static void Main()
{
ClassRequiringFullTrust iclass =
new ClassRequiringFullTrust();
Console.WriteLine(iclass.ToString());
// You cannot create a type that inherits from the full trust type
// directly, but you can create a type that inherits from
// the APTCA type which in turn inherits from the full trust type.
InheritFromAFullTrustDecendent inherit =
new InheritFromAFullTrustDecendent();
//Show the inherited protected member has changed.
Console.WriteLine("From Test: {0}", inherit.ToString());
// Trusted types now get the wrong information from
// the TrustedLocation property.
Console.WriteLine(iclass.ToString());
}
}
}
這個範例產生下列輸出。