出于安全原因,最好在执行之前检查代码的完整性,以及攻击者避免篡改软件。所以,我的问题是
如何在Linux下签署可执行代码并仅运行可信软件?
我已经阅读了van Doom 等人的工作, Linux的签名可执行文件的设计和实现以及IBM的TLC(受信任的Linux客户端) )由Safford&琐。 TLC使用TPM控制器,这很好,但该文件来自2005年,我无法找到当前的替代品。
你知道其他选择吗?
更新:关于其他操作系统? OpenSolaris的? BSD家庭?
答案 0 :(得分:56)
我意识到这是一个古老的问题,但我现在才发现它。
我前段时间为Linux内核(版本2.4.3)编写了签名的可执行文件支持,并使用整个工具链来签署可执行文件,在execve(2)
时检查签名,缓存签名验证信息(当文件被打开以进行写入或以其他方式修改时清除验证),将签名嵌入到任意ELF程序等中。它确实在每个程序的第一次执行时引入了一些性能损失(因为内核必须加载到整个文件,而不仅仅是需求页面所需的页面)但是一旦系统处于稳定状态,它就能很好地工作。
但是我们决定停止追求它,因为它面临着一些太大而无法证明复杂性的问题:
我们尚未建立对签名库的支持。签名库还需要修改ld.so
加载器和dlopen(3)
机制。这并非不可能,但确实使接口复杂化:我们是否应该让加载程序要求内核验证签名,还是应该完全在用户空间中完成计算?如果验证的这部分是在用户空间中完成的,那么如何防止strace(2)
d进程?我们会被迫完全禁止strace(2)
这样的系统吗?
很多程序都是用不能编译成ELF对象的语言编写的。我们需要向bash
,perl
,python
,java
,awk
,{{1}提供语言特定的修改等等,每个解释器都能够 验证签名。由于大多数这些程序都是自由格式的纯文本,因此缺少将数字签名嵌入ELF目标文件的结构。签名将存储在哪里?在脚本中?在扩展属性?在签名的外部数据库中?
许多口译人员大开关于他们允许的内容; sed
可以使用bash(1)
和echo
完全在自己的上与远程系统进行通信,并且很容易被诱骗执行攻击者需要执行的操作。签名与否,一旦受到黑客的控制,你就无法信任他们。
签名可执行文件支持的主要动力来自rootkit替换系统提供的/dev/tcp
,/bin/ps
,/bin/ps
等。是的,签署可执行文件还有其他有用的理由。但是,随着时间的推移,rootkit会更加令人印象深刻,许多人依靠内核黑客来隐藏他们的管理员活动。一旦内核被黑了,整个游戏就结束了。由于rootkit的复杂性,我们希望防止使用的工具在黑客社区中失宠。
内核的模块加载界面是开放的。一旦进程具有/bin/kill
权限,就可以很容易地注入内核模块而无需进行任何检查。我们本可以为内核模块编写另一个验证程序,但内核的模块基础结构非常原始。
答案 1 :(得分:11)
GNU / Linux / FOSS模型实际上鼓励篡改 - 一种。用户和发行商必须可以自由地修改(篡改)软件以满足他们的需求。即使只是重新编译软件(不改变任何源代码)进行自定义也是经常做的事情,但会破坏二进制代码签名。因此,二进制代码签名模型并不特别适合GNU / Linux / FOSS。
相反,这种软件更依赖于生成源包的签名和/或安全哈希。结合可靠且值得信赖的包分发模型,这可以像二进制代码签名一样安全(如果不是更多,相对于源代码的透明性)。
答案 2 :(得分:6)
DigSig内核模块实现了对名为bsign
的工具签名的二进制文件的验证。但是,自Linux内核版本2.6.21以来,没有任何工作。
答案 3 :(得分:5)
看看这个:http://linux-ima.sourceforge.net/
它尚未签名,但仍可启用验证。
答案 4 :(得分:3)
我可以回答Solaris 10& S中的问题。 11 OS透视图,所有二进制文件都已签名。验证签名使用' elfsign' ...
$ elfsign verify -v /usr/bin/bash
elfsign: verification of /usr/bin/bash passed.
format: rsa_sha1.
signer: O=Oracle Corporation, OU=Corporate Object Signing, OU=Solaris Signed Execution, CN=Solaris 11.
signed on: Fri Oct 04 17:06:13 2013.
Oracle最近也为Solaris 11添加了经过验证的启动过程,有关详细信息,请参阅 - Solaris Verified Boot Introduction
OpenSolaris代码有一些生产等级的分叉,有三个值得研究的是Illumos,SmartOS和OmniOS。
答案 5 :(得分:2)
看看Medusa DS9。我玩了很久( long ),但如果我没记错,你可以注册特定的二进制文件,并且在内核级别不允许任何修改。当然,它可以通过本地访问机器来覆盖,但这并不容易。有一个名为constable的智能守护进程,可以检查机器上发生的一切,如果出现异常情况,就会开始尖叫。
答案 6 :(得分:2)
我从未尝试过,但请看一下:http://blog.codenoise.com/signelf-digitally-signing-elf-binaries。该解决方案无需内核支持即可运行,看起来已准备就绪。
签名者的代码可以在http://sourceforge.net/projects/signelf/
找到它没有解决“在Linux上运行仅受信任的代码”的问题,但它确实通过为程序检测自身可能的篡改/损坏来解决问题
答案 7 :(得分:1)
http://en.wikipedia.org/wiki/PKCS
使用它的PKCS7(S / MIME)标志。生成您自己的证书/私钥对,对证书进行自签名,然后使用PKCS7使用私钥和证书对您的文件进行签名。它将附加证书,然后它可以在运行时使用openssl命令(man smime或只是做openssl帮助)检查自己。这是防篡改的,因为即使公钥在您提供的文件中,该公钥的S / MIME签名也只能使用您不会分发的私钥生成。因此,如果文件由您的证书签名,则必须由拥有私钥的人签名,因为您没有将私钥提供给任何人,所以它必须来自您。
以下是如何制作自签名证书。
http://www.akadia.com/services/ssh_test_certificate.html
你必须说服openssl信任你的证书作为权限的根(-CAfile),然后用它作为根检查它,并检查文件上的证书是你的(散列证书)并检查哈希。请注意,虽然没有记录,但openssl的退出状态反映了您在执行smime验证时检查的符号的有效性。如果匹配则为0,如果不匹配则为非零。
请注意,所有这些都不安全,因为如果检查在您的代码中,他们只需删除支票,如果他们想要打败你。唯一安全的方法是在操作系统中安装检查程序并检查二进制文件,如果没有签名则拒绝运行它。但是因为操作系统中没有检查器,所以无论如何都可以修改linux以删除/绕过它...这真的很有用,只是检测损坏的文件而不是试图阻止人们绕过你。
答案 8 :(得分:0)
我同意围绕Linux的哲学,GNU等。围绕修补。另一方面,我也认为某些系统值得保护,以防止诸如软件篡改之类的漏洞,这些漏洞可能破坏系统用户的隐私和完整性。
内核实现无法跟上内核本身的快速开发周期。我建议改为使用用户空间工具实现一种形式的可执行文件签名验证。将可执行文件放置在档案或文件系统映像中,并使用私钥对该映像进行签名;如果该私钥保留在您的开发计算机上(私有),那么当您的服务器被黑客入侵时,攻击者仍然无法签名自己的映像并注入其代码,而不会欺骗系统来安装未签名的映像。它沿着链进一步延伸:
使所有事情都做对是一项艰苦的努力。通过使用另一种方法来设计系统,可以更轻松地解决所有问题:
答案 9 :(得分:0)
我喜欢将安全视为一条链。链条较弱的环节可能会损害整个系统。因此,整个过程变成了“ 防止未经授权的用户获取根密码”。
正如@DanMoulding所建议的那样,软件的来源也很重要,将来将来可能会成为官方的OS应用程序商店。考虑一下Play商店,Apple或Microsoft商店。
我认为秘密的恶意代码的安装和分发是 更阴险的问题。毕竟,为了加载错误的代码, 必须首先安装在系统上的某个位置。的更多层 安全性通常会更好。问题是:是否值得 费用?
我认为答案是“取决于”。 您可以采用@sleblanc建议的一组安全策略来降低风险。您可以加密文件系统(https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup),对二进制文件使用只读文件系统,或使用一种机制来签名和验证二进制文件。
但是,无论使用哪种机制,一旦攻击者获得了根访问权限,您将无能为力。签名验证工具可以用篡改版本替换,也可以禁用,并且一旦计算机受到威胁,该工具是否在用户空间或内核空间中运行都没有关系(尽管后者当然会更安全) )。
因此,如果Linux内核可以在根用户和操作系统之间嵌入签名验证模块和另一个安全层,那就太好了。
例如,这是在最新的 macOS 版本中采用的方法。即使使用root帐户也无法修改(有时无法读取)某些文件,并且策略和内核模块也受到限制(例如,系统上只能加载经过签名或授权的kext)。 Windows 与 AppLocker 大致采用相同的方法。