Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Locked screen fails unlock with YubiKey on Kubuntu (KDE-based Ubuntu) #113

Open
conz27 opened this issue Dec 30, 2016 · 31 comments
Open

Comments

@conz27
Copy link

conz27 commented Dec 30, 2016

The issue seems similar to #92 and #99 that were reported earlier, but for the KDE-based Linux distros.

The process that runs the lock-screen: kscreenlocker_greet runs as the session user as opposed to root. So when the CR occurs, it receives a "Permission Denied" when it tries to open /var/yubcio/user-123456 because chown is set as follows: root:user.

As soon as I changed the permission on /var/yubico/user-123456 to -rw-r-----, the lock screen worked just fine.

As far as I understand, the challenge response stored in /var/yubico/user-123456 is sensitive, hence should only be accessible by root?

@conz27 conz27 changed the title Locked screen fails unlock with YubiKey on Kubuntu (KDE-based Ubuntu) [BUG] Locked screen fails unlock with YubiKey on Kubuntu (KDE-based Ubuntu) Dec 30, 2016
@Joeviocoe
Copy link

Is there a workaround for this? Or am I expected to recompile with this commit 155b485?

Kubuntu has this issue when using the shared /var/yubico directory per the instructions. Linux Mint seems unaffected using the same configuration.

@klali
Copy link
Member

klali commented Jan 2, 2017

@Joeviocoe this issue is not a duplicate of #92 and #99, please avoid posting the same comment to multiple issues.

@conz27 I would say that expected usage of ykpamcfg is to run it as the user if you expect things running in the users context to be able to use the configuration. Maybe ykpamcfg should grow something to support running it as root but setting permissions properly for a user.

@conz27
Copy link
Author

conz27 commented Jan 2, 2017

@klali: unfortunately, I can't run ykpamcfg as the user because my home directory is in encrypted. I have to use the /var/yubico shared directory because of that.

I think the real question is:

When using ykpamcfg in shared-mode (i.e. /var/yubico), if ykpamcfg creates the /var/yubico/user-123456 file with root:user ownership, should the file permissions be set to 0640 as opposed to 0600. I mean whats the point of setting the file ownership to root:user if you're going to set the permissions to 0600? Might as well have set the ownership to root:root in that case.

@klali
Copy link
Member

klali commented Jan 2, 2017

Yes, this is a tricky situation. My thought would be to run it as the user with -p to write the file, but this gets thorny when you have multiple users.
Currently ykpamcfg known nothing about what user it writes the file for, it only sets the umask to 077, leaving group and user up to the environment it runs in.

Maybe it should be possible to give it a username and have the file chowned to that user after it is written? A different alternative would be to set umask 007 instead (write for user and group) and hope that group is going to be correct, but in that case we might want to take the group in as a parameter as well..

@crosser
Copy link
Contributor

crosser commented Jan 2, 2017

Using group permission does not look right to me. Not all setups have a personal group for each user. I would say, the file ought to be owned by the user. In my own implementation of challenge-response PAM module, I rely on the file being created owned by the user initially, and when I create a new replacement file, I carry over the ownership from the old file to the new like this.

@conz27
Copy link
Author

conz27 commented Jan 2, 2017

If the file is chowned by the user, it will work with both root and user-based processes like @klali and @crosser suggested - without requiring group knowledge or permissions. However, if user accounts are compromised by attackers then they will be able to read and/or change the CR file to whatever they like with only user-level privileges - which is the part that feels wrong to me. You'd think sudo privileges should be required to make modifications to an existing CR file.

I'm guessing that with the CR file being static, the response from the YubiKey is the same every time and HMAC-SHA1 does not use non-static values or counters. This means that if an attacker is able to see the CR file, they can perform a MITM replay attack with the response - meaning the YubiKey requirement is short-circuited.

Edit: I'm guessing the CR file is static ... is it actually?

Unless there is some kind of authentication algorithm TLS-like handshake using Diffie-Hellman between yubico-pam and the YubiKey to establish a mutually-authenticated channel ... HMAC-SHA1 by itself is vulnerable.

The privilege-level of the attacked user determines the blast-radius of the compromise - (i.e. if I have sudo privileges, the attacker gains sudo privileges provided they know my password and the CR).

klali added a commit that referenced this issue Jan 3, 2017
also refactor to use a tempfile when writing a new challenge file so we
rename it to the correct name as the last operation.

fixes #113
@klali
Copy link
Member

klali commented Jan 3, 2017

So the file is not static, for the process to work properly it has to be writable by the pam module. The reason for this is that two responses are calculated, one being for authentication of this session and one for authentication of the next one to not have a static challenge & response.

I've pushed a branch (https://github.com/Yubico/yubico-pam/commits/ykpamcfg_user) adding a username switch to ykpamcfg (this should also help with having to rename the file when using a common path).

@jeremyn
Copy link

jeremyn commented Mar 12, 2017

I'm also getting a permission error on the challenge file under /var/yubico when trying to unlock the screen, and this is with Ubuntu 16.10 with Unity, so this is not just a KDE problem.

@ghost
Copy link

ghost commented Mar 16, 2017

Workaround for KDE plasma 5:

Locate kcheckpass binary file on your system. It's installed by kscreenlocker package. It could be /usr/lib/kcheckpass or /usr/lib/x86_64-linux-gnu/libexec/kcheckpass and so on.

Next, give it SUID permissions:
chmod u+s /Path/to/kcheckpass

Now it should be able to read&write to any yubico directory. In this case SUID should be safe as it's supported by upstream in case PAM isn't avalaible.

Unfortunately SUID bit will bo gone in case kcheckpass file is overwritten i.e during update kscreenlocker package.

To undo above changes:
chmod u-s /Path/to/kcheckpass

@OOPMan
Copy link

OOPMan commented Apr 8, 2017

@fancytenseletters Thanks for the work-around! I was worried I'd have to sneak around using loginctl until this got fixed :-)

@potiuk
Copy link

potiuk commented May 2, 2017

Any workaround/suggestion for Ubuntu 16.04 with Gnome ? I have exactly the same problem :(

@potiuk
Copy link

potiuk commented May 3, 2017

Just looked a bit more closely - looks like in Ubuntu + Gnome it's the gnome-screensaver-dialog that calls the pam authentication method. Unfortunately setting the SUID bit does not help, and I checked the source code to see why - it seems that similarly to kcheckpass SUID is acceptable (for BSD style OS) but it's written in quite safe and sensible way - it drops the extra priviledges as one of the first things it does and switches back to the original user :( so the actual pam calls are executed as normal user .

For now the "workaround" is to use "Switch user" button rather than provide password when the screensaver dialog is displayed. Then you are thrown out to Lightdm (I use it instead of gdm). Lightdm of course runs as root, and have access to the file so it can login as usual. It kind of works, but is not the nicest way.

Any ideas how this can be solved are welcome!

@OOPMan
Copy link

OOPMan commented May 3, 2017

@potiuk Have you tried pinging the Gnome guys about this? Otherwise, you can use loginctl in a text-mode session to unlock the DM session

@potiuk
Copy link

potiuk commented May 3, 2017

I think it's not the question of gnome guys, there is nothing wrong with gnome about it (it's the same for KDE, Unity and likely others). How I understand it - it is more of an architectural problem with the yubico pam module security itself.

Firstly - it's perfectly OK for pam authentication to be run as both user, and root (on behalf of another user). Both cases are valid, and general screensaver consensus is that screensaver does not require root access and runs as the logged in user. Which is good and safe. It is actually a potential security hole if screensaver is run with setuid (there are multiple references in source code of gnome-screensaver about not opening that hole).

Unfortunately yubico's pam module's architecture with challenge-repsonse (for safety reason) requires storing non-static challenge/response information in a place which is not accessible to all applications running as the logged in user. It's again a sensible solution, otherwise any application should be able to read the upcoming challenge and response and do MITM attack as described by @conz27. For now the solution is that pam authentication must be run as root.

To be honest - it's not a blocker as there are workarounds that work. Not nicest and user friendly, but they do work. For example using "switch user" in gnome-screensaver and logging in again as the same user is functionally working OK (it kills the screensaver and switches to the login screen which is run as root). The only drawback is that you won't be able to type in the password directly in screensaver. That's a User Experience issue rather than functional.

We simply need a solution where only pam-library-code can store and read stored challenge/response, regardless from the user it runs as. Seems simple but not really.

I looked at other options that might be better than linux discretionary access rights. Using AppArmor is not good because it restricts sensitive apps rather than protects files. SELinux would be better but there are many distros (including Ubuntu) which do not have it by default and yubico would have to define whitelist of apps that are allowed to read the file. Maybe another solution would be that challenge/response data could be kept encrypted by the pam module (and user accessible). But then probably there is no good way to generate and keep the encryption keys in the way that only pam library could access. I cannot think of better solution, unfortunately :(

@ghost
Copy link

ghost commented May 3, 2017

You can try to set capabilities on gnome-screensaver like CAP_DAC_OVERRIDE, see https://www.insecure.ws/linux/getcap_setcap.html however there is possibility that it drops them too.

@crosser
Copy link
Contributor

crosser commented May 3, 2017

Unfortunately yubico's pam module's architecture with challenge-repsonse (for safety reason) requires storing non-static challenge/response information in a place which is not accessible to all applications running as the logged in user. It's again a sensible solution, otherwise any application should be able to read the upcoming challenge and response and do MITM attack as described by @conz27. For now the solution is that pam authentication must be run as root.

I would like to challenge the validity of this reasoning. In my view, if an adversary could read the pam state file with the userid of the attacked user, they are already in, and can read (and write) anything that belongs to the user. Preventing their subsequent login does not noticeably improve the situation, the user is already compromised.

For the above reason, I maintain that the right solution is to have the state file owned by the user. This is the approach that I take in my PAM module.

@OOPMan
Copy link

OOPMan commented May 3, 2017

@potiuk I think you're missing something which is that the KDE screenlocker does not run with SUID, it's the kcheckpass utility which does and is explicitly stated to be safe for this usage. Perhaps if Gnome broke out their screenlocker from the process of password verification they could achieve something similar?

Your exposition didn't really convince me. While you state that PAM auth can be run as user or root there seem to be multiple use-cases where it is restricted to root (only Yubico, Shadow Passwords file, probably other potential ones as well) for genuinely good reasons.

It thus seems to me that you should talk to the Gnome guys about this because workaround suggested by @fancytenseletters may very well be considered the right way to approach this?

@potiuk
Copy link

potiuk commented May 3, 2017

@crosser - it'a much worse if you also use C/R for things like sudo access. In my case - I was using initially C/R for both - logging-in and sudo access. Remember we are talking about also write access to the file (write access is needed because the stored challenge/response is not static - it changes every time you exercise challenge/response so that next time it will be different challenge and different response). So you could write your own challenge/response to the file and login as sudo using your own key for example (thus leading to priviledge escalation).

@crosser
Copy link
Contributor

crosser commented May 3, 2017

@potiuk I agree that sudo changes the perspective. My answer is not to use (only) the C/R module for sudo.

@potiuk
Copy link

potiuk commented May 3, 2017

@OOPMan true. It does look like KDE approach is the only "good" I can imagine in fact. I looked at kcheckpass implementation and they do mention that it is as simple as only possible in order to have less worries about setuid. Also it would play very well with AppArmour - because you could specifically restrict kcheckpass to only access what's needed. If only convincing gnome team to do something like that was easy. But it's a good idea to contact them. I will try to do it now :).

@potiuk
Copy link

potiuk commented May 3, 2017

@OOPMan issue raised: https://bugzilla.gnome.org/show_bug.cgi?id=782134

@EdRoxter
Copy link

In addition to @fancytenseletters 's excellent workaround (#113 (comment)), I want to add that I created a little systemd script which would just blindly run at boot time to set the +s bit on kcheckpass.

  1. Create (as root) a file /usr/local/bin/chmodkcheckpass.sh with the following content:
#!/bin/bash

/bin/chmod u+s /usr/lib/x86_64-linux-gnu/libexec/kcheckpass
exit 0

You may want to check if the path is correct.
2. Make it executable: sudo chmod u+x /usr/local/bin/chmodkcheckpass.sh
3. Create (as root) a minimal systemd service file, for example /etc/systemd/system/chmodkcheckpass.service with the following content:

[Unit]
Description=Chmod kcheckpass so unlocking works with yubikey

[Service]
ExecStart=/usr/local/bin/chmodkcheckpass.sh

[Install]
WantedBy=default.target
  1. Check that the +s bit is not set on kcheckpass, then run sudo systemctl start chmodkcheckpass.service
  2. Check if the +s bit is set now, additionally check tail /var/log/syslog if the service file ran without errors (i.e. there should be only one line saying Dec 20 14:18:02 edbook systemd[1]: Started Chmod kcheckpass so unlocking works with yubikey.)
  3. Set up the service for default run:
nico@edbook:~$ sudo systemctl enable chmodkcheckpass.service 
Created symlink /etc/systemd/system/default.target.wants/chmodkcheckpass.service → /etc/systemd/system/chmodkcheckpass.service.

So as long as there is no definite fix for this, this solution should work and also be update-proof.

@SecKatie
Copy link

SecKatie commented Feb 8, 2018

I am using mate and ran into the same problem. Would it be proper and secure to set a capability to the dialog using setcap? I was able to work around the issue in the mate desktop by using setcap cap_dac_read_search+ep /usr/lib/mate-screensaver/mate-screensaver-dialog This allows it to have read access to all files but not write access. I am currently in testing to see if it will drop the capability. It could also possibly be automated much in the same way that @EdRoxter automated the SUID permissions.

@NotSpecial
Copy link

I am using cinnamon on arch and experienced the same problem. In case it helps anyone, I have resorted to the following solution: Using two different challenge files, one with root, and one with user privileges.

Concretely, I use the root-accessible file for sudo, and the user accessible file for the cinnamon screensaver.

As far as I understand, the initial state of the challenge-response state file is random, and thus it should be impossible to use determine the current root state from the user state.

In practice, this is straightforward, as is requires only an additional pam rule. If there are any glaring security holes I am overlooking with this setup, please let me know. Otherwise it might be of use for someone.

@axilleas
Copy link

For anyone using Arch, you can use a pacman hook:

  1. Create the directory if it doesn't exist:

    sudo mkdir /etc/pacman.d/hooks
  2. Create /etc/pacman.d/hooks/kcheckpass.hook with the following contents:

    # Set SUID for kcheckpass so unlocking works with yubikey
    # https://github.com/Yubico/yubico-pam/issues/113#issuecomment-353061344
    # https://cgit.kde.org/kscreenlocker.git/tree/kcheckpass/README
    
    [Trigger]
    Operation = Install
    Operation = Upgrade
    Type = Package
    Target = kscreenlocker
    [Action]
    Depends = kscreenlocker
    Depends = yubico-pam
    When = PostTransaction
    Exec = /bin/chmod u+s /usr/lib/kcheckpass

@kmahyyg
Copy link

kmahyyg commented Apr 18, 2020

Thanks to @axilleas , Only his solution is working. Arch + kde5

@figboy9
Copy link

figboy9 commented Jun 17, 2022

After updating kscreenlocker, kcheckpass is gone and I can no longer unlock it. Does anyone have another solution?

kscreenlocker: 5.25.0-1

@davidshen84
Copy link

I got hit by this issue today after upgrading my kscreenlocker to 5.25.5.

+s to the /usr/lib64/libexec/kscreenlocker_greet file is simply not allowed by the Plasma framework because it is considered a security hole.

@edward-p
Copy link

edward-p commented Nov 25, 2022

I think the problem is at:

yubico-pam/drop_privs.c

Lines 85 to 93 in 5719a2f

if (setegid(pw->pw_gid) < 0) {
D (privs->debug_file, "setegid: %s", strerror(errno));
goto free_out;
}
if (seteuid(pw->pw_uid) < 0) {
D (privs->debug_file, "seteuid: %s", strerror(errno));
goto free_out;
}

Since kscreenlocker is running as normal user, setegid(pw->pw_gid) seteuid(pw->pw_uid) will always fail.
But in this case, there's no need to call setegid, seteuid, and authorization should contine.

Possible fix (Not tested):

 if (getegid() != pw->pw_gid && setegid(pw->pw_gid) < 0) { 
     D (privs->debug_file, "setegid: %s", strerror(errno)); 
     goto free_out; 
 } 
  
 if (geteuid() != pw->pw_uid && seteuid(pw->pw_uid) < 0) { 
     D (privs->debug_file, "seteuid: %s", strerror(errno)); 
     goto free_out; 
 } 

@Maryse47
Copy link

Since kscreenlocker is running as normal user

The problem is challenge file isn't accessible for normal users. You need to either make it accessible or make kscreenlocker privileged.

@surmish
Copy link

surmish commented Sep 27, 2024

is there a user-friendly workaround for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests