Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Signed executables under Linux

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?

like image 562
TH. Avatar asked Nov 14 '09 01:11

TH.


People also ask

Are Linux binaries signed?

Yes, Linux does have ELF signing. I'm guessing you are speaking more generally about ensuring that "only signed code is allowed to execute", rather than just "making sure ELF binaries are signed" based on the remaining context of your comment.

What is code signing Linux?

Signing code involves associating a cryptographic signature with a specific digital artifact – release files, container images, and binaries – so that the person using the software can check the code's signature to verify that the release is authentic and hasn't been altered by someone along the way.

What are signed executables?

Executable signing certificates, commonly referred to as code signing certificates, are digital files you can use to digitally sign executable files (.exe files). The code signing certificate uses a cryptographic hash that validates the executable file's integrity and authenticity.

Are Linux packages signed?

All Red Hat Enterprise Linux packages are signed with the Red Hat GPG key. GPG stands for GNU Privacy Guard, or GnuPG, a free software package used for ensuring the authenticity of distributed files. For example, a private key (secret key) locks the package while the public key unlocks and verifies the package.


2 Answers

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.

like image 197
sarnold Avatar answered Sep 21 '22 20:09

sarnold


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.

like image 41
Dan Moulding Avatar answered Sep 23 '22 20:09

Dan Moulding