In May 2002 I had an idea for securing access to GNUPG [1]. What I did was to write SE Linux policy to only permit the gpg program to access the secret key (and other files in ~/.gnupg). This meant that the most trivial ways of stealing the secret key would be prevented. However an attacker could still use gpg to encrypt it’s secret key and write the data to some place that is accessible, for example the command “gpg -c --output /tmp/foo.gpg ~/.gnupg/secring.gpg“. So what we needed was for gpg to either refuse to encrypt such files, or to spawn a child process for accessing such files (which could be granted different access to the filesystem). I filed the Debian bug report 146345 [2] requesting this feature.
In March upstream added this feature, the Debian package is currently not built with --enable-selinux-support so this feature isn’t enabled yet, but hopefully it will be soon. Incidentally the feature as currently implemented is not really SE Linux specific, it seems to me that there are many potential situations where it could be useful without SE Linux. For example if you were using one of the path-name based MAC systems (which I dislike – see what my friend Joshua Brindle wrote about them for an explanation [3]) then you could gain some benefits from this. A situation where there is even smaller potential for benefit is in the case of an automated system which runs gpg which could allow an attacker to pass bogus commands to it. When exploiting a shell script it might be easier to specify the wrong file to encrypt than to perform more sophisticated attacks.
When the feature in question is enabled the command “gpg -c --output /tmp/foo.gpg ~/.gnupg/secring.gpg” will abort with the following error:
gpg: can’t open `/root/.gnupg/secring.gpg’: Operation not permitted
gpg: symmetric encryption of `/root/.gnupg/secring.gpg’ failed: file open error
Of course the command “gpg --export-secret-keys” will abort with the following error:
gpg: exporting secret keys not allowed
gpg: WARNING: nothing exported
Now we need to determine the correct way of exporting secret keys and modifying the GPG configuration. It might be best to allow exporting the secret keys when not running SE Linux (or other supported MAC systems), or when running in permissive mode (as in those situations merely copying the files will work). Although we could have an option in gpg.conf for this for the case where we want to prevent shell-script quoting hacks.
For editing the gpg.conf file and exporting the secret keys we could have a program similar in concept to crontab(1) which has PAM support to determine when it should perform it’s actions. Also it seems to me that crontab(1) could do with PAM support (I’ve filed Debian bug report 484743 [4] requesting this).
Finally one thing that should be noted is that the targeted policy for SE Linux does not restrict GPG (which runs in the unconfined_t domain). Thus most people who use SE Linux at the moment aren’t getting any benefits from such things. This will change eventually.
This may be too obvious, but how about only allowing the secret keys to be exported when they’re encrypted *to* the secret key? In other words, using the public key for a secret key to encrypt the keyring, then exporting the encrypted result.
If I’ve got the secret key anyway, (or at least know the passphrase in order to decrypt the bundle), and I have local filesystem and shell access, I can send stuff signed by the secret key, and read stuff encrypted to it anyway. You’re thus not opening up a huge extra vulnerability.
Simon: Exporting a secret key encrypted so that it can only be decrypted with that secret key does not make much sense to me. Either you want a backup or install that key on a second box. How do you want to decrypt it then on the second box? Catch-22.
What is the standard way to check whether a process is running under SE-linux control?
We could at a option to gpg.conf to the effect that if that option is set and gpg detects that it is under SE-Linux control, the gpg internal permission checks are disabled (or at least those for exporting keys).
Werner:
You export it encrypted; you then decrypt it on the box you’re on, and back it up or install it on a second box.
I’m making the assumption that it’s easier to crack any passphrase given the secring file than it is to brute-force it through running GPG.
Either the goal is to prevent you backing up the key at all, or the goal is to prevent people who cannot use the key from backing it up.
An equivalent fix would be to require key passphrases when exporting the secret keys; if you don’t know the key passphrase, you can’t export it.
http://www.coker.com.au/selinux/play.html
Werner: security_getenforce(3) is what you want. The above URL has the login details for a test machine, I would be happy to give you your own account (root is shared and random people can rm files etc). If you login at a quiet time (most times) then you could test compiling some code there.
Simon’s idea of requesting the pass-phrase before backing up a key makes sense for some situations. However I can imagine the case where you want cron jobs to decrypt or sign data but don’t want them to be able to send the public key out over the net.
We probably need a configuration option for this.
Okay, an extra transport key to encrypt keys during export would make sense but I see problem to manage that properly.
The idea to require a passphrase for export actually makes sense. It has been requested for years but I always rejected it with the rationale that it won’t help because the user could just copy the secring.gpg. Of course with SE this is different.
[Typo above; it should be: … send the private key…]
I created https://bugs.g10code.com/gnupg/issue928 to remember this. I guess you want to have that in Lenny; need to hurry a bit.
What about this:
if ( ! is_selinux_enabled () )
disable_all_se_linux_hacks ();
else if ( security_getenforce () != 1 )
allow_secret_key_export ();
My man page for is_selinux_enabled states “May change soon” – what does thins mean?
I think for exporting the secret keys there should be at least a config option to select permissive (always) or something more restricted.
But i’m not sure if disallowing the user to read his/her own files is a good idea. I’d wish that even with selinux* the user keeps full control over his files and potentially problematic programs (all internet software, etc) would run somehow with a different MAC context that restricts only those. Then gpg would “only” need to find out if the calling context can read the file to check if exporting is allowed.
Is something like that possible with SElinux?
* standard end user configuration for SElinux, obviously the local admin might have reasons to use an other policy and SElinux shouldn’t enforce things like this.
Werner: If someone seems to be using some underhand method of reading the secret key, then that should be blocked at any time. Without SE Linux the user can use cp to get the secring.gpg file. The defined way of doing this from gpg is –export-secret-keys, having this force the user to encrypt the data would make sense. Allowing no way of exporting unencrypted secret key data makes sense (that would not deny them access as cp still works).
Even without SE Linux it seems to me that there still is the possibility that blocking unusual ways of accessing secret data can do some good.
Why not allow exporting of secret keys to a file; but only as long as the newly created file can be created with the same SELinux context as the secret key ring itself. This would allow secret keys to be exported when needed (without disabling GPG functionality or mandating special password restrictions only when in SELinux mode), but still allow SELinux profiles to maintain control over those exported secret keys, since you’re not allowing data to be copied across different security contexts.