code signing in FreeBSD

All,

I was just wondering if it was possible, or if there were plans to support the ability to enforce code signing (on binaries, at runtime) in FreeBSD? Why do I ask? Because history has shown over the past 20 years or so that allowing unsigned code to run by default is a security nightmare. The ability to enforce code signing would reduce the risks of running as a privileged user (or hell, normal user for that matter), as an un-signed, tojaned or otherwise modified binary will refuse to run.

I'm thinking that if you could either use a central FreeBSD repository CA, or have the ability to set up your own local CA as an optional step.

Both Apple and Microsoft are going down this path with OS X 10.8 and Windows 8.

I think so long as we can control who has the "keys to the castle" at install time (local admin's CA, repository CA or code-signing switched off in the boot-loader), code signing can only be a good thing?
 
How would those binaries be signed? A lot of us build FreeBSD from source. How could you tell if it's a modified source that's being used to build a trojaned executable or not?

The idea would work for binary updates but not so much for source updates.
 
I'm not sure I got the point, but we can sign source code, we can sign binaries and check hashes (the ports already does). Of course it is nor possible to avoid a user to modify locally source file, compile and sign the result. And therefore signed binaries will not protect you against someone who already has access to the system. I guess the best could be having an mtree or similar database against which are compared the base executables. Configuration files are another story.
 
The point is, on an average UNIX system there are a lot of scripts running under the root account. How are you going to protect against that? With ELF executables, you have a single loading point: kernel. Which could check some embedded certificate before running the program. With scripts, you have a ton of interpreters. Each interpreter should do that job, and that's impossible.

On the other hand, this whole "trusted binaries" issue comes down to mending the situation after someone exploited a system account. Prevent exploiting.

Besides, OSX and Windows are layman operating systems. FreeBSD is for technical users. You're expected to build, tweak, and change FreeBSD's stuff. Introducing code signing bullsh*t would only slow down the workflow. And most of us use FreeBSD because it doesn't slow us down, unlike those two OSes mentioned before.

The truth is, I've thought a lot about this same issue, of making a KLD that would load a read-only table of binaries and their hashes on boot, and prevent loading any program that doesn't match. However, as I've progressed with the idea, I came to conclusions that I've listed here. And there are plethora of problems and traps.

As with most Windows "advanced security mechanisms", this one would be easily avoided and just present an additional burden to normal users/admins.
 
Why not applying secure levels to files, so that you can be sure the file you are "loading" has not been modified? Seems to me at least complex to manage as a signature applied to files.
 
Only loading signed binaries may be not working for a running system, but what I would whish for is a way to be sure that no one messed with the non-encrypted parts of my laptop while I was not able to look at it.
 
Zare said:
Code:
#!/bin/sh

rm -rf /

Sign this.

Can be done in powershell. No reason any of the unix shells couldn't be extended in a similar manner.

SirDice said:
How would those binaries be signed? A lot of us build FreeBSD from source. How could you tell if it's a modified source that's being used to build a trojaned executable or not?

The idea would work for binary updates but not so much for source updates.

I'm not sure, but just putting the idea out there at this stage. Maybe the compiler needs to know about signing so that known good source files can be signed, and the signing honored? I mean, if the linux kernel source was signed, when they had the kernel.org breach a while back there would have been a lot less concern - modified files without Linus' signature (another authorized committer) on them (embedded at the end of the .c file) would not compile (assuming the compiler checked code-signing).

I'm not talking about making it mandatory but it would, for example be useful to be able to set up a local CA, install your box, then sign all the binaries so that if modified they will not run - and any further executable uploaded to the box without the signature will not run.

i.e., the OPTION to ensure only signed code (either signed binaries from the FTP site, or self-signed binaries from your own CA) will run would be useful. Option in the boot loader to turn on/off....


I'm not saying it will be easy - simply that I believe this is the way things will end up going, because when you have code hosted on public internet servers, there's no guarantee that your trusted host hasn't been hacked, and your files trojan-ed. You'll typically only find out when the host compromise has been reported, or someone re-examines the source in detail which may be months....

For an example of how it is done in powershell (for scripts), see here:
http://www.hanselman.com/blog/SigningPowerShellScripts.aspx

No reason C source couldn't be modified in a similar manner after it has been "released" with an authorised FreeBSD maintainer's key - assuming the compiler was code-signing aware.
 
throAU said:
I'm not sure, but just putting the idea out there at this stage. Maybe the compiler needs to know about signing so that known good source files can be signed, and the signing honored? I mean, if the linux kernel source was signed, when they had the kernel.org breach a while back there would have been a lot less concern - modified files without Linus' signature (another authorized committer) on them (embedded at the end of the .c file) would not compile (assuming the compiler checked code-signing).

I don't believe this is a task the compiler should do, after all a compiler should simply compile what you give as input. This is the aim of other tools, such as git and hash checksums.

throAU said:
I'm not talking about making it mandatory but it would, for example be useful to be able to set up a local CA, install your box, then sign all the binaries so that if modified they will not run - and any further executable uploaded to the box without the signature will not run.

Again this sounds to me as making binary filesystem not writable, with file flags turned on, and other filesystem not suid.
 
fluca1978 said:
I don't believe this is a task the compiler should do, after all a compiler should simply compile what you give as input. This is the aim of other tools, such as git and hash checksums.

On second thoughts - agreed, however maybe some sort of pre-processor to check signatures would be appropriate? (and again: optional).


Again this sounds to me as making binary filesystem not writable, with file flags turned on, and other filesystem not suid.

This won't protect you from code that has been changed on the source server you download your binaries (or source for that matter) from. It won't protect you from a rogue mirror / p2p trojan-ed download, malicious internal employee, DNS spoofed/hacked update server, etc.

Read-only/no-suid filesystems are a good thing, don't get me wrong, but they're not a silver bullet. At the end of the day, come update time, an admin is likely to download source from his "trusted" repository (whether that is an official mirror, internally hosted branch or whatever), and compile then install it. To do that, the filesystem will be made read-write. I would wager that close to 100% of admins do not have the time to audit the source code first.

I'm not saying code-signing is a silver bullet either, but it is another option/tool in the arsenal...
 
throAU said:
This won't protect you from code that has been changed on the source server you download your binaries (or source for that matter) from.
Neither would signing. If an attacker is able to modify the source, he's also able to modify the hash. Besides, the (automated) build process will happily create a signed binary from backdoored source and nobody would be anything wiser unless they looked at the source.

It won't protect you from a rogue mirror / p2p trojan-ed download, malicious internal employee, DNS spoofed/hacked update server, etc.
It would protect against this but due diligence will also protect you.
 
throAU said:
On second thoughts - agreed, however maybe some sort of pre-processor to check signatures would be appropriate? (and again: optional).


No, I don't think so. Compilers have to do their work, that is compile source code. Let's do the verification to some other tool. The tools you are looking for are git and/or mercurial or alike.

throAU said:
This won't protect you from code that has been changed on the source server you download your binaries (or source for that matter) from. It won't protect you from a rogue mirror / p2p trojan-ed download, malicious internal employee, DNS spoofed/hacked update server, etc.

I think there is nothing that can protect you against a compromised trusted party. If you trust the remote server and that has been compromised, also the signatures will be adjusted to masquerade the malicious behavior, and therefore you will not notice. In such a scenario you would have to check against several mirrors to see if all agree about the binary and its signature, and only then you can almost trust one of them.

throAU said:
Read-only/no-suid filesystems are a good thing, don't get me wrong, but they're not a silver bullet. At the end of the day, come update time, an admin is likely to download source from his "trusted" repository (whether that is an official mirror, internally hosted branch or whatever), and compile then install it. To do that, the filesystem will be made read-write. I would wager that close to 100% of admins do not have the time to audit the source code first.

My example of read-only filesystem was meant to emphasize that, in my opinion, having a tool that loads executable only if signed is like having a clean and trusted install that does not change. Of course if you need to update you have to write on the local filesystem, but again you are going to install some trusted components (checksums, hash, ...) and then you can harden your machine again. I don't see how signatures can improve this scenario...
 
SirDice said:
Neither would signing. If an attacker is able to modify the source, he's also able to modify the hash.

If it is signed via a certificate, then unless he has the authorized signatory's private key (stored on the developer's machine - not the repository - and validated against a third party's CRL), then no, he can't sign the binaries/source.

By pre-processor, I meant some additional tool.. not necessarily part of the compiler. I agree it is a separate task.

My point with all this is that trusting public servers to host code without them being hacked and the code modified is a risk. Given the kernel.org compromise, a very real risk. If the code has to be signed using a public key infrastructure, then unless the private key (not stored on the FTP/CVS mirror) is compromised, the code can be verified as being unmodified from the point where the team signed off on it as valid.

A private key is a lot easier to secure than every mirror site, sitting on the internet. I'm making the assumption here that, eventually, they WILL be compromised.

IF the key is compromised - revoke it. Instantly, all copies of the compromised/old source/binaries are flagged as invalid because they aren't signed with the current key.
 
throAU said:
IF the key is compromised - revoke it. Instantly, all copies of the compromised/old source/binaries are flagged as invalid because they aren't signed with the current key.
Instantly killing every single install up to that date, including ones that don't have the backdoored code. Potentially this will take hundreds, if not thousands, of FreeBSD installations offline.

I don't think the admins are going to like that...
 
throAU said:
Given the kernel.org compromise, a very real risk. If the code has to be signed using a public key infrastructure, then unless the private key (not stored on the FTP/CVS mirror) is compromised, the code can be verified as being unmodified from the point where the team signed off on it as valid.

As far as I know, bitkeeper has checksums that helped finding the compromise. So even in such case there was not the need for signatures. Or better, signatures were already there (even is not so much strong).

throAU said:
IF the key is compromised - revoke it. Instantly, all copies of the compromised/old source/binaries are flagged as invalid because they aren't signed with the current key.

Besides having to invalidate a lot of running systems, this also means that signatures have to be checked each time the executable is run, not only at the install phase, and therefore this will overkill the network, reduce performances, and simply will not let me run a program on my laptop when offline.

I admit that using keys can help preventing some critical scenarios, but I don't see the point for an easy and effective wide application.
 
Something random to be thrown into the ring. Esp. the part about "Reflections on Trusting Trust" can be recommended. :stud
 
Back
Top