我一直在考虑一个场景,让用户(可以是任何人,也可能是恶意的)提交在Linux PC上运行的代码(让我们称之为基准节点)。目标是为单线程例程创建一种自动化的基准测试环境。假设一个网站向代理发布一些代码。这个代理将此代码交给基准节点,而基准节点只有到代理的以太网连接,而不是互联网本身。
如果让任何用户发布的C/asm代码在基准节点上运行,将面临什么安全挑战?做出以下假设:
- 程序以无特权用户身份运行
- 代理将有机会杀死基准节点上的进程(以无限循环为例)
- 代理能够重新启动基准节点(如果它回复…)
那么,在实践中,这个用户空间程序是否有可能使操作系统崩溃,或者使机器对代理不可用?有了汇编,程序员基本上可以随心所欲(例如操作堆栈指针),我想知道Linux在这方面的限制性/健壮性有多强。我还知道进程请求与其他进程共享内存区域的可能性(shm),这可能也在这里发挥作用?
欢迎任何关于这个主题的文献或文章。
沙盒解决方案可能也很有趣,但重要的是,CPU必须在基准测试期间执行100%的能力(至少在运行基准测试的核心上)。
只是我脑海中的一个快速列表。从本质上讲,如果你至少有一点不信任用户,你就陷入了深深的麻烦:
- 文件系统操作:删除或覆盖进程作为用户运行的文件
- 窥探系统上发现的各种数据(文件,有时是同一用户的网络流量)
- 终止用户的其他进程
- 消耗内存,直到OOM Killer开始杀死随机进程,或者(如果启用了交换)直到机器减速到爬行
- 生成大量I/O以降低系统速度
- 随意执行漏洞攻击(你几乎可以肯定在某个地方有一些未修补的特权升级漏洞)
- 利用用户能够运行的任何软件中的漏洞
- 在您的机器上托管DDoS网络或儿童色情文件服务器
- 使用您的机器作为代理启动对CIA和FBI服务器的攻击
- 天空是极限
听起来不是个好主意。
那么,在实践中,这个用户空间程序是否有可能使操作系统崩溃,或者使机器对代理不可用?
是的,诸如生成过多的进程、分配过多的内存(导致交换文件使用)或排队等待大量磁盘I/O之类的技术会使计算机没有响应,从而使您的主管进程无法及时运行。
如果您的监控程序代码最终被交换到磁盘,那么即使它具有高优先级,它也不会运行,直到磁盘可用,这可能会由于寻道时间而导致很长的延迟。
Linux确实有ulimit
,它可以防止其中的一些,请参阅限制Linux中用户可用的内存和cpu。恶意网络活动也可以被阻止。您还可以禁用程序到tmpfs
装载的交换和chroot
。但一些恶作剧仍然是可能的。
那么,在实践中,这个用户空间程序是否有可能使操作系统崩溃,或者使机器对代理不可用?
理论上,你应该很难让操作系统崩溃。然而,有很多错误报告说,这在实践中比我们希望的更有可能。
另一方面,如果没有特别的预防措施,就很容易实现拒绝服务。想象一下,一个用户程序什么也没做,只是用数据包淹没代理;单凭这一点,如果不能彻底拒绝服务,可能会让事情进展得令人尴尬。
有了汇编,程序员基本上可以随心所欲(例如操作堆栈指针),我想知道Linux在这方面的限制性/健壮性有多强。
然而,我们比这要好得多。如果权限提升所需的只是"堆栈指针混乱",那么作为字段的安全性将完全是一个笑话。内核旨在被编写,这样任何程序,无论怎样,都不会导致内核崩溃。如前所述,它并不完美。
这个故事的寓意是,你真的不想在你关心的计算机上运行不受信任的代码。这里的常见答案是一个检查点虚拟机:启动一个虚拟机,在虚拟机上运行不受信任的代码,然后在完成或超时后将虚拟机吹走。那样的话,持续的破坏是不可能的。就其他滥用而言,你的代理会阻止他们托管破旧的互联网服务,这很好。根据您的虚拟机情况,可能有一些好的工具可以限制CPU消耗和网络使用,这将有助于消除其他拒绝服务的可能性。
您提到需要CPU以满负荷运行。硬件虚拟化非常好,性能应该合理地反映出它在真实系统上的表现。
顺便说一句,上面没有任何内容是Linux特有的;所有可信的通用操作系统都应该如此。
编辑:如果你真的坚持直接在硬件上运行,那么:
- 从只读设备(livecd或写阻止的硬盘驱动器)启动
- 系统中没有可写介质
- 添加一个熄灯服务器,在拒绝服务的情况下,可以根据代理的请求强制重置机器;商业解决方案已经存在
这本质上为您提供了VM解决方案的功能,但在硬件上。
如果代码在正确配置的机器上的有限帐户下运行,它应该可以抵御许多基本类型的攻击(意外或恶意)。
程序员可以使用汇编这一事实无关紧要——攻击可以用许多不同的语言编码——编译或其他方式。
主要问题是未知的安全问题或0day漏洞。允许任何未经授权的程序运行都是有风险的,如果有人设法利用允许权限提升的问题,你就完蛋了。
通常建议使用沙盒,因为它们既限制了应用程序的功能,又(如果设计正确)将流氓行为造成的损害降至最低。
程序组可能会施加内存压力,导致机器无响应(尤其是当开始交换到磁盘时)。示例代码:perl -e '$_.="x"x1000000 while fork'