簡體   English   中英

在ASP.NET Core 2中動態加載程序集的安全性如何?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM