Linux 下签名的可执行文件

发布于 2024-08-10 19:06:06 字数 458 浏览 6 评论 0原文

出于安全原因,最好在执行之前检查代码的完整性,避免攻击者篡改软件。所以,我的问题是

如何在 Linux 下签署可执行代码并仅运行受信任的软件?

我已经阅读了 van Doom 等人的作品。设计和实现Linux 的签名可执行文件,以及 IBM 的 Safford & TLC(受信任的 Linux 客户端)佐哈尔。 TLC 使用 TPM 控制器,这很好,但该论文是 2005 年的,我无法找到当前的替代方案。

您知道其他选择吗?

更新:其他操作系统呢?开放Solaris? BSD家族?

For security reasons, it is desirable to check the integrity of code before execution, avoiding tampered software by an attacker. So, my question is

How to sign executable code and run only trusted software under Linux?

I have read the work of van Doom et al., Design and implementation of signed executables for Linux, and the IBM's TLC (Trusted Linux Client) by Safford & Zohar. TLC uses TPM controller, what is nice, but the paper is from 2005 and I was unable to find current alternatives.

Do you know another options?

UPDATE: And about other OS's? OpenSolaris? BSD family?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

世态炎凉 2024-08-17 19:06:07

我同意围绕 Linux、GNU 等的哲学。围绕着修修补补。另一方面,我也认为某些系统应该受到保护,防止软件篡改等漏洞,这些漏洞可能会破坏系统用户的隐私和完整性。

内核实现无法跟上内核本身的快速开发周期。我建议使用用户空间工具来实现某种形式的可执行文件签名验证。将可执行文件放入存档或文件系统映像中,并使用私钥对映像进行签名;如果该私钥保留在您的开发计算机上(私有),那么当您的服务器被黑客攻击时,攻击者仍然无法在不欺骗系统挂载未签名图像的情况下签署自己的图像并注入他们的代码。它沿着链条进一步延伸:

  • 将您的服务包含到运行时安装的只读映像中;
  • 让机器运行签名的只读文件系统;
  • 在您的计算机上实施安全启动,运行强制启动介质完整性的启动加载程序;
  • 相信您组织中的人员不会篡改您的机器。

让一切都正确是一项艰巨的努力。通过采用另一种方法设计系统来解决所有问题要简单得多:

  • 将用户与系统隔离。不要引入让用户在您的系统上执行命令的方法。避免从依赖用户提供数据的程序内部进行剔除。
  • 使用配置管理设计您的部署过程,并确保您的部署是“可重复的”,这意味着当您多次部署它们时,它们会产生相同的功能结果。这使您可以从轨道上对您怀疑已受到损害的机器进行“核攻击”。
  • 将您的机器视为受到损害的机器:定期运行审核以验证系统的完整性。将数据保存在单独的映像上并定期重新部署系统。对图像进行签名并让系统拒绝未签名的图像。
  • 使用证书:支持“证书固定”方法。请为您的应用程序部署根证书(这将自动拒绝未经您的组织认证的签名),但至少让系统管理当前图像的指纹,并在指纹发生更改时通知管理员。尽管可以使用密钥链来实现所有这些,但基于证书的身份验证是专为这种应用程序而设计的。

I agree that the philosophy surrounding Linux, GNU et al. revolves around tinkering. On the other hand, I also believe that some systems deserve protection against vulnerabilities such as software tampering, which can undermine the privacy and integrity of a system's users.

Kernel implementations cannot keep up with the rapid development cycle of the kernel itself. I recommend instead to implement a form of executable file signature verification using userspace tools. Place executables in an archive or filesystem image and sign the image using a private key; if that private key stays on your development machines (private), when your server gets hacked, attackers still have no way to sign their own images and inject their code without tricking the system to mount unsigned images. It extends further along the chain:

  • have your services contained into runtime-mounted read-only images;
  • have the machine run off of a signed, read-only filesystem;
  • implement secure boot on your machines, running a bootloader that enforces the integrity of the boot media;
  • trust that the people in your organization will not tamper with your machines.

Getting everything right is a hard endeavor. It is much simpler to work around it all by designing your system under another approach:

  • quarantine users from the system. Do not introduce means for users to execute commands on your system. Avoid shelling out from inside the programs that rely on user-fed data.
  • design your deployment procedures using configuration management and ensure that your deployments are "repeatable", meaning that they lead to the same functional result when you deploy them several times. This allows you to "nuke from orbit" machines that you suspect have been compromised.
  • treat your machines as if they were compromised: regularly run audits to verify the integrity of your systems. Save your data on separate images and redeploy systems regularly. Sign images and have systems reject unsigned images.
  • use certificates: favor a "certificate pinning" approach. Do deploy a root certificate for your applications (which will provide automatic rejection of signatures that have not been certified by your organization) but at the very least have the system manage fingerprints of current images and notify administrators when fingerprints have changed. Although it is possible to implement all this using chains of keys, certificate-based authentication has been designed for this exact application.
无法言说的痛 2024-08-17 19:06:06

我意识到这是一个古老的问题,但我现在才发现它。

不久前,我为 Linux 内核(大约版本 2.4.3)编写了签名的可执行文件支持,并准备好了整个工具链来签名可执行文件,在 execve(2) 时间检查签名,缓存签名验证信息(在打开文件进行写入或以其他方式修改时清除验证),将签名嵌入到任意 ELF 程序中等。它确实在每个程序的第一次执行时引入了一些性能损失(因为内核必须加载整个文件,而不仅仅是按需分页所需的页面),但是一旦系统处于稳定状态,它就会运行良好。

但我们决定停止追求它,因为它面临着几个太大的问题,无法证明其复杂性:

  • 我们尚未构建对签名库的支持。签名库还需要修改 ld.so 加载器和 dlopen(3) 机制。这并非不可能,但确实使接口变得复杂:我们应该让加载程序要求内核验证签名还是应该完全在用户空间中完成计算?如果这部分验证是在用户空间中完成的,那么如何防止 strace(2)d 进程呢?我们是否会被迫在这样的系统上完全禁止 strace(2)

    对于提供自己的加载程序的程序我们该怎么办

  • 许多程序都是用不能编译为 ELF 对象的语言编写的。我们需要对 bashperlpythonjava 提供特定于语言的修改code>、awksed 等,以便每个解释器都能够验证签名。由于大多数这些程序都是自由格式的纯文本,因此它们缺乏将数字签名嵌入到 ELF 目标文件中如此简单的结构。签名将存储在哪里?在脚本中?在扩展属性中?在外部签名数据库中?

  • 许多口译员对于他们所允许的内容持开放态度。 bash(1) 可以使用 echo/dev/tcp 完全独立地与远程系统进行通信,并且很容易被诱骗执行攻击者需要做的任何事情。无论是否签名,一旦它们受到黑客的控制,您就无法信任它们。

  • 签名可执行文件支持的主要动机来自 Rootkit 替换系统提供的 /bin/ps/bin/ps/bin/kill< /代码>,等等。是的,签署可执行文件还有其他有用的理由。然而,随着时间的推移,rootkit 变得更加令人印象深刻,许多 rootkit 依靠内核黑客来向管理员隐藏其活动。一旦内核被破解,整个游戏就结束了。由于 Rootkit 的复杂性,我们希望防止使用的工具在黑客社区中逐渐失宠。

  • 内核的模块加载接口是完全开放的。一旦进程拥有 root 权限,就可以很容易地注入内核模块而无需任何检查。我们还可以为内核模块编写另一个验证器,但内核围绕模块的基础设施非常原始。

I realize this is an ancient question but I just now found it.

I wrote signed executable support for the Linux kernel (around version 2.4.3) a while back, and had the entire toolchain in place for signing executables, checking the signatures at execve(2) time, caching the signature validation information (clearing the validation when the file was opened for writing or otherwise modified), embedding the signatures into arbitrary ELF programs, etc. It did introduce some performance penalties upon the first execution of every program (because the kernel had to load in the entire file, rather than just demand-page the needed pages) but once the system was in a steady-state, it worked well.

But we decided to stop pursuing it because it faced several problems that were too large to justify the complexity:

  • We had not yet built support for signed libraries. Signed libraries would require also modifying the ld.so loader and the dlopen(3) mechanism. This wasn't impossible but did complicate the interface: should we have the loader ask the kernel to validate a signature or should the computation be done entirely in userspace? How would one protect against a strace(2)d process if this portion of the validation is done in userspace? Would we be forced to forbid strace(2) entirely on such a system?

    What would we do about programs that supply their own loader?

  • A great many programs are written in languages that do not compile to ELF objects. We would need to provide language-specific modifications to bash, perl, python, java, awk, sed, and so on, for each of the interpreters to be able to also validate signatures. Since most of these programs are free-format plain text they lack the structure that made embedding digital signatures into ELF object files so easy. Where would the signatures be stored? In the scripts? In extended attributes? In an external database of signatures?

  • Many interpreters are wide open about what they allow; bash(1) can communicate with remote systems entirely on its own using echo and /dev/tcp, and can easily be tricked into executing anything an attacker needs doing. Signed or not, you couldn't trust them once they were under control of a hacker.

  • The prime motivator for signed executables support comes from rootkits replacing the system-provided /bin/ps, /bin/ps, /bin/kill, and so on. Yes, there are other useful reasons to have signed executables. However, rootkits got significantly more impressive over time, with many relying on kernel hacks to hide their activities from administrators. Once the kernel has been hacked, the whole game is over. As a result of the sophistication of rootkits the tools we were hoping to prevent from being used were falling out of favor in the hacking community.

  • The kernel's module loading interface was wide-open. Once a process has root privilege, it was easy to inject a kernel module without any checking. We could have also written another verifier for kernel modules but the kernel's infrastructure around modules was very primitive.

夏有森光若流苏 2024-08-17 19:06:06

GNU/Linux/FOSS 模型实际上鼓励某种程度的篡改。用户和发行版制造商必须可以自由修改(篡改)软件以满足他们的需求。即使只是重新编译软件(不更改任何源代码)进行定制也是很常见的事情,但会破坏二进制代码签名。因此,二进制代码签名模型并不是特别适合 GNU/Linux/FOSS。

相反,这种软件更多地依赖于生成签名和/或源包的安全散列。与可靠且可信的包分发模型相结合,这可以与二进制代码签名一样安全(如果不是更安全,相对于源代码的透明度)。

The GNU/Linux/FOSS model actually encourages tampering -- of a sort. Users and distro-makers must be free to modify (tamper with) the software to suit their needs. Even just recompiling the software (without changing any source code) for customization is something that is done quite often, but would break binary code-signing. As a result, the binary code-signing model isn't particularly well suited to GNU/Linux/FOSS.

Instead, this kind of software relies more on generating signatures and/or secure hashes of the source packages. In combination with a reliable and trusted package distribution model, this can be made just as secure (if not more so, vis-à-vis transparency into the source code) as binary code-signing.

彼岸花ソ最美的依靠 2024-08-17 19:06:06

DigSig 内核模块实现了对由名为 bsign 的工具签名的二进制文件的验证。然而,自 Linux 内核 2.6.21 版本以来,还没有任何相关工作。

The DigSig kernel module implements verification of binaries signed by a tool called bsign. However, there hasn't been any work on it since version 2.6.21 of the Linux kernel.

痴梦一场 2024-08-17 19:06:06

看看这个: http://linux-ima.sourceforge.net/

它还没有签名,但仍然可以进行验证。

Have a look at this: http://linux-ima.sourceforge.net/

It's not signing yet, but it still enables verification.

救赎№ 2024-08-17 19:06:06

我可以通过 Solaris 10 和 Solaris 来回答这个问题。 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 验证引导简介

OpenSolaris 代码有一些生产级分支,其中三个值得研究的是 Illumos、SmartOS 和 OmniOS。

I can answer the question from a Solaris 10 & 11 OS perspective, all binaries are signed. To verify the signature use '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 have recently added a verified boot process for Solaris 11 too, for details see - Solaris Verified Boot Introduction

There are some production grade forks of the OpenSolaris code, three worth investigating are Illumos, SmartOS and OmniOS.

情感失落者 2024-08-17 19:06:06

看看 Medusa DS9。我很久以前就玩过它,但如果我没记错的话,你可以注册特定的二进制文件,并且在内核级别不允许进行任何修改。当然,可以通过对机器的本地访问来覆盖它,但这并不容易。有一个名为 constable 的智能守护进程,它检查机器上发生的所有情况,如果发生异常情况,它就会开始尖叫。

Take a look at Medusa DS9. I played with it a long (long) time ago, but if I remember correctly, you could register specific binaries and any modification was not allowed at the kernel level. Of course, it can be overridden with local access to the machine, but it was not really easy. There's a smart daemon, called constable, checking everything that happens on the machine and if something out of the ordinary occurs, it start screaming.

拧巴小姐 2024-08-17 19:06:06

我从未尝试过,但请看一下:http://blog。 codenoise.com/signelf-digitally-signing-elf-binaries。该解决方案无需内核支持即可工作,并且看起来已经准备就绪。

签名者的代码可以在 http://sourceforge.net/projects/signelf/

找到不能解决“在 Linux 上仅运行受信任的代码”问题,但它确实通过让程序检测自身可能的篡改/损坏的方式部分解决了问题

I've never tried it, but take a look at : http://blog.codenoise.com/signelf-digitally-signing-elf-binaries. The solution works without needing kernel support, and looks like to be ready to go.

The code for the signer can be found at http://sourceforge.net/projects/signelf/

It does not solve the "Run only trusted code on linux" question, but it does partially solve the problem by making a way for the program to detect itself a possible tampering/corruption

转瞬即逝 2024-08-17 19:06:06

我喜欢将安全视为一条链条。链条中的薄弱环节可能会危及整个系统。所以整个事情就变成了“防止未经授权的用户获取root密码”。

正如 @DanMoulding 所建议的,软件的来源也很重要,将来可能官方操作系统应用程序商店将成为标准。想想 Play 商店、Apple 或 Microsoft 商店。

我认为安装和分发隐蔽的恶意代码是
更阴险的问题。毕竟,为了加载坏代码,它是
必须首先安装在系统上的某个地方。更多层数
当然,安全性通常更好。问题是:值得吗
费用?

我认为答案是“视情况而定”。
您可以通过采用 @sleblanc 建议的一组安全策略来降低风险。您可以加密您的文件系统 (https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup ),对二进制文件使用只读文件系统或使用某种机制来签名和验证二进制文件。

然而,无论您使用什么机制,一旦攻击者获得根访问权限,您就无能为力。签名验证工具可以替换为篡改版本或只是禁用,并且一旦机器受到损害,这些工具是否在用户空间或内核空间中运行并不重要(当然后者会更安全) )。

因此,如果 Linux 内核能够在 root 用户和操作系统之间嵌入签名验证模块和另一个安全层,那就太好了。

例如,最近的 macOS 就采用了这种方法< /em> 版本。有些文件即使是 root 帐户也无法修改(有时甚至无法读取),并且策略和内核模块也受到限制(例如,只能在系统上加载签名或授权的 kext)。 WindowsAppLocker采用了或多或少相同的方法。

I like to think to security as a chain. The weaker link of the chain can compromise the whole system. So the whole thing become "preventing an unauthorized user from obtaining the root password".

As suggested by @DanMoulding the source of the software is also important and in the future probably official OS application stores will be the standard. Think about Play Store, Apple or Microsoft stores.

I think installation and distribution of covert malicious code is the
far more insidious problem. After all, in order to load bad code it's
got to first be installed on the system somewhere. More layers of
security are usually better, of course. The question is: is it worth
the cost?

In my opinion the answer is "it depends".
You can reduce the risk by adopting a set of security policies as suggested by @sleblanc. You can encrypt your file system (https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup), use read-only file systems for the binaries or use a mechanism to sign and verify the binaries.

However whatever mechanism you use there is nothing you can do once the root access is obtained by an attacker. The signature verification tools can be replaced with a tampered version or just disabled and it doesn't really matter if the tools run in user-space or kernel-space once that the machine has been compromised (although the latter would be more secure of course).

So it would be nice if the Linux kernel could embeds a signature verification module and another security layer between the root user and the operating system.

For example this is the approach adopted on the recent macOS versions. Some file can't be modified (and sometimes read) even by the root account and there are restrictions also on the policies and kernel modules (e.g. only signed or authorized kext can be loaded on the system). Windows adopted more or less the same approach with AppLocker.

动听の歌 2024-08-17 19:06:06

http://en.wikipedia.org/wiki/PKCS

使用 PKCS7 (S/MIME )它的标志。生成您自己的证书/私钥对,对证书进行自签名,然后使用 PKCS7 使用私钥和证书对您的文件进行签名。它将把证书附加到它上面,然后它可以使用 openssl 命令在运行时检查自身(man smime 或只是做 openssl help)。这是防篡改的,因为即使公钥位于您提供的文件中,该公钥的 S/MIME 签名也只能使用您不会分发的私钥生成。因此,如果文件是由您的证书签名的,则它一定是由拥有私钥的人签名的,并且由于您没有将私钥提供给任何人,因此它一定来自您。

以下是制作自签名证书的方法。

http://www.akadia.com/services/ssh_test_certificate.html

您将必须说服 openssl 信任您的证书作为权威根(-CAfile),然后将其作为根进行检查,并检查文件上的证书是您的(对证书进行哈希处理)并检查哈希值。请注意,虽然没有记录,但 openssl 的退出状态反映了您在进行 smime 验证时检查的标志的有效性。如果匹配则为 0,如果不匹配则为非零。

请注意,所有这些都是不安全的,因为如果检查在您的代码中,如果他们想击败您,他们可以简单地删除检查。唯一安全的方法是在操作系统中安装检查器,并让它检查您的二进制文件,如果未签名则拒绝运行它。但由于操作系统中没有检查器,并且无论如何都可以修改 Linux 来删除/绕过它......这真正的好处只是检测损坏的文件,而不是试图阻止人们绕过你。

http://en.wikipedia.org/wiki/PKCS

Use a PKCS7 (S/MIME) sign of it. Generate your own cert/private key pair, self-sign the cert and then sign your file with the private key and cert using PKCS7. It'll attach the cert to it, and then it can check itself at runtime using the openssl command (man smime or just do openssl help). This is tamperproof because even though the public key is in the files you give out, the S/MIME signature for that public key can only be generated with the private key which you won't distribute. So if the file is signed by your cert, it must have been signed by someone with the private key and since you didn't give the private key to anyone, it must have come from you.

Here's how to make the self-signed certificate.

http://www.akadia.com/services/ssh_test_certificate.html

You'll have to convince openssl to trust your cert as a root of authority (-CAfile), then check it with that as the root, and also check the cert on the file is yours (hash the cert) and check the hash. Note that although it isn't documented, the exit status of openssl reflects the validity of the sign you are checking when doing an smime verify. It's 0 if it matches, non-zero if it doesn't.

Note that all of this is not secure because if the check is in your code, they can simply remove the check if they want to beat you. The only secure way to do it would be to have the checker in the OS and have it check your binary and refuse to run it if it isn't signed. But since there is no checker in the OS and linux can be modified to remove/bypass it anyway... What this is really good for is just detecting corrupt files more than trying to keep people from bypassing you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文