keepassxreboot / keepassxc

KeePassXC is a cross-platform community-driven port of the Windows application “Keepass Password Safe”.
https://keepassxc.org/
Other
21.33k stars 1.47k forks source link

Linux login manager & PAM integration for SSO #6055

Closed vorstrelok closed 2 years ago

vorstrelok commented 3 years ago

Summary

Not quite sure where to post this, I hope you'll forgive me if it's a wrong place. I've been using KeePassXC for a couple of weeks and I find typing my password 2 times on every login or screen unlock VERY inconvenient. I find https://github.com/keepassxreboot/keepassxc/issues/1404 and what is proposed by Q&A (use secret-tool to store password) not suitable, because:

  1. It requires running additional service for storing password just to store your KeePassXC DB password
  2. You can't use KeePassXC as you freedesktop secret service provider https://github.com/keepassxreboot/keepassxc/issues/1403

This issue has already been discussed here: https://github.com/keepassxreboot/keepassxc/issues/2797 and PAM integration will be needed for https://github.com/keepassxreboot/keepassxc/issues/3856 and https://github.com/keepassxreboot/keepassxc/issues/5991

Writing a PAM module would've been a proper solution, but it would require quite some time and learning. So I spent some time (around 4 days probably) for possible workarounds and I created one!

How it works

Upon login your user password is saved into your Linux user keyring (not to be confused with gnome or kde keyring!), then I have a service that monitors this keyring for a specifically named key and send this key via D-Bus call to running instance of KeePassXC. KeePassXC must be already running. End result is that is your KeePassXC will be automatically unlocked on login and screed unlock, while staying locked if your screen is locked. It is still a hack, but imo less hacky than using other secret service provider just for automatic unlock.

How to do it

It needs keyutils and d-bus packages but you probably already have them. Oh and I wrote in fish shell script, but porting to other shell should be trivial. Code is here: https://gist.github.com/vorstrelok/3b7a2b43c85e2b8b6cd3f81abe7a93fa

  1. Put keepassxc_pam.fish and keepassxc_sendpass.fish somewhere (I chose my home folder for now)
  2. Add this 2 lines to your /etc/pam.d/system-local-login or copy mine from the gist. auth optional pam_exec.so expose_authtok /home/vorstrel/keepassxc_pam.fish session optional pam_exec.so /home/vorstrel/keepassxc_pam.fish Do not forget to change /home/vorstrel (my home folder name) to a name of your home folder! $HOME will not work, it's too early in session creation to have this variable and PAM config is not a shell scripting language. Order of lines IS IMPORTANT, be sure to add each line after 'auth' and 'session' section like in my example! Also, if you completely mess your /etc/pam.d/system-local-login you probably won't be able to login, so be sure to have recovery usb lying around just in case. But you will probably be fine!
  3. Add keepassxc_sendpass.fish to your prefered service autostart method. I used systemd user unit, example in the gist. Do not forget to change /home/vorstrel to your home folder
  4. Done!

Future development

I will rewrite this in POSIX shell if there will be at least 3 users of my hack. If this post will get 10 likes I will consider writing a proper PAM module if I will be able to recall how to code in C. No promises tho! Hope my labour will be useful not just for me and help someone else too!

phoerious commented 3 years ago

This is pretty much out of scope. If anything, we could query the database password from the user's Gnome/KDE/macOS keyring, but then the whole security depends on the security of that and your login password is usually much less secure than your database password.

droidmonkey commented 3 years ago

I am absolutely against this integration. Quick unlock should solve most inconvenience imposed in a far more secure way. Agree that sharing the same security threshold as your computer account is poor practice.

phoerious commented 3 years ago

Also, Windows still uses NTHash, which basically MD4 of your UTF-16 password, so I would NEVER share a password with my password database on Windows.

vorstrelok commented 3 years ago

Also, Windows still uses NTHash, which basically MD4 of your UTF-16 password, so I would NEVER share a password with my password database on Windows.

But I want this feature for linux?

If anything, we could query the database password from the user's Gnome/KDE/macOS keyring

But if you use KeePassXC as your freedesktop secret service provider it won't work, because Gnome/KDE already provides freedesktop secret service! I mean, it creates circular dependency:

  1. Keepassxc DB password is stored in 'secret service'
  2. But you need to unlock Keepassxc to provide 'secret service'

I mean, I want to use KeePassXC as my keyring instead of Gnome/KDE etc. You already implemented freedesktop secret service to make it work. I use login password as my keepassxc db password. It is long and random and hard to guess etc. All that good security stuff. I just don't want to type it 2 times. Gnome/KDE keyring (that are supposed to be your password manager) do the very same thing that I propose, use your user account password or some other authentication (fingerprint) to unlock keyring.

When you use sudo or ssh into your computer, you use your login account password and not some other password, don't you?

I am no security or PAM expert, but afaik if one of the apps that you use on X11 linux is compromised, your computer is screwed. Installing keylogger or changing your .bashrc so the next time you sudo password is sent somewhere is trivial. To increase security you have to use Wayland based compositor & some form of LSM (AppArmor or SELinux) Writing PAM module will allow securely transfer your credentials to KeePassXC so it can't be spied upon other programs running as your user (in my understanding)

Quick unlock should solve most inconvenience imposed in a far more secure way.

Sorry if I missed something, but what do you mean by "Quick unlock"?

droidmonkey commented 3 years ago

I would think the whole reason you want keepassxc to be your secrets provider is that it's not coupled to your computer account like gnome keyring is. Similar to why you use keepassxc plus a browser plugin instead of storing passwords directly in the browser. The separation is part of the security model.

I'm actually not sure what we need to do since you already have a POC built.

vorstrelok commented 3 years ago

My current solution can't be considered a POC because it is a bunch of scripts to automatically and unsecurely send password to KeePassXC. POC can be something like a PAM module that will receive login password, launch KeePassXC via D-Bus or some other way if need be, and attach user's login password in form of a linux key (not to be confused with gnome/kde keyring) to a running KeePassXC. This way eavesdropping from other applications (even running as your user UID) is impossible, if I understood linux keyring manpage correctly. You can read more about this facility here: https://man.archlinux.org/man/keyrings.7 https://man.archlinux.org/man/keyctl.1

In this issue I wanted to ask if there is an interest in developing a proper integration and may be start developing it myself for inclusion in stock KeePassXC. You seem to be against it. Probably because you use 2 different password, one for login and another for keepass. I want one password, that is a promise of password manager, at least for me. Even thou I disagree with you, I can accept your decision. You are the maintainer after all. :smiley:

Thank you for developing KeePassXC, your program motivated me to finally move away from passwords stored in text files everywhere, I will continue to use it. :smile:

droidmonkey commented 3 years ago

I wouldn't be against someone doing this work and owning it. We don't want to maintain a PAM module specific to keepassxc. If there is a more generic PAM module that we can leverage that would be preferred. The communication plumbing should be similarly standard.

phoerious commented 3 years ago

KeePassXC isn't running when you are logging into your system via PAM, so we would need to store the hash in a kernel key ring and play it back or something (not so sure if that is a good idea), so I am not quite sure how this is supposed to work at the moment and how to keep the hash secure on a system where any application can impersonate any other. You could of course authenticate through PAM again once it's running, but that wouldn't be any different from where we're at already. Also keep in mind that Linux hashes passwords as SHA512. While that may be secure enough for most intents and purposes, it surely is a downgrade from Argon2.

michaelk83 commented 3 years ago

I would think the whole reason you want keepassxc to be your secrets provider is that it's not coupled to your computer account like gnome keyring is. ... The separation is part of the security model.

That really depends on the use case. In my case, I'm hoping to use KPXC as a drop-in replacement for KWallet, which hasn't been actively developed in years, suffers from a bunch of problems, and is effectively end-of-life (ref1, ref2). I also like the KPXC UI a lot more than KWallet, and I like that it's a Qt application, so doesn't add GNOME/Gtk or Mono dependencies.

Granted, this isn't entirely possible yet, since not all KDE apps have migrated to QtKeyChain yet (the ones that don't, still depend directly on KWallet), but I don't mind entering their passwords manually until they migrate. The general direction in KDE is to migrate to QtKeyChain (which supports libsecret as one of the backend options).

So my plan is:

  1. Set KPXC as the system keyring, and disable KWallet.
  2. Set up separate databases for the local passwords and more sensitive stuff.
  3. Encourage KDE to continue their migration to QtKeyChain.

I don't mind the local passwords DB to have the same password as my user account (and sudo, as aptly noted by OP), since I've been doing that for years with KWallet. Given KWallet's current state, that would still be an upgrade. And given the same password (which can still be quite strong), it would be a nice convenience to not have to enter it twice at login.

I've seen auto-unlock-on-login requested multiple times here, so I and OP aren't the only ones who want this. The usually proposed solution of using secret-tool and --pw-stdin won't work if KPXC is the secret service provider, as OP has explained.

The other database would, of course, still have a separate password, and would not be auto-unlocked.

michaelk83 commented 3 years ago

KeePassXC isn't running when you are logging into your system via PAM, so we would need to store the hash in a kernel key ring and play it back or something

I'm not quite sure how PAM works, but assuming that:

  1. The local passwords DB in KPXC has the same password as the user account.
  2. That password has to be entered to log in.
  3. It has to be entered again to resume a locked session.

Then I would think that it doesn't need to be stored anywhere (other than the mandatory /etc/shadow) for any longer than it takes to send it over DBus (or whichever) to unlock the passwords DB. Of course, if the DB is auto-locked after a few minutes, and then needed again, the password will have to be re-entered.

(Also worth noting that this should be disabled by default, and likely won't work anyway if the DB password is different from the user account. But it would still be nice to have that option.)

developer91234 commented 3 years ago

I think unlocking on startup is a great idea because typing in the long password every time is too much - but anything shorter is insecure. I use database chain unlocking to accomplish this but it's not a very elegant workflow.

developer91234 commented 3 years ago

I don't mind the local passwords DB to have the same password as my user account (and sudo, as aptly noted by OP), since I've been doing that for years with KWallet. Given KWallet's current state, that would still be an upgrade. And given the same password (which can still be quite strong), it would be a nice convenience to not have to enter it twice at login.

Root passwords are going to be weaker than the Keepass key. They are typed in far more often, so they need to be easy to type. The whole point of using PAM is I think to avoid having to type in the long Keepass passkey every login. But if the root password and the keepass password are the same, then that's going to be even worse because now you're going to have to type in a very complex password to do anything that requires root/login.

This is what I do right now - I just have a helper database to unlock the main db, then use a script to open the main and close the helper.

PAM should unlock some intermediate layer which will in turn unlock the keepass database on the machine. The login pass and the keeXC database pass should be independent of each other.

michaelk83 commented 3 years ago

If you're not sharing the DB online (e.g. backing it up to Google Drive), then having a helper DB with the user password, or having the main (but offline-only) DB with the user password, I think both cases have the same security. If the helper DB is compromised, so is the main one. And the point was, if your root password is compromised (which with sudo is usually the same as the user password), you have far bigger problems to worry about (and you have no way to protect the main DB in that case, anyway).

If you are sharing the main DB online, then yes, it makes sense to have a stronger passphrase on it, to protect it from outside your system. My approach for that is similar, but simpler: just have a separate DBs, and don't share the one with the user password.

developer91234 commented 3 years ago

So you keep the db's in sync somehow? I mean you can merge them manually every time, but who wants to do that?

michaelk83 commented 3 years ago

In my particular case, I don't have anything in the local DB that I need to sync to the main one. But sure, if you have a lot of stuff that needs to be in both places, then the helper DB approach may be more convenient.

danisztls commented 3 years ago

I don't care for passwords or encryption on KeepassXC side as I already have an encryption layer on top of anything and my local system is hardened. If I have to protect my passwords from my local environment it's game over already. KeepasXC is great but does not need this forced attrition. Also it does not make sense because unless you have a Yubikey you are probably using a low entropy password or a keyfile residing on your userspace.

phoerious commented 3 years ago

I don't care for passwords or encryption on KeepassXC side as I already have an encryption layer on top of anything and my local system is hardened.

If you don't need encryption, why do you use KeePassXC and not a notes manager or so? The point of KeePassXC is to encrypt your passwords. Everything else is added on.

Also it does not make sense because unless you have a Yubikey you are probably using a low entropy password or a keyfile residing on your userspace.

That's plain wrong. A simple passphrase can be very high-entropy and Argon2 prevents efficient bruteforcing. A key file can add additional protection for free, although a Yuibikey is of course the best option.

danisztls commented 3 years ago

If you don't need encryption, why do you use KeePassXC and not a notes manager or so? Everything else is added on.

No notes manager that I know of has the same features for managing password as KeepasXC has. :smile:

It's not that I don't want encryption. KeepasXC database is already under two encryption layers and having a third it's not an issue but just a nuisance as I have to unlock KeepassXC each time I open it. Some integration with Gnome Keyring would be nice.

phoerious commented 3 years ago

You cannot unlock KeePassXC with Gnome Keyring, but you can use it as a replacement for Gnome Keyring.

danisztls commented 3 years ago

What would be the rationality? Having Argon instead of SHA256? I suspect using this would lead to more integrations problems without solving any real issue.

Aetf commented 2 years ago

Putting aside whether using a PAM module to unlock KeepassXC is a good practice in terms of security or not, there are actually technical challenges implementing such a PAM module.

When I implemented the Fdo secret service provider in KeepassXC, automatically unlocking it using PAM was exactly the next step I planned to do next. But it turns out to be quite difficult if not possible to implement securely.

Fundamentally, the problem is that the PAM authentication process happens very early during user login. The user session doesn't even exist yet. So the PAM module has to find a way to store the password for a prolonged time until the user session is set up (with KeepassXC now running) and then unlock the database. This raises this question:

How do you guarantee that you only give the password to KeepassXC, not something else happens to start quicker than KeepassXC and pretend to be KPXC?

This rules out the possibility of directly using the kernel keyring:

The current implementation in Gnome keyring and KWallet work around this problem by using an IMHO ugly hack roughly like the following:

The assumption is that we only trust a program we started ourselves. This trust model is also used in Wayland compositors, where certain privileged programs such as input methods are started by the compositor.

In this case, the keyring service is no longer a normal service managed by systemd or the DE's auto start mechanism. That's why I call it a hack and don't want to pursue it further. But if anyone else is interested, so far I feel replicating something like the above is the best we can do.

danisztls commented 2 years ago

@Aetf Thanks for the explanation.

michaelk83 commented 2 years ago

Assuming such a PAM module is specific to KPXC, would it not be possible to set up some sort of encryption scheme (key pair? TOTP?) and/or communication protocol, so that only KPXC can read the password successfully? So that if another process attempts the same, it either fails to get anything, or only gets an encrypted password. Not because the other process is untrusted, but because it lacks some sort of shared secret.

This may also be related to Linux fingerprint support / QuickUnlock, because those features share a similar secure storage problem. Essentially, what we want to happen here is roughly analogous to the PAM module saving the password for QuickUnlock, and then when KPXC launches, it automatically would initiate the QuickUnlock. But the difference is that actual QuickUnlock has an extra security factor (user PIN / fingerprint), and here we don't (or at least not one that should require another user interaction).

And that also reminds me a related use case - what if a user wants to log in to the session using the fingerprint PAM module, and then use that to automatically unlock KPXC?

Aetf commented 2 years ago

Assuming such a PAM module is specific to KPXC, would it not be possible to set up some sort of encryption scheme (key pair? TOTP?) and/or communication protocol, so that only KPXC can read the password successfully?

Not sure how this would work, given everything is readable by the user. So you can't embed any private secret in the program or the PAM module.

Automatic login or fingerprint unlock or anything that doesn't involve a password are not supported by Gnome keyring or KWallet. For KPXC I'm also not sure how to work around that.

michaelk83 commented 2 years ago

Not sure how this would work, given everything is readable by the user. So you can't embed any private secret in the program or the PAM module.

That's true. I was thinking that if it was somehow generated algorithmically, like a TOTP, then there won't be much to read, other than the binary code (or source code on github). It would have to be a purpose-built malware, and IIRC there was an argument that once the userspace is compromised with such malware, it's game over anyway.. But if the encryption is too weak, the password can be brute-forced without any specialized malware like that. A strong encryption would still require some sort of entropy source, which is most simply some sort of key file. Which brings us back to square one, so I guess that's not useful.

For the fingerprint SSO, the fingerprint becomes the password, I guess. So probably, the fingerprint reader PAM module needs to somehow pass that data to KPXC's PAM module, and then the latter would take over from there as usual.

But honestly, all of this is above my pay grade, so I'm just throwing ideas.

droidmonkey commented 2 years ago

Negative, a fingerprint is an identity (at best), aka username. You can use a fingerprint as a second factor to access a secure crypto store (similar to what Windows Hello and TouchID do), but you cannot use it as a password. Most fingerprint readers do this local to the reader, they then turn around and do FIDO2 with whatever is requesting it.

michaelk83 commented 2 years ago

a fingerprint is an identity (at best), aka username

Usually, yes. Yet somehow people use it to unlock their session, do they not? (If they choose to configure it that way.) Maybe that's more akin to a passwordless login with the username replaced or verified by the fingerprint, but from the user's perspective the result is as same as if their fingerprint acted as a password. (edit: Or did you mean there is some sort of key file stored on the fingerprint reader, so the fingerprint is used to access that, and then the key file is used as the password? Even if so, that's still transparent to the user.)

Regardless, whatever data that comes from the fingerprint PAM will need to find its way to the KPXC PAM (once that exists), and be used there in whichever way it needs to be. Or something like that.

But before that, there's still the bigger issue that Aetf raised above.

droidmonkey commented 2 years ago

Closing this per Aetf's excellent feedback:

When I implemented the Fdo secret service provider in KeepassXC, automatically unlocking it using PAM was exactly the next step I planned to do next. But it turns out to be quite difficult if not possible to implement securely.

Fundamentally, the problem is that the PAM authentication process happens very early during user login. The user session doesn't even exist yet. So the PAM module has to find a way to store the password for a prolonged time until the user session is set up (with KeepassXC now running) and then unlock the database.

michaelk83 commented 2 years ago

That's why I call it a hack and don't want to pursue it further.

@Aetf , how about this, inspired by #6458 :

  1. The PAM module would come with a client authorization file set to root:root 600 (rw by root only). This prevents unauthorized clients from tampering with this file.
  2. When KPXC is installed or upgraded, the system admin has to update this file (can be handled by the installer?), e.g.: sudo sha256sum /absolute/path/to/keepassxc >> /etc/keepassxc/pam/clients This produces a line in the form <hash of binary> /absolute/path/to/keepassxc.
  3. During login, the PAM module saves the password e.g. in kernel memory, and waits.
  4. KPXC is launched as normal (SystemD, Autostart, etc), and asks the PAM module for the password.
  5. The PAM module detects the binary path and hash of the requesting process, similar to #6458 , and compares against the authorization file. If it finds a match, it returns the password, otherwise it refuses.
  6. Optionally, the PAM module deletes the password from memory and shuts down after some timeout period.

The path and binary hash of KPXC is public knowledge, so it doesn't need to be hidden, but it's not something that another process can easily reproduce. As long as the authorization file is protected, I think this should work?

droidmonkey commented 2 years ago

There are a few people asking for PAM integration and absolutely zero people willing to code it. I certainly have no appetite to review the code, test it, and understand the myriad of potential security issues that can be had depending on each distribution. Just let this die please.

Aetf commented 2 years ago

What @michaelk83 said sounds like a plan. But I agree with @droidmonkey that we should close this. People who want this can totally create a PAM module outside of KPXC repo. There's no need to host PAM code here I think.

michaelk83 commented 2 years ago

There's no need to host PAM code here I think.

Agreed.

There will still need to be the bit that polls the password from the PAM module, but that's minor. Depending on how QuickUnlock will eventually be implemented on Linux ( #5991 ), it might be possible to reuse (some of?) that code path, even. But yes, the main PAM module code doesn't need to be touched by KPXC team at all (and isn't even specific for KPXC).

Patricol commented 3 months ago

I doubt this is enough to re-open the issue; but my use case isn't subject to nearly any of the criticism leveled at this proposal.

I'm using KeePassXC exclusively as a replacement for KWallet/GnomeKeyring, specifically for ssh-agent, secretservice, and git (git-credential-keepassxc). I do not and will not use it to store any other passwords. I imagine users who do use KeePassXC as their primary password manager could just create a separate database to emulate my use case.

With its user-confirmation functionality for secretservice; KeePassXC is more secure than KWallet and GnomeKeyring.

PAM integration that securely achieves the goal of unlocking secretservice daemons using a login password may seem like a kludge because of the circumvention of systemd, but it's actually secure for users who cba to enter a separate (and thus likely less secure than login) password right after every login. Those users will insecurely use GnomeKeyring etc. to store the KeePassXC password that guards all of their primary passwords; creating some real risk. Much more real than if they just set their login password to match their KeePassXC password and used a 'kludgey' pam integration.

In summary, I believe even a kludgey pam integration would significantly improve security for users who attempt auto-login when considering that those users are going to settle for insecurity (often without realizing) rather than give up. I also present a use case where KeePassXC with a kludgey pam integration would be more secure than the standard usage patterns of the widely used KWallet/GnomeKeyring (which use the same kludgey pam integration).

m00nwtchr commented 1 month ago

Started working on something here: https://github.com/m00nwtchr/pam-keepassxc