设计(用户模式)沙箱是一项艰巨的挑战,需要深入了解底层操作系统(或者换句话说:使用现有解决方案可能比重新发明轮子更好)。
.NET 中现有的隔离级别(例如 AppDomains)不适合您的场景。您需要从较低的级别开始,并且可以考虑以下方法之一来运行应用程序并限制对主机的访问。
Windows完整性机制
运行限制访问系统的程序的一种简单方法是利用 Windows 完整性机制,这是方法之一,例如:保护模式下的 Internet Explorer 或 Microsoft Office 是隔离的。此机制并非旨在提供完全隔离的沙箱,但在基本情况下可能就足够了。文档states https://msdn.microsoft.com/en-us/library/bb625957.aspx:
Windows 完整性机制并非旨在用作应用程序沙箱。但是,它可以是应用程序开发人员用来限制不太可信的应用程序的行为的安全工具之一。
完整性机制主要限制写入权限,但它不会禁止或阻止任何更高级别的数据读取。
以最低完整性级别启动进程就像更改可执行映像的 ACL 一样简单here https://msdn.microsoft.com/en-us/library/bb625960.aspx然后启动程序:
-
设置完整性级别:
icacls myprogram.exe /setintegritylevel Low
-
启动现在以最低完整性级别运行的程序(可以使用 Process Explorer 等工具看到):
myprogram.exe
如链接文章中所述,您还可以通过编程方式启动完整性较低的新进程(不使用 .NET,而是通过 P/Invoking 到 Windows API)。本文还给出了如何设计低级程序才能工作的提示(例如哪些位置可写等)。
容器
Docker等容器解决方案通过添加一些操作系统级别的屏障来提供更高级别的隔离,但内核等一些资源仍然是共享的(从而带来一定的恶意代码逃逸沙箱的风险)。
虚拟化
虚拟化提供了更高级别的隔离:整个系统在隔离的虚拟机中运行,只能通过专用接口(例如开放的 TCP 端口)进行访问。虚拟化方法提供了最高的安全性,并且在大多数情况下,逃离虚拟机被认为是非常困难的(尽管虚拟机管理程序中可能存在漏洞,并且可能会使用某些相当复杂的攻击来利用漏洞)。
与容器的区别在于,您从一个几乎完全隔离的系统开始,在该系统中仅向主机系统开放特定的专用通信通道。相比之下,使用容器,您可以共享相同的系统,并根据需要建立屏障来隔离来宾。这样做的缺点是更容易忘记一些事情。
信息安全 Stackexchange 网站上的一篇文章进一步讨论了该问题:Docker 作为不受信任代码的沙箱 https://security.stackexchange.com/questions/107850/docker-as-a-sandbox-for-untrusted-code