[英]How secure is it to dynamically load assemblies in ASP.NET Core 2?
目前,我正在使用ASP.NET Core 2.2進行Web項目研究,並且正在做一些研究,以使應用程序可擴展以適應將來的更改,而無需始終構建和部署新版本。 因此,我的想法是在Web應用程序中實現某種插件系統,並在應用程序仍在運行的情況下以“熱插拔”模式動態加載新功能。
我確實成功找到了ApplicationPart和ApplicationPartManager,從而可以從外部來源注入零件。
實際上,我沒有發現這種方法的安全性。 假設我的網絡應用帶有安裝程序,可以共享。 插件編程將是使用該應用程序的社區的一個開放選項。
動態加載應用程序部件有多安全? 是否存在注入作為插件提供的惡意代碼的風險? 是否可以以某種方式彌補這些風險?
編輯:似乎我沒有清楚地表達我的問題。
使用這種方法是否有可能使應用程序崩潰?
是否有可能以不再可用的方式破壞或更改數據庫?
是否可以注入將可能的敏感數據發送到第三方端點(例如身份信息)的插件代碼?
最后,是否有可能限制應用程序中的“訪問”插件代碼? 比如讓它只查詢與插件相關的數據庫表?
我同意Fildor,“安全”的定義尚待討論。 盡管您已經很好地編輯了一些問題的帖子,但這使我們有話要說。
首先,讓我們開始說,每當CLR加載包含ApplicationPart
的程序集時,它們都將加載到應用程序的默認AppDomain
中。 現在我們可以討論.NET Core是否包含AppDomain
。 這里的重點是要了解已加載的程序集都能夠相互通信。 因此,現在我們知道了這一點,並且主應用程序(webapp)將在某個時候調用您的自定義(插件)程序集內的一些代碼,讓我們看一下您的問題:
使用這種方法是否有可能使應用程序崩潰?
是。 可以說,每當插件加載時,就會執行以下代碼:
public void Run()
{
this.Run();
}
這將導致stackoverflow異常,該異常無法由用戶代碼處理,並且默認情況下,CLR將終止該進程,這意味着您的應用程序將崩潰。
是否有可能以不再可用的方式破壞或更改數據庫? 是否可以注入將可能的敏感數據發送到第三方端點(例如身份信息)的插件代碼?
我將這些問題歸為本質,您想知道的是:動態加載和調用的代碼的局限性和功能是什么?
答案是什么 。 他們可以訪問您的所有程序集,也可以訪問您的DatabaseManager
類型(例如)。 可以從插件中實例化此類型,然后使用它來操作數據庫。 除此之外,他們可以執行.NET框架提供的任何功能,如果他們想向網站發送內容,則可以輕松地實例化WebClient
並發出請求。
讓我們忘記ApplicationPart
功能,並想象我們創建了自己的插件系統,這是我的主要應用程序:
class Program
{
private static string secretUser = "SecretUser";
static void Main(string[] args)
{
Console.WriteLine($" > Hello {secretUser}");
LoadPlugins();
Console.WriteLine($" > System fully loaded! Hello again {secretUser}");
}
}
LoadPlugins
將搜索當前正在執行的程序集的目錄以發現動態鏈接的庫(DLL),並將嘗試使用某些數據協定來加載這些庫。 假設合同強制一個插件具有void Run
。 我可以在此方法中包含以下代碼來修改原始應用程序,例如,像這樣修改secretUser
變量:
public void Run()
{
var mainClass = System.AppDomain.CurrentDomain.GetAssemblies()
.Select(asm => asm.EntryPoint?.DeclaringType)
.Single(x => x?.Name == "Program");
var fieldDef = mainClass
.GetField("secretUser",
BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Static);
fieldDef.SetValue(mainClass, "HackerPlugin");
}
現在,無論何時運行代碼,首先SecuretUser
顯示SecuretUser
,但是無論何時加載惡意插件,應用程序都將顯示HackerPlugin
,因為該插件使用反射來訪問主應用程序實例並修改其內容。 這聽起來像是一個安全問題,但實際上,這是設計使然,它使.NET生態系統像今天一樣流行,因為它解決了許多其他我們需要處理的問題。
所以基本上 如果您擔心安全性,則不應使用ApplicationPart
方法,因為您的代碼將與插件共享(因此可以訪問)。
您想要的是將插件代碼與應用程序的代碼隔離。 這可以通過以下任一方法來實現: 使用多個AppDomain
(這仍可能導致進程終止)或使用多個進程並使這些進程相互通信。 進程是獨立的,不能(默認)互相讀取其他內存區域。
請注意, ApplicationPart
會為您做很多事情,例如發現並挑戰(外部)依賴項的加載,如果您決定構建自定義解決方案,則還需要自己構建它-這並不意味着您可以查看.NET存儲庫,並使用其解決方案作為參考。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.