[pkg-cryptsetup-devel] Bug#939357: Bug#939357: cryptsetup-run: invoking "sudo cryptdisks_start" with "decrypt_keyctl" in crypttab fails
Guilhem Moulin
guilhem at debian.org
Thu Sep 5 01:03:34 BST 2019
Control: retitle -1 `decrypt_keyctl` fails when the user-keyring(7) isn't attached to the calling process
Hi Sebastian,
Thanks for the detailed report! I was able to reproduce this in a fresh
Buster netinstall, taking SSH sessions and sudo(8)'s ā-iā flag out of
the picture. This is what I get right after a reboot:
user at kvm-31992:~$ sudo keyctl show @u
Keyring
99804791 --alswrv 0 65534 keyring: _uid.0
user at kvm-31992:~$ sudo keyctl show @s
Keyring
1021507217 --alswrv 1000 1000 keyring: _ses
872133423 ---lswrv 1000 65534 \_ keyring: _uid.1000
user at kvm-31992:~$ sudo keyctl show @us
Keyring
133933438 --alswrv 0 65534 keyring: _uid_ses.0
99804791 --alswrv 0 65534 \_ keyring: _uid.0
Keys attached to root's user-keyring(7) can't be read.
user at kvm-31992:~$ sudo keyctl add user "foo" "bar" @u
875128385
user at kvm-31992:~$ sudo keyctl show @us
Keyring
133933438 --alswrv 0 65534 keyring: _uid_ses.0
99804791 --alswrv 0 65534 \_ keyring: _uid.0
875128385 --alswrv 0 0 \_ user: foo
user at kvm-31992:~$ sudo keyctl print 875128385
keyctl_read_alloc: Permission denied
So LUKS2 volumes can't be open using token keyrings:
user at kvm-31992:~$ sudo dd if=/dev/zero of=/tmp/disk.img bs=1M count=64 status=none
user at kvm-31992:~$ sudo cryptsetup luksFormat -q \
--pbkdf-force-iterations 4 --pbkdf-memory 32 /tmp/disk.img <<<bar
user at kvm-31992:~$ sudo cryptsetup token add --key-description foo -S 0 /tmp/disk.img
user at kvm-31992:~$ sudo cryptsetup luksOpen --test-passphrase --debug \
--token-only /tmp/disk.img
[ā¦]
# keyring_get_passphrase failed (error -126)
# Token 0 (luks2-keyring) open failed with -22.
And indeed decrypt_keyctl chokes as well:
user at kvm-31992:~$ sudo CRYPTTAB_NAME=foo CRYPTTAB_KEY=bar CRYPTTAB_TRIED=0 \
/lib/cryptsetup/scripts/decrypt_keyctl
Caching passphrase for foo: ***
keyctl_set_timeout: Permission denied
Error setting timeout on key (163348240), removing
AFAICT this is because the caller doesn't possess %user:foo, cf.
https://manpages.debian.org/buster/manpages/keyrings.7.en.html#Possession
A workaround is to do these operations in a new session-keyring(7), and
link root's user-keyring(7) to it.
user at kvm-31992:~$ sudo keyctl session
Joined session keyring: 777897511
root at kvm-31992:/home/user# keyctl link @u @s
root at kvm-31992:/home/user# keyctl show
Session Keyring
777897511 --alswrv 0 0 keyring: _ses
99804791 --alswrv 0 65534 \_ keyring: _uid.0
875128385 --alswrv 0 0 \_ user: foo
root at kvm-31992:/home/user# keyctl print 875128385
bar
root at kvm-31992:/home/user# cryptsetup luksOpen --test-passphrase -v \
--token-only /tmp/disk.img
Key slot 0 unlocked.
Command successful.
root at kvm-31992:/home/user# CRYPTTAB_NAME=foo CRYPTTAB_KEY=bar CRYPTTAB_TRIED=0 \
/lib/cryptsetup/scripts/decrypt_keyctl >/dev/null
Caching passphrase for foo: ***
root at kvm-31992:/home/user# exit
I suppose /etc/pam.d/sudo could use pam_keyinit(8) to initialize a new
session instead of doing the above dance. Anyway cryptsetup calls
request_key("user",,NULL,0) at the moment, so unlocking LUKS2 devices
via keyring tokens will only works in sessions where the user-keyring(7)
is linked to the session-keyring(7).
On Wed, 04 Sep 2019 at 00:18:57 +0200, Sebastian Mohr wrote:
> I don't know whether there are further security implications or
> something like that,
AFAICT blindly using session-keyring(7) as it might open a window during
which any program in the user session is able to read the payload:
user at kvm-31992:~$ sudo keyctl add user "foo" "foo" @s
137160032
user at kvm-31992:~$ keyctl show @s
Keyring
461059914 --alswrv 1000 1000 keyring: _ses
641525861 --alswrv 1000 65534 \_ keyring: _uid.1000
137160032 --alswrv 0 0 \_ user: foo
user at kvm-31992:~$ keyctl print 137160032
foo
(While the key is owned by the privileged user, it's possessed by the
caller. It might even be possible to poison the session-keyring(7)
by creating %user:foo with non-root ownership.) I think the best place
to solve that is in /etc/pam.d/sudo itself, but failing that I suppose
it's acceptable to have the payload readable by root (perhaps only as
fallback, when the caller doesn't have enough right on the key it's
adding).
Perhaps keyctl(1) could provide a wrapper using thread-keyring(7) as
temporary keyring, like the attached PoC. Or we could even rewrite
decrypt_keyctl in C, or merge it with askpass. In fact one of our goals
for this release cycle is to better integrate crypttab(5) with LUKS2
native keyring support, and that probably goes via adding keyring
support in askpass.
Cheers,
--
Guilhem.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://alioth-lists.debian.net/pipermail/pkg-cryptsetup-devel/attachments/20190905/6515ad98/attachment.sig>
More information about the pkg-cryptsetup-devel
mailing list