[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