出于安全原因,最好在执行前检查代码的完整性,避免攻击者篡改软件。所以,我的问题是
如何在 Linux 下签署可执行代码并只运行受信任的软件?
我读过 van Doom等人的作品。,为 Linux 设计和实现签名的可执行文件,以及 Safford & Zohar 的 IBM 的TLC(受信任的 Linux 客户端)。TLC 使用 TPM 控制器,这很好,但这篇论文是 2005 年的,我无法找到当前的替代品。
你知道其他选择吗?
更新:关于其他操作系统?开放式Solaris?BSD家族?
出于安全原因,最好在执行前检查代码的完整性,避免攻击者篡改软件。所以,我的问题是
如何在 Linux 下签署可执行代码并只运行受信任的软件?
我读过 van Doom等人的作品。,为 Linux 设计和实现签名的可执行文件,以及 Safford & Zohar 的 IBM 的TLC(受信任的 Linux 客户端)。TLC 使用 TPM 控制器,这很好,但这篇论文是 2005 年的,我无法找到当前的替代品。
你知道其他选择吗?
更新:关于其他操作系统?开放式Solaris?BSD家族?
我意识到这是一个古老的问题,但我现在才发现它。
不久前,我为 Linux 内核(大约 2.4.3 版)编写了签名的可执行文件支持,并准备好了整个工具链来对可执行文件进行签名,execve(2)
及时检查签名,缓存签名验证信息(在文件被删除时清除验证)打开用于写入或以其他方式修改),将签名嵌入到任意 ELF 程序等。它确实在每个程序的第一次执行时引入了一些性能损失(因为内核必须加载整个文件,而不仅仅是请求页面需要的页面)但是一旦系统处于稳定状态,它就会运行良好。
但我们决定停止追求它,因为它面临几个太大的问题,无法证明其复杂性是合理的:
我们还没有建立对签名库的支持。签名库还需要修改ld.so
加载器和dlopen(3)
机制。这并非不可能,但确实使接口复杂化:我们应该让加载程序要求内核验证签名还是应该完全在用户空间中完成计算?strace(2)
如果这部分验证是在用户空间中完成的,如何防止d 进程?我们会被迫strace(2)
完全禁止这样的系统吗?
对于提供自己的 loader 的程序,我们会怎么做?
许多程序是用不编译为 ELF 对象的语言编写的。我们需要对, , , , ,等提供特定于语言的修改,以便每个解释器也能够验证签名。由于这些程序中的大多数都是自由格式的纯文本,它们缺乏使将数字签名嵌入 ELF 对象文件变得如此容易的结构。签名将存储在哪里?在脚本中?在扩展属性中?在外部签名数据库中?bash
perl
python
java
awk
sed
许多口译员对他们允许的内容持开放态度。可以完全自行使用andbash(1)
与远程系统通信,并且很容易被诱骗执行攻击者需要执行的任何操作。无论是否签名,一旦他们受到黑客的控制,您就无法信任他们。echo
/dev/tcp
支持已签名可执行文件的主要动力来自替换系统提供/bin/ps
的 、/bin/ps
、/bin/kill
等的 rootkit。是的,还有其他有用的理由来签署可执行文件。然而,随着时间的推移,rootkit 变得更加令人印象深刻,许多人依靠内核黑客来向管理员隐藏他们的活动。一旦内核被黑,整个游戏就结束了。由于 rootkit 的复杂性,我们希望阻止使用的工具在黑客社区中已经失宠。
内核的模块加载接口是完全开放的。一旦进程拥有root
特权,就很容易注入内核模块而无需任何检查。我们也可以为内核模块编写另一个验证器,但内核围绕模块的基础设施非常原始。
GNU/Linux/FOSS 模型实际上鼓励篡改——某种程度上。用户和发行版制造商必须可以自由修改(篡改)软件以满足他们的需求。即使只是重新编译软件(不更改任何源代码)进行定制也是经常做的事情,但会破坏二进制代码签名。因此,二进制代码签名模型并不是特别适合 GNU/Linux/FOSS。
相反,这种软件更多地依赖于生成签名和/或源包的安全哈希。结合可靠和受信任的包分发模型,这可以像二进制代码签名一样安全(如果不是更安全的话,相对于源代码的透明度)。
DigSig内核模块实现对由名为bsign
. 但是,自 Linux 内核 2.6.21 版以来,还没有任何工作。
看看这个: http: //linux-ima.sourceforge.net/
它还没有签名,但它仍然可以验证。
我可以从 Solaris 10 和 11 操作系统的角度回答这个问题,所有二进制文件都已签名。要验证签名,请使用“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。
看看美杜莎 DS9。我很久(很久)以前玩过它,但如果我没记错的话,您可以注册特定的二进制文件,并且在内核级别不允许进行任何修改。当然,可以通过对机器的本地访问来覆盖它,但这并不容易。有一个名为 constable 的智能守护程序,它检查机器上发生的一切,如果发生异常情况,它就会开始尖叫。
我从未尝试过,但请看一下: http: //blog.codenoise.com/signelf-digitally-signing-elf-binaries。该解决方案无需内核支持即可工作,并且看起来已经准备就绪。
可以在http://sourceforge.net/projects/signelf/找到签名者的代码
它并没有解决“在 linux 上只运行受信任的代码”的问题,但它确实通过让程序检测自己可能的篡改/损坏来部分解决问题
我喜欢将安全视为一条链条。链条中较弱的环节可能会危及整个系统。所以整个事情变成了“防止未经授权的用户获得root密码”。
正如@DanMoulding 所建议的,软件的来源也很重要,未来可能官方的操作系统应用程序商店将成为标准。想想 Play Store、Apple 或 Microsoft 商店。
我认为隐蔽恶意代码的安装和分发是更隐蔽的问题。毕竟,为了加载坏代码,它必须首先安装在系统的某个地方。当然,更多的安全层通常会更好。问题是:值得付出代价吗?
在我看来,答案是“视情况而定”。您可以通过采用@sleblanc 建议的一组安全策略来降低风险。您可以加密您的文件系统 ( https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup ),对二进制文件使用只读文件系统或使用一种机制来签署和验证二进制文件。
但是,无论您使用何种机制,一旦攻击者获得了 root 访问权限,您将无能为力。签名验证工具可以被篡改的版本替换,或者只是禁用,一旦机器受到攻击,这些工具是在用户空间还是内核空间运行并不重要(尽管后者当然会更安全)。
因此,如果 Linux 内核可以在 root 用户和操作系统之间嵌入签名验证模块和另一个安全层,那就太好了。
例如,这是最近的macOS版本采用的方法。有些文件甚至不能被 root 帐户修改(有时是读取),并且对策略和内核模块也有限制(例如,只有签名或授权的 kext 可以加载到系统上)。Windows采用了或多或少与AppLocker相同的方法。
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 以删除/绕过它......这真正有用的只是检测损坏的文件,而不是试图阻止人们绕过你。
我同意围绕 Linux、GNU 等人的哲学。围绕修补。另一方面,我也相信一些系统值得保护免受软件篡改等漏洞的影响,这些漏洞会破坏系统用户的隐私和完整性。
内核实现跟不上内核本身的快速开发周期。我建议改为使用用户空间工具实现一种可执行文件签名验证形式。将可执行文件放在存档或文件系统映像中,并使用私钥对映像进行签名;如果该私钥保留在您的开发机器上(私有),那么当您的服务器被黑客入侵时,攻击者仍然无法在不欺骗系统安装未签名图像的情况下签署他们自己的图像并注入他们的代码。它沿着链进一步延伸:
把每件事都做好是一项艰苦的工作。通过在另一种方法下设计系统来解决这一切要简单得多: