.NET Framework 定義 24 種安全權限(檔案 I/O、UI、反射、網路、資料存取等),組成權限集指派給組件。載入時依證據(來源/強名稱)授予權限。AppDomain 預設 FullTrust,本機代碼通常全權運行,缺乏沙箱保護。部分信任代碼嘗試存取無權資源拋出 SecurityException。CLR 執行堆疊巡查確保所有呼叫者具備權限;Assert 可終止巡查,但需擁有該權限與 SecurityPermissionFlag.Assertion。
僅允許 BasicHttpBinding、WSHttpBinding、WebHttpBinding 在部分信任下調用,且限無安全性或 Transport 安全;WSHttpBinding 禁用訊息安全/可靠傳訊/交易。綁定要求:執行權限 + Web 連線權限(目標 URI)。配置檔不得引用憑證存儲區(需 FullTrust)。
在 Proxy 類別標記 [PermissionSet(SecurityAction.Assert, Name="FullTrust")],隱藏 ClientBase<T> 需 FullTrust 的方法。前提:Proxy 組件本身獲授 FullTrust(透過 .NET Configuration 工具依強名稱授予,或放入 GAC 並標記 AllowPartiallyTrustedCallers)。契約介面須同屬該組件(WCF 要求上游呼叫鏈全為 FullTrust)。
[assembly: AllowPartiallyTrustedCallers]
[ServiceContract] public interface IMyContract { [OperationContract] void MyMethod(); }
[PermissionSet(SecurityAction.Assert, Name="FullTrust")]
public class MyContractClient : ClientBase<IMyContract>, IMyContract, IDisposable
{
public void MyMethod() { Channel.MyMethod(); }
public new void Close() { base.Close(); }
void IDisposable.Dispose() { Close(); }
}
部分信任用戶端無網路權限,卻透過 Proxy 呼叫 TCP 服務——Proxy 抑制了 WCF 的安全要求,讓惡意代碼繞過 CAS 限制。必須改為「結構化權限請求」:Proxy 僅在必要時 Assert FullTrust,並根據實際操作主動要求對應 CAS 權限。
Close 明確 Assert FullTrust(壓制 WCF 綁定建構/開啟/關閉時的 FullTrust 要求)。Channel 屬性,getter 內 Assert FullTrust。protected object Invoke(string operation, params object[] args):DemandAsyncPermissionsDemandSyncPermissions(委派 DemandClientPermissions)Assert FullTrust → 反射呼叫 Channel 方法RevertAssertpublic abstract class PartialTrustClientBase<T> : ClientBase<T>, IDisposable where T : class
{
[PermissionSet(SecurityAction.Assert, Name="FullTrust")]
protected PartialTrustClientBase() { }
// ... 其他建構子同樣 Assert
protected object Invoke(string operation, params object[] args)
{
if (IsAsyncCall(operation)) DemandAsyncPermissions();
DemandSyncPermissions(operation);
CodeAccessSecurityHelper.PermissionSetFromStandardSet(StandardPermissionSet.FullTrust).Assert();
try { return typeof(T).GetMethod(operation).Invoke(Channel, args); }
finally { PermissionSet.RevertAssert(); }
}
// ...
}
| 場景 | 原始 WCF 要求 | 結構化要求 |
|---|---|---|
| TCP 綁定 | 執行 + 非受控代碼 + 不受限 DNS + Socket 連線 | 執行 + 不受限 DNS + Socket 連線 |
| IPC 綁定 | 執行 + 非受控代碼 + 控制策略/證據 | 執行 + 控制策略/證據 |
| WS/WS-Dual/Basic/Web | 執行 + 非受控代碼 + Web 連線 | 執行 + Web 連線 (Dual 另需 Web 接受回調 + 最小 ASP.NET 宿主) |
| MSMQ | 執行 + 非受控代碼 | 執行 + MSMQ 發送權限 |
| 非同步/雙工/用戶名憑證協商 | 控制策略/證據 | 控制策略/證據 |
| Windows 互動式憑證 | 環境變數 USERNAME | 環境變數 USERNAME |
| Windows 替代憑證 | 控制主體 + USERNAME | 控制主體 |
| 診斷追蹤 | 非受控代碼 + COMPUTERNAME | COMPUTERNAME + 檔案 I/O (路徑發現/附加/寫入) |
| 交易流 | FullTrust | 不受限分散式交易權限 |
| 憑證存取 | FullTrust | 列舉/開啟/列舉存儲區權限 |
關鍵改進:移除所有非受控代碼要求、FullTrust 降級為具體權限、新增 MSMQ/交易/憑證/追蹤的精確權限。
public static void DemandClientPermissions<T>(this ClientBase<T> proxy, string opName) where T : class
{
DemandClientConnectionPermissions(proxy.Endpoint);
DemandTransactionPermissions(proxy.Endpoint, opName);
DemandTracingPermissions();
DemandClientSecurityPermissions(proxy);
DemandEnvironmentPermissions(proxy);
DemandClientStorePermissions(proxy.Endpoint);
}
static void DemandClientConnectionPermissions(ServiceEndpoint ep)
{
PermissionSet set = new PermissionSet(PermissionState.None);
if (ep.Binding is NetTcpBinding)
{
set.AddPermission(new SocketPermission(NetworkAccess.Connect, TransportType.Tcp,
ep.Address.Uri.Host, ep.Address.Uri.Port));
set.AddPermission(new DnsPermission(PermissionState.Unrestricted));
}
// ... 其他綁定
set.Demand();
}
static void DemandTransactionPermissions(ServiceEndpoint ep, string opName)
{
bool flow = false, allowed = false;
if (ep.Binding is NetTcpBinding)
flow = (ep.Binding as NetTcpBinding).TransactionFlow;
// ... 檢查其他綁定
if (flow && Transaction.Current != null)
{
foreach (var op in ep.Contract.Operations)
{
if (opName != null && opName != op.Name) continue;
foreach (var beh in op.Behaviors)
if (beh is TransactionFlowAttribute attr && attr.Transactions != TransactionFlowOption.NotAllowed)
{ allowed = true; break; }
if (allowed) break;
}
if (allowed) new DistributedTransactionPermission(PermissionState.Unrestricted).Demand();
}
}
依相同原理實作,額外處理回調端點的 Web 接受權限與最小 ASP.NET 宿主權限。
PartialTrustClientBase 讓部分信任用戶端安全、正確地使用 WCF 全功能(含 TCP、IPC、MSMQ、交易、雙工、憑證、診斷),不再依賴 FullTrust,也不再暴露誘餌攻擊面。下一篇將處理部分信任服務與宿主端。