国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

針對 .NET 框架的安全編碼指南

2024-07-10 12:59:07
字體:
來源:轉載
供稿:網友
摘要:公共語言運行庫和 microsoft .net 框架對所有托管代碼應用程序強制實施基于證據的安全性。大多數代碼很少需要或完全不需要為安全性進行顯式編碼。本文簡要描述了安全系統,討論了可能需要在代碼中考慮的安全問題,并為分類組件提供了指南,以便您了解為了確保代碼的安全可能需要解決什么問題。
前提條件:讀者應當熟悉公共語言運行庫和 microsoft(r) .net 框架,以及基于證據的安全性和代碼訪問安全性的基本知識。


本頁內容
基于證據的安全性和代碼訪問安全性
安全編碼的目標
安全編碼的方法
安全編碼的最佳做法
確保狀態數據的安全
確保方法訪問的安全
包裝程序代碼
非托管代碼
用戶輸入
遠程處理注意事項
受保護的對象
序列化
應用程序域跨域問題
評估權限
其他安全技術

基于證據的安全性和代碼訪問安全性
結合使用兩項單獨的技術來保護托管代碼:

• 基于證據的安全性決定將什么權限授予代碼。

• 代碼訪問安全性負責檢查堆棧上的所有代碼是否擁有執行某項操作的所需權限。


權限將這兩個技術綁定在一起:權限是執行某個特定受保護操作的權利。例如,“讀取 c:/temp”是一個文件權限;“連接到 www.msn.com”是一個網絡權限。

基于證據的安全性決定授予代碼的權限。證據是有關用作安全策略機制輸入的任何程序集(授予權限的單位)的已知信息。假如將證據作為輸入,系統將評估由管理員設置的安全策略,以決定可以將什么權限授予代碼。代碼本身可以使用權限請求來影響被授予的權限。權限請求被表示為使用自定義屬性語法的程序集級別的聲明性安全性。但是,代碼不能以任何方式獲取多于或少于策略系統所允許的權限。權限授予只發生一次,指定程序集中所有代碼的權利。要查看或編輯安全策略,請使用 .net 框架配置工具 (mscorcfg.msc)。

下表列出了策略系統用來向代碼授予權限的某些常見證據類型。除了這里列出的標準證據類型(它們是由安全系統提供的)以外,還可以使用用戶定義的新類型來擴展證據集合。

證據 說明
哈希值
程序集的哈希值

出版商
authenticode(r) 簽名者

強名稱
公鑰+名稱+版本

站點
代碼來源的 web 站點

url
代碼來源的 url

區域
代碼來源的 internet explorer 區域


代碼訪問安全性負責處理執行所授予權限的安全檢查。這些安全檢查的獨特方面是,它們不僅會檢查試圖執行受保護操作的代碼,而且會沿堆棧檢查它的所有調用方。要讓檢查獲得成功,所有被檢查的代碼都必須具有所需權限(可以重寫)。

安全檢查是有好處的,因為它們可以防止引誘攻擊。引誘攻擊是指未經授權的代碼調用您的代碼,并引誘您的代碼代替未經授權的代碼執行某些操作。假設您有一個讀取文件的應用程序,并且安全策略將讀取文件的權限授予了您的代碼。因為您的所有應用程序代碼都擁有權限,所以會通過代碼訪問安全性檢查。但是,如果無權訪問文件的惡意代碼以某種方式調用了您的代碼,那么安全檢查將失敗,這是因為不受信任的代碼調用了您的代碼,從而在堆棧上可見。

需要注意的是,該安全性的所有方面都是基于允許代碼執行什么操作這一機制的。基于登錄信息對用戶進行授權是基礎操作系統完全獨立的安全功能。請將這兩個安全系統看作多層防御:例如,要訪問一個文件,必須要通過代碼授權和用戶授權。雖然在許多依賴用戶登錄信息或其他憑據來控制某些用戶可以和不可以執行某項操作的應用程序中,用戶授權很重要,但這種類型的安全不是本文討論的重點。


安全編碼的目標
我們假設安全策略是正確的,并且潛在的惡意代碼不具有授予信任代碼的權限,該權限允許受信任代碼安全地執行功能更強大的操作。(如果進行其他假設,將使一種類型的代碼無法與其他類型的代碼區分開,從而使問題不會發生。)使用強制 .net 框架的權限和代碼中實施的其他措施時,您必須建立障礙來防止惡意代碼獲得您不希望它得到的信息,或防止它執行惡意的操作。此外,在受信任代碼的所有預期情況中,必須在代碼的安全性和可用性之間找到一種平衡。

基于證據的安全策略和代碼訪問安全性為實現安全性提供了非常強大的顯式機制。大多數應用程序代碼只需要使用 .net 框架實現的基礎結構。在某些情況下,還需要其他特定于應用程序的安全性,該安全性是通過擴展安全系統或使用新的特殊方法生成的。


安全編碼的方法
這些安全技術的一個優點是,您通??梢酝浰鼈兊拇嬖凇H绻麑⒋a執行任務所需的權限授予代碼,那么一切將正常工作(同時,您將能夠抵御潛在的攻擊,例如,前面描述的引誘攻擊)。但是,在某些特定情況下,您必須顯式地處理安全問題。下面的幾個部分描述了這些方法。即使這些部分并不直接適用于您,但了解這些安全問題總是有用的。

安全中立代碼
安全中立代碼不對安全系統執行任何顯式操作。它只使用獲得的權限來運行。盡管無法捕獲受保護操作(例如,使用文件、網絡等)的安全異常會導致不良的用戶體驗(這是指包含許多細節的異常,但對大多數用戶來說這些細節是完全模糊的),但這種方式利用了安全技術,因為即使是高度受信任的代碼也無法降低安全保護的程度。可能發生的最壞情況是,調用方將需要許多權限,否則會被安全機制禁止運行。

安全中立庫具有您應當了解的特殊特征。假設此庫提供的 api 元素需要使用文件或調用非托管代碼;如果您的代碼沒有相應的權限,將無法按描述運行。但是,即使該代碼擁有權限,調用它的任何應用程序代碼也必須擁有相同的權限才能運行。如果呼叫代碼沒有正確的權限,那么安全異常將作為代碼訪問安全性堆棧審核的結果出現。如果可以要求調用方對庫所執行的所有操作都擁有權限,那么這將是實現安全性的簡單且安全的方式,因為它不涉及危險的安全重寫。但是,如果想讓調用庫的應用程序代碼不受權限要求的影響,并減少對非常強大的權限的需要,您必須了解與受保護資源配合工作的庫模型,這部分內容將在本文的“公開受保護資源的庫代碼”部分中進行描述。

不屬于可重用組件的應用程序代碼
如果您的代碼是不會被其他代碼調用的應用程序的一部分,那么安全性很簡單,并且可能不需要特殊的編碼。但請記住,惡意代碼可以調用您的代碼。雖然代碼訪問安全性機制可以阻止惡意代碼訪問資源,但此類惡意代碼仍然可以讀取可能包含敏感信息的字段或屬性的值。

此外,如果您的代碼可以從 internet 或其他不可靠的來源接受用戶輸入,則必須小心惡意輸入。

有關詳細信息,請參閱本文的確保狀態數據的安全和用戶輸入。

本機代碼實現的托管包裝程序
通常在此情況下,某些有用的功能是在本機代碼中實現的,并且您想在不改寫它的情況下將其用于托管代碼。托管包裝程序很容易編寫為平臺調用或使用 com 互操作。但是,如果您這樣做,包裝程序的調用方必須擁有非托管代碼的權利,調用才能成功。在默認策略下,這意味著從 intranet 和 internet 下載的代碼將不會與包裝程序配合工作。

更好的方法是將這些非托管代碼權利只授予包裝程序代碼,而不要授予使用這些包裝程序的所有應用程序。如果基礎功能很安全(不公開任何資源)并且實現也很安全,則包裝程序只需要斷言它的權利,這將使任何代碼都能夠通過它進行調用。如果涉及到資源,則安全編碼應與下一部分中描述的庫代碼情況相同。因為包裝程序向調用方潛在地公開了這些問題,所以需要對本機代碼的安全性進行仔細驗證,這是包裝程序的責任。

有關詳細信息,請參閱本文的非托管代碼和評估權限部分。

公開受保護資源的庫代碼
這是功能最強大因此也是潛在最危險(如果方法不正確)的安全編碼方式:您的庫充當了其他代碼用來訪問特定資源(這些資源以其他方式是不可用的)的接口,正如 .net 框架類對它們所使用的資源施加權限一樣。無論在哪里公開資源,代碼都必須先請求適用于資源的權限(即,執行安全檢查),然后通常需要斷言它執行實際操作的權利。

有關詳細信息,請參閱本文的非托管代碼和評估權限部分。


安全編碼的最佳做法
注 除非另行指定,代碼示例都是用 c# 編寫的。

權限請求是使代碼獲得安全性的好方法。這些請求可讓您做兩件事:

• 請求代碼運行所必需的最低權限。

• 確保代碼所接收的權限不會超過它實際需要的權限。

例如:

[assembly:fileiopermissionattribute
(securityaction.requestminimum, write="c://test.tmp")]
[assembly:permissionset
(securityaction.requestoptional, unrestricted=false)]
…securityaction.requestrefused_



該示例告訴系統:除非代碼收到寫入 c:/test.tmp 的權限,否則不應當運行。如果代碼遇到沒有授予該權限的安全策略,那么將引發 policyexception,并且代碼不會運行。您可以確保代碼將被授予該權限,并且不必擔心由于權限太少而導致的錯誤。

該示例還告訴系統:不需要其他權限。除此之外,代碼將被授予策略選擇要授予它的任何權限。雖然額外的權限不會導致損害,但如果某處有安全問題,則擁有較少的權限可以很好地堵住漏洞。帶有代碼不需要的權限會導致安全問題。

將代碼所接收的權限限制為最少特權的另一個方式是列出要拒絕的特定權限。如果您要求所有權限都是可選的,并從該請求中排除特定權限,那么權限通常會被拒絕。


確保狀態數據的安全
處理敏感數據或作出任何安全決定的應用程序需要使該數據處于自己的控制下,并且不能讓其他的潛在惡意代碼直接訪問該數據。使數據安全地保留在內存中的最佳方式是將其定義為私有或內部(限制在同一程序集的范圍內)變量。但是,此數據也服從于您應當知道的訪問權:

• 在反射時,引用了對象的高度受信任代碼可以獲得并設置私有成員。

• 使用序列化時,如果高度受信任的代碼可以通過對象的序列化形式訪問相應數據,那么它就可以有效地獲得和設置私有成員。

• 在調試時,可以讀取該數據。


確保自己的任何方法或屬性都沒有無意地公開這些值。

在某些情況下,數據可以使用“protected”加以保護,這時,只能訪問該類及其派生類。但是,由于存在其他公開的可能性,您還應當采取下面的預防措施:

• 通過將類的派生限制在同一個程序集內,或使用聲明性安全來要求某些標識或權限以便從您的類中派生,從而控制允許哪些代碼從您的類中派生(請參閱本文的確保方法訪問的安全部分)。

• 確保所有派生類都實現了相似的保護或者被密封。


裝箱的值類型
如果您認為已經分發了無法修改原始定義的類型的副本,有時還可以修改裝箱的值類型。返回裝箱的值類型時,您所返回的是對值類型的引用,而不是對值類型副本的引用,因而允許調用您代碼的代碼修改您的變量值。

以下 c# 代碼示例顯示了如何使用引用來修改裝箱的值類型。

using system;
using system.reflection;
using system.reflection.emit;
using system.threading;
using system.collections;
class bug {
// suppose you have an api element that exposes a
// field through a property with only a get accessor.
public object m_property;
public object property {
get { return m_property;}
set {m_property = value;} // (if applicable)
}
// you can modify the value of this by doing
// the byref method with this signature.
public static void m1( ref int j ) {
j = int32.maxvalue;
}
public static void m2( ref arraylist j )
{
j = new arraylist();
}
public static void main(string[] args)
{
console.writeline( "////// doing this with value type" );
{
bug b = new bug();
b.m_property = 4;
object[] objarr = new object[]{b.property};
console.writeline( b.m_property );
typeof(bug).getmethod( "m1" ).invoke( null, objarr );
// note that the property changed.
console.writeline( b.m_property );
console.writeline( objarr[0] );
}
console.writeline( "////// doing this with a normal type" );
{
bug b = new bug();
arraylist al = new arraylist();
al.add("elem");
b.m_property = al;
object[] objarr = new object[]{b.property};
console.writeline( ((arraylist)(b.m_property)).count );
typeof(bug).getmethod( "m2" ).invoke( null, objarr );
// note that the property does not change.
console.writeline( ((arraylist)(b.m_property)).count );
console.writeline( ((arraylist)(objarr[0])).count );
}
}
}


確保方法訪問的安全
某些方法可能不適合由不受信任的任意代碼調用它們。此類方法會導致幾個風險:方法可能會提供某些受限制信息;可能會相信傳遞給它的任何信息;可能不會對參數進行錯誤檢查;或者,如果參數錯誤,可能會出現故障或執行某些有害操作。您應當注意這些情況,并采取適當的操作來確保方法的安全。

在某些情況下,您可能需要限制不打算公開使用、但仍必須是公共的方法。例如,您可能有一個需要在自己的 dll 之間進行調用的接口,因此它必須是公共的,但您不想公開它,以防止用戶使用它或防止惡意代碼利用它作為入口點進入到您的組件中。對不打算公共使用(但仍必須是公共)的方法進行限制的另一個常見理由是,避免用文檔記錄和支持非常內部的接口。

托管代碼為限制方法訪問提供了幾個方式:

• 將可訪問性的作用域限制到類、程序集或派生類(如果它們是可信任的)。這是限制方法訪問的最簡單方式。請注意,通常派生類的可信賴度比它們派生自的類更低,但在某些情況下,它們可以共享超類標識。特別是,不要從關鍵字 protected 推斷信任情況,因為在安全上下文中,該關鍵字不是必須使用的。

• 將方法訪問限制到指定標識(實質上,是您選擇的任何特殊證據)的調用方。

• 將方法訪問限制到擁有您所選權限的調用方。


同樣,聲明性安全也允許您控制類的繼承。您可以使用 inheritancedemand 執行以下操作:

• 要求派生類擁有指定的標識或權限。

• 要求重寫特定方法的派生類擁有指定的標識或權限。


示例:保護對類或方法的訪問
以下示例顯示了如何確保公共方法的安全,以限制訪問。

• sn -k 命令用于創建新的私鑰/公鑰對。私鑰部分需要使用強名稱簽署代碼,并由代碼發行者安全地保留。(如果泄露,任何人都可以在他們的代碼上假冒您的簽名,從而使保護措施失效。)

通過強名稱標識來確保方法的安全

sn -k keypair.dat
csc/r:app1.dll /a.keyfile:keypair.dat app1.cs
sn -p keypair.dat public.dat
sn -tp public.dat >publichex.txt

[strongnameidentitypermissionattribute
(securityaction.linkdemand,
publickey="_",hex_",name="app1",
version="0.0.0.0")]
public class class1


• csc 命令用于編譯和簽署 app1,以授于它訪問受保護方法的權限。

• 后面的兩個 sn 命令用于從密鑰對中提取公鑰部分,并將它格式化為十六進制。

• 示例的下半部分是摘錄的受保護方法的源代碼。自定義屬性可定義強名稱,指定密鑰對中的公鑰,并插入從 sn 得到的十六進制格式的數據作為 publickey 屬性。

• 在運行時,由于 app1 擁有必需的強名稱簽名,所以被允許使用 class1。


該示例使用 linkdemand 來保護 api 元素;有關使用 linkdemand 的限制的重要信息,請參閱本文后面的部分。

防止不受信任的代碼使用類和方法
使用以下聲明可以防止部分信任的代碼使用類和方法(包括屬性和事件)。通過將這些聲明應用于類,可以對該類的所有方法、屬性和事件應用保護;但請注意,字段訪問不會受到聲明性安全的影響。請注意,鏈接請求只保護直接調用方,并且仍可能會受到引誘攻擊(本文的基于證據的安全性和代碼訪問安全性部分對此進行了描述)。

具有強名稱的程序集將聲明性安全應用于所有可公開訪問的方法、屬性和事件,因此只有完全受信任的調用方才能使用它們,除非程序集通過應用 allowpartiallytrustedcallers 屬性顯式地決定參與使用。因此,通過顯式地標記類來排除不受信任的調用方,只對未簽名的程序集或具有該屬性的程序集、以及原本就不打算用于不受信任調用方的類型的子集才是必需的。有關全部詳細信息,請參閱 microsoft .net 框架的第 1 版安全更改文檔。

• 對于公共的非密封類:

[system.security.permissions.permissionsetattribute(system.security.
permissions.securityaction.inheritancedemand, name="fulltrust")]
[system.security.permissions.permissionsetattribute
(system.security.permissions.securityaction.linkdemand, name="fulltrust")]
public class canderivefromme


• 對于公共的密封類:

[system.security.permissions.permissionsetattribute
(system.security.permissions.securityaction.linkdemand, name="fulltrust")]
public sealed class cannotderivefromme


• 對于公共的抽象類:

[system.security.permissions.permissionsetattribute
(system.security.permissions.securityaction.inheritancedemand, name="fulltrust")]
[system.security.permissions.permissionsetattribute
(system.security.permissions.securityaction.linkdemand, name="fulltrust")]
public abstract class cannotcreateinstanceofme_cancasttome


• 對于公共的虛擬函數:

class base {
[system.security.permissions.permissionsetattribute
(system.security.permissions.securityaction.inheritancedemand,
name="fulltrust")]
[system.security.permissions.permissionsetattribute(
system.security.permissions.securityaction.linkdemand,
name="fulltrust")]
public override void canoverrideorcallme() { ... }


• 對于公共的抽象函數:

class base {
[system.security.permissions.permissionsetattribute
(system.security.permissions.securityaction.inheritancedemand, name="fulltrust")]
[system.security.permissions.permissionsetattribute
(system.security.permissions.securityaction.linkdemand,
name="fulltrust")]
public override void canoverrideme() { ... }


• 對于基函數不需要完全信任的公共重寫函數:

class derived {
[system.security.permissions.permissionsetattribute
(system.security.permissions.securityaction.demand, name="fulltrust")]
public override void canoverrideorcallme() { ... }


• 對于基函數需要完全信任的公共重寫函數:

class derived {
[system.security.permissions.permissionsetattribute
(system.security.permissions.securityaction.linkdemand,
name="fulltrust")]
public override void canoverrideorcallme() { ... }


• 對于公共接口:

[system.security.permissions.permissionsetattribute
(system.security.permissions.securityaction.inheritancedemand,
name="fulltrust")]
[system.security.permissions.permissionsetattribute
(system.security.permissions.securityaction.linkdemand,
name="fulltrust")]
public interface cancasttome



demand 與 linkdemand
聲明性安全提供了兩種類似的、但檢查方式大不相同的安全檢查。花些時間了解這兩種形式是值得的,因為錯誤的選擇會導致脆弱的安全性或性能損失。本部分并不打算完整地說明這些功能;有關完整的詳細信息,請參閱產品文檔。

聲明性安全可提供以下安全檢查:

• demand 指定代碼訪問安全性的堆棧審核:堆棧上的所有調用方都必須擁有權限或標識才能通過。demand 會發生在每個調用上,這是因為堆??赡馨煌恼{用方。如果您重復調用某個方法,則每次都會進行該安全檢查。demand 對引誘攻擊具有強大的抵御能力;它可捕獲試圖通過它的未經授權的代碼。

• linkdemand 發生在實時 (jit) 編譯時(在前面的示例中,當引用 class1 的 app1 代碼將要執行時),并且它只檢查直接調用方。該安全檢查不檢查調用方的調用方。一旦通過該檢查,無論它被調用多少次,都不會有其他安全開銷。但是,它無法防御引誘攻擊。如果使用 linkdemand,則您的接口是安全的,但通過測試并且可以引用您的代碼的任何代碼都可以潛在地破壞安全性,因為它們允許使用授權代碼調用惡意代碼。因此,除非可以完全避免所有可能的弱點,否則不要使用 linkdemand。


使用 linkdemand 時所需的額外預防措施必須是“手工制訂的”(安全系統可以幫助實施)。任何錯誤都會導致安全漏洞。使用您代碼的所有經授權代碼都必須通過執行以下操作,來負責實現其他安全性:

• 將呼叫代碼的訪問權限制到類或程序集。

• 為該代碼設置相同的安全檢查,并強制它的調用方這樣做。例如,如果您編寫的代碼調用了某個方法,而該方法通過對 securitypermission.unmanagedcode 權限使用 linkdemand 獲得保護,那么您的方法也應當對該權限使用 linkdemand(或 demand,這是更強的手段)。例外情況是,假如代碼中有其他安全保護機制(例如,demand),則您的代碼將以一種總是安全的或您決定是安全的受限方式使用 linkdemand 所保護的方法。在調用方負責削弱對基礎代碼的安全保護情況下,會出現此例外情況。

• 確保它的調用方無法進行欺騙,以代表它去調用受保護的代碼(也就是說,調用方不能強迫經授權的代碼將特定參數傳遞給受保護的代碼,或從中獲得結果)。


接口和 linkdemands
如果具有 linkdemand 的虛擬方法、屬性或事件重寫了某個基類方法,則此基類方法也必須具有相同的 linkdemand,以便重寫方法也是安全的。惡意代碼可能會強制轉換回基礎類型,并調用基類方法。還要注意,可以將 linkdemands 隱式地添加到不具有 allowpartiallytrustedcallersattribute 程序集級屬性的程序集中。

好的做法是,當接口方法也有 linkdemands 時,使用 linkdemands 對方法實現進行保護。

關于對接口使用 linkdemands,請注意以下事項:

• allowpartiallytrustedcallers 屬性會影響接口。

• 可以將 linkdemands 放在接口上,以有選擇地挑出某些接口,使其不能由部分信任的代碼使用(例如,在使用 allowpartiallytrustedcallers 屬性時)。

• 如果在不包含 allowpartiallytrustedcallers 屬性的程序集中定義接口,則可以在部分信任的類上實現該接口。

• 如果將 linkdemand 放在一個實現接口方法的類的公共方法上,在隨后強制轉換到該接口并調用該方法時,將不會執行 linkdemand。在這種情況下,因為是對接口進行鏈接,所以只考慮接口上的 linkdemand。


應當審閱以下各項是否有安全問題:

• 接口方法上的顯式鏈接請求。確保這些鏈接請求提供了預期的保護。確定惡意代碼是否可以使用強制轉換來避開前面描述的鏈接請求。

• 具有鏈接請求的虛擬方法。

• 它們實現的類型和接口應當一致地使用 linkdemands。


虛擬內部重寫
在確認代碼對其他程序集不可用時,需要了解類型系統可訪問性的細微差別。聲明 virtual 和 internal 的方法可以重寫超類的 vtable 條目,并且只能在同一個程序集的內部使用,因為它是內部的。但是,重寫的可訪問性是由 virtual 關鍵字決定的,并且只要代碼能夠訪問類本身,就可以從另一個程序集對該可訪問性進行重寫。如果重寫的可能性比較小,請使用聲明性安全解決它,或者刪除 virtual 關鍵字(如果它不是必需的)。


包裝程序代碼
包裝程序代碼(特別是在包裝程序比使用它的代碼具有更高可信度時)可以顯露一組獨特的安全漏洞。如果沒有將調用方的受限制權限包括在適當的安全檢查中,則代表調用方所執行的任何操作都是可能被利用的潛在漏洞。

不要通過包裝程序來啟用調用方本身無法執行的某些操作。在執行某些涉及受限制安全檢查的操作時(與完整的堆棧審核請求相反),會有特殊的危險性。涉及到單一級別的檢查時,在實際調用方與可疑 api 元素之間插入包裝程序代碼,可以很容易地使安全檢查在不應當成功時成功通過,從而降低了安全性。

委托
無論何時,如果您的代碼從可能調用它、但信任度較低的代碼那里取得委托權,請確保您不會讓信任度較低的代碼提升它的權限。如果您取得委托權并隨后使用它,那么,如果委托中或委托下面的代碼試圖執行受保護的操作,則創建委托的代碼將不會在調用堆棧中,并且不會測試它的權限。如果您的代碼和委托代碼具有比調用方更高的特權,這將使調用方能夠在不成為調用堆棧一部分的情況下改變調用路徑。

要解決該問題,可以限制調用方(例如,要求它具有某個權限)或對執行委托的權限加以限制(例如,通過使用 deny 或 permitonly 堆棧重寫)。

linkdemands 和包裝程序
在安全基礎結構中,已經加強了對鏈接請求的特殊保護措施,但它仍然是代碼中可能的漏洞來源。

如果完全受信任的代碼調用某個由 linkdemand 保護的屬性、事件或方法,那么,如果對調用方的 linkdemand 權限檢查獲得通過,則調用將成功。此外,如果完全受信任的代碼所公開的類使用了某個屬性的名稱,并使用反射來調用該屬性的 get 訪問器,那么,即使用戶代碼無權訪問該屬性,對 get 訪問器的調用也會成功。這是因為 linkdemand 將只檢查直接調用方,而直接調用方是完全受信任的代碼。其實,完全受信任的代碼在代表用戶代碼執行經授權的調用時,不需要確保用戶代碼有權進行該調用。如果您要包裝反射功能,請參閱 microsoft .net 框架的第 1 版安全更改一文,以獲得詳細信息。

為了防止因疏忽造成的安全漏洞(例如,上面描述的情況),運行時將對任何使用調用的操作(實例創建、方法調用、屬性設置或獲得)所進行的完整堆棧審核請求檢查擴展到由鏈接請求保護的方法、構造函數、屬性或事件。該保護會導致一些性能成本(單級 linkdemand 速度更快),并且會更改安全檢查的語義 — 即使單級檢查已通過,完整堆棧審核請求也可能會失敗。

程序集加載包裝程序
用來加載托管代碼的幾個方法(包括 assembly.load(byte[])),可使用調用方的證據加載程序集。具體來說,如果要包裝這些方法中的任意一個,安全系統可以使用您代碼被授予的權限(而不是調用方對包裝程序的權限)來加載程序集。顯然,您并不想允許信任度較低的代碼指使您代表它加載其所獲權限比調用方對包裝程序的權限更高的代碼。

擁有完全信任或信任度比潛在調用方(包括 internet 權限級調用方)高得多的任何代碼很容易通過這種方式降低安全性。如果您代碼包含的公共方法可以取得字節數組并將其傳遞給 assembly.load(byte[]),從而代表調用方創建程序集,則可能會破壞安全性。

該問題會發生在以下 api 元素上:

• system.appdomain.definedynamicassembly

• system.reflection.assembly.loadfrom

• system.reflection.assembly.load


異常處理
在運行任何 finally 語句之前,將運行堆棧上面的一個篩選表達式。在運行 finally 語句之后,將運行與該篩選器關聯的 catch 代碼塊。請考慮以下偽代碼:

void main() {
try {
sub();
} except (filter()) {
console.writeline("catch");
}
}
bool filter () {
console.writeline("filter");
return true;
}
void sub() {
try {
console.writeline("throw");
throw new exception();
} finally {
console.writeline("finally");
}
}

該代碼將打印以下內容:

throw
filter
finally
catch

篩選器將在 finally 語句之前運行,這樣,如果可以執行其他代碼,則造成狀態更改的任何操作都可以帶來安全問題。例如:

try {
alter_security_state();
// this means changing anything (state variables,
// switching unmanaged context, impersonation, and so on)
// that could be exploitable if malicious code ran before state is restored.
do_some_work();
}
finally {
restore_security_state();
// this simply restores the state change above.
}

該偽代碼允許篩選器備份堆棧以運行任意代碼。具有類似效果的其他操作示例是對另一個標識的臨時模擬,這樣會設置一個避開某個安全檢查的內部標志,并更改與線程關聯的區域性等等。

建議的解決方案是引入異常處理程序,將代碼的線程狀態更改與調用方的篩選器塊隔離開。但重要的是,要正確引入異常處理程序,否則將無法解決該問題。下面的 microsoft visual basic(r) 示例將切換 ui 區域性,但可以類似地公開任何線程狀態更改。

yourobject.yourmethod()
{
cultureinfo saveculture = thread.currentthread.currentuiculture;
try {
thread.currentthread.currentuiculture = new cultureinfo("de-de");
// do something that throws an exception.
}
finally {
thread.currentthread.currentuiculture = saveculture;
}
}

public class usercode
public shared sub main()
try
dim obj as yourobject = new yourobject
obj.yourmethod()
catch e as exception when filterfunc
console.writeline("an error occurred: '{0}'", e)
console.writeline("current culture: {0}",
thread.currentthread.currentuiculture)
end try
end sub

public function filterfunc as boolean
console.writeline("current culture: {0}", thread.currentthread.currentuiculture)
return true
end sub

end class

在此例中,正確的修復措施是在 try/catch 塊中包裝現有的 try/finally 塊。只將 catch-throw 子句引入現有的 try/finally 塊中將無法解決問題:

yourobject.yourmethod()
{
cultureinfo saveculture = thread.currentthread.currentuiculture;

try {
thread.currentthread.currentuiculture = new cultureinfo("de-de");
// do something that throws an exception.
}
catch { throw; }
finally {
thread.currentthread.currentuiculture = saveculture;
}
}

這不會解決問題,因為在 filterfunc 獲得控制權之前尚未運行 finally 語句。

以下代碼通過確保在根據調用方的異常篩選塊提供異常之前執行 finally 子句,來解決該問題。

yourobject.yourmethod()
{
cultureinfo saveculture = thread.currentthread.currentuiculture;
try {
try {
thread.currentthread.currentuiculture = new cultureinfo("de-de");
// do something that throws an exception.
}
finally {
thread.currentthread.currentuiculture = saveculture;
}
}
catch { throw; }
}


非托管代碼
某些庫代碼需要調用非托管代碼(例如,本機代碼 api,如 win32)。因為這意味著脫離托管代碼的安全邊界,所以應十分謹慎。如果您的代碼是安全中立的(請參閱本文的安全中立代碼部分),則您的代碼和任何調用它的代碼都必須擁有非托管代碼權限 (securitypermission.unmanagedcode)。

但是,要求您的調用方擁有這么大的權限通常是不合理的。在這種情況下,您的受信任代碼可以是“調解者”,類似于先前描述的托管包裝程序或庫代碼。如果基礎非托管代碼的功能是完全安全的,則可以直接公開它;否則,需要先進行適當的權限檢查 (demand)。

當您的代碼調用非托管代碼、但您不想讓調用方擁有該權限時,必須斷言您的權利。斷言會在您的幀處阻塞堆棧審核。您必須謹慎小心,不要在該過程中創建安全漏洞。通常,這意味著您必須請求適當的調用方權限,然后只使用非托管代碼來執行該權限允許的操作,但不能再執行其他操作。在某些情況下(例如,獲得一天中的時間),非托管代碼可以直接公開給調用方,而不需要進行任何安全檢查。在任何情況下,作出斷言的任何代碼都必須為安全性負責。

因為在本機代碼中提供代碼路徑的任何托管代碼都是惡意代碼的潛在目標,因此確定可以安全地使用什么非托管代碼以及必須如何使用它就需要非常小心。通常,所有非托管代碼都不應當直接公開給部分信任的調用方(請參閱下一部分)。在對可由部分信任代碼調用的庫中的非托管代碼使用情況的安全性進行評估時,有兩個主要注意事項:

• 功能。非托管 api 是否提供了安全的功能,即,不允許通過調用它來執行潛在危險的操作?代碼訪問安全性使用權限來實施對資源的訪問,所以請考慮 api 是否使用文件、用戶界面、線程,或者是否公開受保護的信息。如果是這樣,則包裝它的托管代碼必須請求所需的權限,然后才允許輸入它。此外,雖然不受權限保護,但安全性要求將內存訪問限制在嚴格的類型安全范圍內。

• 參數檢查。常見攻擊在試圖使被公開的非托管代碼 api 方法進行脫離規范的操作時,會將意外的參數傳遞給它們。緩沖溢出是此類攻擊的一個常見示例(使用范圍外的索引或偏移量值),另一個示例是可能利用基礎代碼中的錯誤的任何參數。因此,即使非托管代碼 api 在功能上對于部分受信任的調用方是安全的(在必要的請求之后),但托管代碼仍必須徹底地檢查參數的有效性,以使用托管代碼包裝程序層來確保惡意代碼不會發出非預期的調用。


使用 suppressunmanagedcodesecurity
斷言然后調用非托管代碼有性能方面因素。對每個這樣的調用來說,安全系統會自動請求非托管代碼權限,這會導致每次都進行堆棧審核。如果您斷言并直接調用非托管代碼,則堆棧審核沒有任何意義:它由斷言和非托管代碼調用組成。

可以將一個名為 suppressunmanagedcodesecurity 的自定義屬性應用于非托管代碼入口點,以禁用請求 securitypermission.unmanagedcode 的正常安全檢查。這樣做時必須始終保持謹慎,這是因為該操作會為在沒有運行時安全檢查的情況下進入非托管代碼創建一扇打開的門。應當注意到,即使應用了 suppressunmanagedcodesecurity,在 jit 時也會發生一次性安全檢查,以確保直接調用方擁有調用非托管代碼的權限。

如果您使用 suppressunmanagedcodesecurity 屬性,請檢查以下幾點:

• 使非托管代碼入口點在代碼外部不可訪問(例如,“internal”)。

• 調用非托管代碼的任何位置都是潛在的安全漏洞。確保您的代碼不是惡意代碼間接調用非托管代碼并避開安全檢查的門戶。在適當的情況下請求權限。

• 在創建到非托管代碼的危險路徑時,使用命名約定使它成為顯式的,下一部分將對此進行描述。


非托管代碼方法的命名約定
人們已經為命名非托管代碼方法建立了有用和高度推薦的約定。所有非托管代碼方法都可以劃分到三個類別中:safe、native 和 unsafe。這些關鍵字可用作在其中定義各種非托管代碼入口點的類名稱。在源代碼中,這些關鍵字應添加到類名稱中;例如,safe.gettimeofday、native.xyz 或 unsafe.dangerousapi。這些類別中的每一個都應向使用它們的開發人員發送強消息,如下表所述。

關鍵字 安全注意事項
safe
對于要調用的任何代碼(甚至是惡意代碼)完全無害??梢韵衿渌泄艽a一樣使用。示例:獲得一天中的時間。

native
安全中立;即,需要非托管代碼權限才能調用的非托管代碼。將檢查安全性,這將阻止未經授權的調用方。

unsafe
忽略安全且具有潛在危險性的非托管代碼入口點。開發人員在使用這種不安全代碼時應十分謹慎,同時應確保其他保護措施已就位,以避免安全漏洞。當該關鍵字重寫安全系統時,開發人員必須完全負責。



用戶輸入
用戶數據是指任何類型的輸入(來自 web 請求或 url 的數據、對 microsoft windows 窗體應用程序控件的輸入等等),它可以對代碼造成負面影響,因為這些數據通常被直接用作調用其他代碼的參數。這種情況與惡意代碼使用陌生參數調用您的代碼相似,應當采取相同的預防措施。用戶輸入實際上更難保證安全,這是因為沒有堆棧幀對出現的潛在不受信任數據進行跟蹤。

在需要查找的安全性錯誤中,這些錯誤是最細微和最難找到的,這是因為盡管它們可以存在于表面上與安全無關的代碼中,但它們卻是將有問題的數據傳遞給其他代碼的通路。要找到這些錯誤,請跟蹤任何類型的輸入數據,想象可能值的范圍,并考慮查看該數據的代碼是否可以處理所有這些情況。您可以通過范圍檢查和拒絕代碼無法處理的所有輸入來修復這些錯誤。

涉及用戶數據的某些常見錯誤包括:

&#8226; 在客戶端上,服務器響應中的所有用戶數據都會運行在服務器站點的上下文中。如果 web 服務器取得用戶數據并將它插入返回的 web 頁中,則它可能(例如)包括 <script> 標記,并且運行時好像來自服務器。

&#8226; 請記住,客戶端可以請求任何 url。

&#8226; 考慮那些復雜或無效的路徑:

&#8226; ../,非常長的路徑。

&#8226; 使用通配符 (*)。

&#8226; 令牌擴展 (%token%)。

&#8226; 具有特殊含義的陌生格式的路徑。

&#8226; 備用的 ntfs 流名稱;例如,filename::$data。

&#8226; 文件名的縮寫版本;例如,longfilename 和 longfi~1。


&#8226; eval(userdata) 可以執行任何操作。

&#8226; 對包含某些用戶數據的名稱的晚期綁定。

&#8226; 如果要處理 web 數據,您必須考慮許可的各種形式的轉義,包括:

&#8226; 十六進制轉義 (%nn)。

&#8226; unicode 轉義 (%nnn)。

&#8226; 超長的 utf-8 轉義 (%nn%nn)。

&#8226; 雙重轉義(%nn 變成 %mmnn,其中,%mm 是“%”的轉義)。


&#8226; 警惕可能具有多個規范格式的用戶名。例如在 microsoft windows 2000 中,通常可以使用 redmond/用戶名 格式或用戶名@redmond.microsoft.com 格式。



遠程處理注意事項
遠程處理允許您在應用程序域、進程或機器之間設置透明的調用。但是,代碼訪問安全性堆棧審核無法跨越進程或機器邊界(它只能應用在同一進程的應用程序域之間)。

可遠程處理的任何類(從 marshalbyrefobject 類派生的)都需要為安全性負責。要么只在呼叫代碼可以被隱式信任的安全封閉環境中使用代碼,要么對遠程調用進行設計,以便它們不會將受保護的代碼公開給可以被惡意使用的外部入口。

通常,您不應公開由聲明性的 linkdemand 和 inheritancedemand 安全檢查所保護的方法、屬性或事件。若使用遠程處理,則不會執行這些檢查。其他安全檢查(例如 demand、assert 等)在進程內的應用程序域之間工作,但不能跨進程或跨機器工作。


受保護的對象
某些對象自身可保持安全狀態。您不應將這些對象傳遞給不受信任的代碼,如果這樣,后者會獲得超越它自身權限的安全授權。

以創建一個 filestream 對象為例。在創建該對象時需要 fileiopermission,如果成功,將返回文件對象。但是,如果將該對象引用傳遞給沒有文件權限的代碼,則該對象將能夠讀/寫此特定文件。

對此類對象的最簡單防御措施是,通過公共 api 元素要求試圖獲得該對象引用的所有代碼都擁有相同的 fileiopermission。


序列化
使用序列化可以允許其他代碼看到或修改以其他方式不可訪問的對象實例數據。同樣,執行序列化的代碼也需要擁有特殊的權限:securitypermission.serializationformatter。在默認策略下,該權限不會授予從 internet 下載的代碼或 intranet 代碼;只有本地機器上的代碼才會被授予該權限。

正常情況下,對象實例的所有字段均被序列化,這意味著數據將以實例的序列化數據形式表示。這樣,代碼就可以解釋該格式以確定數據值是什么,這與成員的可訪問性無關。同樣,反序列化將從序列化表現形式中提取數據并直接設置對象狀態,這同樣也與可訪問性規則無關。

對于可以包含安全敏感數據的任何對象來說,應使該對象不可序列化(如果可能)。如果它必須是可序列化的,請嘗試使包含敏感數據的特定字段不可序列化。如果無法這樣做,則應知道該數據將被公開給有權進行序列化的任何代碼,并確保沒有惡意代碼可以獲得該權限。

iserializable 接口的原定用途是僅供序列化基礎結構使用。但是,如果未受保護,它也會潛在地泄漏敏感信息。如果通過實現 iserializable 來提供自定義序列化,則應確保采取以下預防措施:

&#8226; 應通過請求 securitypermission.serializationformatter 權限,或者確保方法輸出中未包含敏感信息,來顯式地確保 getobjectdata 的安全。例如:

[securitypermissionattribute(securityaction.demand,serializationformatter
=true)]
public override void getobjectdata(serializationinfo info,
streamingcontext context)


&#8226; 用于序列化的特殊構造函數還應執行徹底的輸入驗證,并且應當受保護或是私有的,以避免被惡意代碼濫用。它應當實施相同的安全檢查以及通過其他手段(通過某類工廠顯式創建或間接創建)獲得該類的實例所需的權限。



應用程序域跨域問題
要在托管宿主環境中隔離代碼,常用方法是:使用降低各種程序集權限級別的顯式策略,來創建多個子應用程序域。但是,在默認的應用程序域中,這些程序集的策略保持不變。如果其中一個子應用程序域可以強制默認應用程序域加載程序集,這就會失去代碼隔離的效果,并且這些程序集中的類型將能夠以更高的信任級別運行代碼。

一個應用程序域可以強制另一個應用程序域加載某個程序集,并通過調用駐留在其他應用程序域中的對象的代理來運行所包含的代碼。要獲得跨應用程序域代理,宿主該對象的應用程序域必須提供一個代理(通過一個方法調用參數或返回值),或者,如果該應用程序域剛剛創建,則創建者將擁有 appdomain 對象的代理。因此,要避免破壞代碼隔離,具有較高信任級別的應用程序域不應將對其域中的 marshalbyrefobject 對象的引用提供給具有較低信任級別的應用程序域。

通常,默認應用程序域在創建子應用程序域時會在每一個子域中包含一個控件對象??丶ο罂晒芾硇碌膽贸绦蛴?,并且有時會從默認應用程序域獲取命令,但實際上它不并知道如何直接與域聯系。有時,默認應用程序域將調用它的控件對象代理。但是,有時可能需要控件對象能夠回調到默認應用程序域。在這些情況下,默認應用程序域會將按引用封送的回調對象傳遞給控件對象的構造函數??丶ο筘撠煴Wo該代理。如果控件對象打算將代理放到公共類的公共靜態字段上,或者公開地公開該代理,那么這會為其他代碼回調到默認應用程序域創造一個危險的機制。因此,控件對象始終被隱式信任,以保持代理的私有性。


評估權限
基于證據的安全性的前提條件是,只有可信賴的代碼才會被授予高度信任(許多強大的權限),而惡意代碼只會被授予很少的信任或者不授予信任。.net 框架隨附的默認策略使用區域(由 microsoft internet explorer 確定)來授予權限。下面是默認策略的簡要說明:

&#8226; 本地機器區域(例如,c:/app.exe)接收完全信任。它假定用戶僅將他們信任的代碼放在機器上,并且大多數用戶不想以不同的信任區域來隔離他們的硬盤。該代碼基本上可以做任何事情,并且托管代碼安全性是無法實施的,所以沒有辦法防御該區域中的惡意代碼。

&#8226; internet 區域(例如,http://www.microsoft.com/)代碼被授予一組非常有限的權限,這些權限通常被認為可以安全地授予,甚至可以授予惡意代碼。一般情況下,不可信任該代碼,所以只能使用一組它無法用來執行有害操作的弱權限來安全地執行,這組權限是:

&#8226; webpermission。對它所在站點服務器的訪問權。

&#8226; filedialogpermission。只能訪問用戶明確選擇的文件。

&#8226; isolatedstoragefilepermission。由 web 站點隔離的永久存儲區。

&#8226; uipermission??梢栽诎?ui 的安全窗口中執行寫入操作。


&#8226; intranet 區域(例如,//unc/share)代碼被授予一組略強的 internet 權限,但仍然沒有強大的權限:

&#8226; fileiopermission。對它所在目錄中文件的只讀權限。

&#8226; webpermission。對它所在服務器的訪問權。

&#8226; dnspermission。允許 dns 名稱被解析為 ip 地址。

&#8226; filedialogpermission。只能訪問用戶明確選擇的文件。

&#8226; isolatedstoragefilepermission。限制更少的永久存儲區。

&#8226; uipermission。可以自由使用它自己的頂層窗口。


&#8226; 受限制的站點區域代碼只被授予最低的執行權限。


您應考慮自己的安全需要,并適當地修改安全策略。不可能只用一個安全配置來滿足所有需要:默認策略的原定用途是,在通常情況下不允許出現有危險的任何事情。

您的代碼將接收不同的權限,這取決于它是如何部署的。確保代碼將被授予能夠正確操作的足夠權限。在考慮確保代碼安全以抵御攻擊時,請考慮攻擊代碼的可能來源,以及它訪問您代碼的可能方式。

危險的權限
.net 框架為其提供權限的幾個受保護操作可以潛在地允許規避安全系統。這些危險的權限應當只授予可信賴的代碼,并且只能在需要時使用。如果向惡意代碼授予了這些權限,則通常無法抵御惡意代碼的攻擊。

危險的權限包括:

&#8226; securitypermission

&#8226; unmanagedcode。允許托管代碼調用非托管代碼,這通常是危險的。

&#8226; skipverification。如果不進行驗證,代碼可以做任何事情。

&#8226; controlevidence。虛構證據來欺騙安全策略。

&#8226; controlpolicy。修改安全策略的能力可以破壞安全性。

&#8226; serializationformatter。使用序列化可以規避可訪問性(前面已討論)。

&#8226; controlprincipal。設置當前用戶的能力可以欺騙基于角色的安全性。

&#8226; controlthread。由于安全狀態與線程相關聯,因此操縱線程是危險的。


&#8226; reflectionpermission

&#8226; memberaccess。挫敗可訪問性機制(可以使用私有成員)。



安全性和爭用條件
另一個關注區域涉及由爭用條件利用安全漏洞的可能性。這在幾種方式下很明顯。下面的子節概括了開發人員必須避免的某些主要缺陷。

dispose 方法中的爭用條件

如果某個類的 dispose 方法未同步化,則 dispose 內部的清除代碼可能會運行多次。請考慮使用以下代碼:

void dispose() {
if( _myobj != null ) {
cleanup(_myobj);
_myobj = null;
}
}

因為該 dispose 實現未同步化,所以cleanup 可能在被第一個線程調用之后又被第二個線程調用,之后才將_myobj 設置為null。這是否是需要關注的安全問題取決于在 cleanup 代碼運行時所發生的事情。未同步化的 dispose 實現的主要問題涉及對資源句柄(文件等)的使用。不正確的處理可能會導致使用錯誤的句柄,而這通常會導致安全漏洞。

構造函數中的爭用條件

在某些應用程序中,其他線程有可能在類成員的類構造函數完全運行之前訪問這些類成員。您應當檢查所有類構造函數,以確保在發生這種情況時不會出現安全問題,或者在需要時同步化線程。

緩存對象的爭用條件

如果類的其他部分未適當地進行同步化,則緩存安全信息或 asserts 的代碼也可能很容易受到爭用條件的侵害。請考慮使用以下代碼:

void somesecurefunction() {
if(somedemandpasses()) {
_fcallersok = true;
dootherwork();
_fcallersok = false();
}
}
void dootherwork() {
if( _fcallersok ) {
dosomethingtrusted();
}
else {
demandsomething();
dosomethingtrusted();
}
}

如果可以使用同一對象從另一個線程調用的 dootherwork 有其他路徑,則不受信任的調用方可以略過某個請求。

如果您的代碼緩存了安全信息,請確保檢查它是否有該漏洞。

完成器中的爭用條件

爭用條件的另一個來源是那些引用了它們在完成器中釋放的靜態或非托管資源的對象。如果多個對象共享在類的完成器中操作的資源,則這些對象必須同步化對該資源的所有訪問。


其他安全技術
本部分列出了其他一些可能適用于您代碼的安全技術,但這里無法充分討論它們。

on-the-fly 代碼生成
某些庫的操作方式是,生成代碼并運行它以執行調用方的某些操作?;締栴}是,代表信任度較低的代碼生成代碼,并以較高的信任度運行它。如果調用方可以影響代碼生成,那么問題將惡化,因此您必須確保只生成安全代碼。

您始終需要確切了解要生成什么代碼。這意味著,您必須嚴格控制從用戶那里得到的任何值,注意他們括起來的字符串(它們應當被轉義,這樣就無法包含意外的代碼元素)、標識符(應當檢查這些標識符,以驗證它們的有效性)或其他任何內容。標識符可能是危險的,因為您可以修改經過編譯的程序集,使它的標識符中包含陌生字符,而這些字符將有可能破壞程序集(盡管這通常不是安全漏洞)。

建議您使用 reflection.emit 生成代碼,這樣做通??梢詭椭苊夂芏噙@類問題。

編譯代碼時,請考慮惡意程序是否可以用某種方式修改它。在編譯器讀取磁盤上的源代碼之前或在您的代碼加載 dll 之前,惡意代碼是否有機會更改源代碼?如果有,則必須根據情況使用代碼訪問安全性或文件系統中的訪問控制列表來保護包含這些文件的目錄。

如果調用方可以用使編譯器出錯的方式影響被生成的代碼,則這里也可能存在安全漏洞。

以最低的可能權限設置運行生成的代碼(使用 permitonly 或 deny)。

基于角色的安全性:身份驗證和授權
除了確保代碼的安全以外,某些應用程序還需要實現將使用者范圍限制在某些用戶或用戶組的安全保護。基于角色的安全性(不在本文的討論范圍內)旨在處理這些需要。

處理機密
數據在內存中時可以相當有效地保密,但持久地保存它并保密則很難做到。第一版的 .net 框架沒有為保密處理提供托管代碼支持。如果您有專門技術,則加密庫可提供許多基本的必需功能。

加密和簽名
system.security.cryptography 命名空間包含一組豐富的加密算法。安全地實施加密需要某些專門技術,并且不應當以特殊方式嘗試。處理所涉及的數據和密鑰的每個方面都必須經過仔細設計和檢查。加密的細節不在本文的討論范圍內。有關詳細信息,請參閱標準的參考資料。

隨機數
應當使用 system.security.cryptography.randomnumbergenerator 來生成可能在需要真實隨機性的安全操作中使用的任意隨機數。使用虛擬隨機數生成器會產生能夠被利用的可預知性。

安裝問題
本部分描述了測試應用程序或組件的安裝以確保最佳安全做法并保護已安裝代碼的注意事項。建議在安裝托管代碼或非托管代碼時采用以下步驟,以確保安裝本身的安全。應對所有支持 ntfs 的平臺執行這些步驟:

&#8226; 將系統設置為兩個分區。

&#8226; 重新格式化第二個分區;不要更改根驅動器上的默認 acl。

&#8226; 安裝產品,將安裝目錄更改為第二個分區上的新目錄。


驗證以下各項:

&#8226; 是否有任何代碼作為服務執行,或者通常由具有全局可寫權的管理員級別的用戶運行?

&#8226; 代碼是否安裝在處于應用程序服務器模式下的終端服務器系統上?您的用戶現在是否可以寫入其他用戶可能運行的二進制代碼?

&#8226; 在非管理員可能寫入的系統區域或系統區域的子目錄中,是否有任何內容最終出現在這里?


此外,如果產品需要與 web 進行交互,則應當知道偶爾使用 web 服務器將允許用戶運行通常在 iusr_machine 帳戶的上下文中執行的命令。某些全局可寫的文件或配置項可以在這些條件下被來訪者帳戶利用,請驗證不存在這樣的文件或配置項。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 南皮县| 随州市| 交口县| 凉城县| 莎车县| 吉隆县| 辛集市| 彭山县| 蓬安县| 三原县| 淮安市| 滁州市| 卓资县| 宁远县| 邵阳市| 乐陵市| 普格县| 屏南县| 博客| 美姑县| 偏关县| 井陉县| 麻城市| 黄石市| 上林县| 光泽县| 沽源县| 平泉县| 土默特右旗| 廉江市| 石渠县| 临西县| 平泉县| 革吉县| 潢川县| 莱阳市| 连江县| 黎川县| 越西县| 堆龙德庆县| 昌邑市|