Using a Yubikey as smartcard for SSH public key authentication
undeadly.org
undeadly.org
The app I wrote includes Python ctypes bindings for all three implementations (https://github.com/pyauth/exile/tree/master/exile/scard, and https://github.com/pyauth/exile/blob/master/exile/ykoath contains an example of how to use them). Hopefully these will be useful to others writing YubiKey-based applications.
I should add, there are other YubiKey modes (like U2F) that use the USB HID protocol instead of the USB PCSC protocol. For those, someone at Google wrote this library: https://github.com/google/pyu2f which provides similar capabilities for HID-based protocols. It similarly interfaces directly with the system-provided HID API using ctypes.
Definitely! HMAC-SHA256 is nice and I was wondering if the TOTP feature of Yubikeys can be (ab)used for anything else that also uses HMAC-SHA256 (e.g. Macaroons).
I'll take some time to digest your code, thanks!
The SSH public key auth method goes like this:
1. Client "I want to do SSH public key auth. I can prove I know the corresponding private key for key X" 2. Server (typically checks authorized_keys file to decide) may say "OK, yes, prove that" 3. Client signs per session data with key to prove possession [it may use the proxy technology to have this done by a different client].
But a FIDO2 / CTAP key needs things to go the other way around
1. Client "I want to try FIDO2" 2. Server "OK, here is a Cookie. Can you prove you know the associated private key?" 3. Client uses CTAP protocol to verify that the Yubikey recognises this cookie and gets back a proof, sends it to server.
In the current world SSH clients know which keys they know, so they can begin by telling the server, but in the FIDO world the Security Key is deliberately too dumb to even know this, it has to be prompted with a cookie.
This is because of a correlation attack [edit: maybe that's the wrong word? The attack is a bad guy figures out who you are based on seeing you connect with this key in many places], which was not considered a big threat for SSH but is clearly a problem on the Web. So FIDO SecurityKeys are engineered to resist correlation by being so dumb that even they don't know if they know your Facebook keys, until Facebook says "Hi, do you know the keys that go with this cookie?" when you try to log in as you.
You can somewhat defend against correlation attack in SSH if it worries you by the way, by explicitly configuring a particular public key for each connection and forbidding the client from trying other keys (which it will by default) using IdentitiesOnly and IdentityFile in OpenSSH.
In fact RFC 4256 pretty much spells out what it's for, it lets you use PAM to augment your authentication policies by changing what the remote user types into their console. You can add a One Time Password check or whatever.
It is full of requirements like "A command line interface (CLI) client SHOULD print the name and instruction (if non-empty), adding newlines" which have nothing whatsoever to do with the actual problem for Security Keys.
Of course you could _add_ a new SSH authentication method, but the existing RFC 4256 "challenge-response" approach is completely inappropriate.
With that said, I suspect it could be retrofitted for this purpose.
On occasion I've un/re-plugged to convince myself that it really is secured. (I do use a passphrase too, but I've already entered it in a given session I can git/ssh/etc. even to new remotes without re-entering it. I don't think that's configurable to be per-remote, since I've unlocked the 'card' (yubikey) for that session.)
Considering the “normal” threat model for AWS IAM keys, where the keys are stored in ~/.aws/credentials, they’re vulnerable to: (1) malicious/compromised apps/scripts on the local workstation, (2) theft of the laptop if it’s unlocked/decrypted. Moving the keys seems to solve (1), but degrades (2) by making it “theft of the yubikey”.
I’ve seen other systems that move the AWS secret keys to the OS keychain (for example https://github.com/99designs/aws-vault ), which seem to harden against (1) without weakening (2).
Is there a mitigation I’m not taking into consideration?
1. YubiKey's OATH application can be protected with a password. If you can't unlock the YubiKey with a password, you can't access any OTPs (or "OTPs" in exile, where they're being used as HMAC keys instead). (Granted, exile does not directly integrate with this yet, nor even mention it - thanks to you, I'll add it to the readme ASAP)
2. The YubiKey is an HSM, which means it can't be duplicated. As soon as you find your laptop/keychain stolen (which is much easier than detecting that the contents of your home directory have been copied) you can revoke the AWS API keys.
3. I consider a hack and theft of my home directory contents to be more likely than physical theft of my YubiKey (which I believe for most people is either permanently inserted into their laptop, or on a physical keychain). This risk calculus may be different for you.
4. As you point out, the attacker would need to know how to make use of this (as yet) fairly obscure use of the YubiKey.
this seems like such an overwhelmingly common use case I dont understand why yubico doesnt make this as frictionless as possible. i understand that the smart card spec is probably a hindrance, but still..
but its still on my (physical) keychain, looking forward to trying your non-gpg workflow. thanks for posting.
I also got GPG agent forwarding to work transparently and with improved security by forwarding a dynamically created unix socket instead of a TCP socket. It allows me to do remote code signing, as well as chain through a bastion host.
Aside from jamming up with ansible occasionally, the setup is reliable.
I've documented the process for my own reference as much as I could here (yep, a fifth guide): https://github.com/naggie/dotfiles/blob/master/etc/yubikey.m... -- see functions.sh in the same repository for some mechanisms to automatically manage gpg-agent and the sockets without getting deadlocked.
I hope someone finds this useful. I'll certainly be trying the opensc method here though, out of interest.
Do you have a strong opinion on `on` vs `fixed` ? I tell myself that I should use fixed but haven't bitten the bullet yet.
Also I further mitigate the risk by having an explicit wrapper (gssh) to be selective about when I forward GPG/SSH agent.
I found that forwarding the scdaemon socket is more reliable. I configure GPG on the remote machine to use netcat as scdaemon.
To get started, you need the following packages:
ykpers (library and tools to program Yubikeys)
yubico-piv-tool (Yubico Personal Identity Verification (PIV) Tool)
pcsc-lite (resource manager for PC/SC)
opensc (set of libraries and utilities to access smart cards)
And the first thing I thought was "sure to be a guaranteed cluster fuck."Can't there be a better way already? We all know sec is a big deal. Don't we?
The specific "smartcard" protocol that Yubico uses for this functionality is well-supported by the three major operating systems, though (winscard is a standard library on Windows, PCSC.framework is standard on Mac OS, and libpcsclite is available on Linux by installing pcscd/pcsc-lite).
I recently implemented a library (https://github.com/pyauth/exile) to use Yubikeys to sign AWS API requests, which required writing a Python ctypes API to talk to these libraries. It turned out to be fairly easy once I threw away the idea that I should rely on any of the libraries you listed, and just started talking via the winscard/PCSC protocol directly.
If anyone wants to write something similar for this application, the ctypes bindings are in https://github.com/pyauth/exile/tree/master/exile/scard, and https://github.com/pyauth/exile/blob/master/exile/ykoath contains an example of how to use them.
Actually there is one pain point: every time I install a new system I have to remember to install the right packages and udev rules to be able to communicate with my yubikey from gnupg as a non-priviledged user.
But once it works it just works and it's a significant quality of life and security improvement.
Other stuff you can do with smartcards https://github.com/EnigmaBridge/javacard-curated-list
Once you have them use these guides to install
https://github.com/philipWendland/IsoApplet/wiki/Installatio...
https://github.com/philipWendland/IsoApplet/wiki/Initializat...
Be sure to set the Yubikey to require touch.
As a side note, the author writes:
> GnuPG's user interface is a disaster
Well, I'd say the procedure described in the article is a strong contender, too :-)
Envisioned setup would entail: download (custom) `libsolo-pk11.so`, generate RSA or ECDSA key on the USB key, get public key via `ssh-keygen -D libsolo-pk11.so`, use via `ssh -I libsolo-pk11.so user@example.com`.
The equivalent thing can be done for TPMs with simple-tpm-pk11 [1] today.
Technically, I'd extend the FIDO2 CTAPHID transport with "vendor commands" [2] mapping the basic Cryptoki API, and call that from the custom PKCS#11 shared library, which is then just a simple shim/wrapper. No additional drivers needed (everyone has HID).
Issues I can foresee: Users too attached to GPG workflow. Installation of custom shared library. No SSH support (via PKCS#11) for Ed25519 yet. SSH support for ECDSA only in about-to-be-released OpenSSH 8.0. Vanilla PuTTY on Windows has no PKCS#11 support. Bad rap of PKCS#11 due to existing vendors adding proprietary and closed source extensions. And the fact that SSH (currently) presents all keys to the host - I'd really like to be able to specify which key to use.
Personally, I'm a bit allergic to the GPG/PCSC/PIV/CCID way of doing things... My itch-to-scratch is just having a few keys off my computers (in particular, portable), and perform (infrequent) signatures on the separate device. And do this via a (comparatively) sane, open standard.
[0] http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/os/pkcs1...
[1] https://github.com/ThomasHabets/simple-tpm-pk11
[2] https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-cl...
Someone else seems to second lower-level standards as the best way [1].
Mostly using it on my Nexus 5. It is great, because using it by NFC with Open Keychain and k9 I do not need to place my private key on the phone. Additionaly that works also great to use the Yubikey to unlock the Phone and also using it on the Yubico Authentificator for the OTPs.
That keys are really great. Love them.
The only other Tool I would recomend with similar features is the Nitrokey (https://www.nitrokey.com/) but the Disadvantage is, that they really lack on some features. But maybe a good alternative for GPG and SSH.
The advantage of the Nitrokeys are, that in compare to Yubico products they use open hardware.
Hope this helps out some people.
And, for everybody who is struggling on the usage, belive me, I spend over four years making everything work and some really frustrating time reseting stuff, building keys, fu*... up big and recover Accounts :D
And with TermBot you can use Yubikey to login via SSH. Can come in handy in trouble.
GPG was a nightmare with it's own particular way of doing things and general refusal to help other projects.
Their scdaemon takes exclusive use of the card and when this has been brought up with the project, they said other projects should use their scdaemon to inferface with cards rather than PKCS11 and opensc.
scdaemon used to crash all the time, that doesn't happen anymore. GPG doesn't lock the card so I have to stop scdaemon to use it w/ other apps.
So for the last half year I've happily used gpg-agent/scdaemon also as SSH agent and it works really well without any issues.
But setting this up (w/ Ubuntu+Gnome) is still a ridiculous task:
- Ensure gnupg2, scdaemon, pinentry-gnome3 are installed
- cp /etc/xdg/autostart/gnome-keyring-ssh.desktop ~/.config/autostart/
- edit ~/.config/autostart/gnome-keyring-ssh.desktop and add "X-GNOME-Autostart-enabled=false"
- edit ~/.gnupg/gpg-agent.conf and add "enable-ssh-support"
Gnome session startup will read both the "X-GNOME-Autostart-enabled=false" and the "enable-ssh-support" and set up and start gpg-agent as ssh agent in the session. There are other ways to disable a .desktop file, but the String "X-GNOME-Autostart-enabled=false" has to be there for this to work.
When all this is set up usability is excellent. the system will even prompt to plug in the right yubikey when you ssh into something. No need to add/remove the card to/from the agent.
[0] https://wiki.gnupg.org/SmartCard#Known_problem_of_Yubikey
[1] https://github.com/Tharre/pkgbuilds/blob/master/arch-system/...
I recently implemented a library (https://github.com/pyauth/exile) to use Yubikeys to sign AWS API requests, which required writing Python ctypes bindings to call these libraries. It turned out to be fairly easy once I threw away the idea that I should rely on any of the intermediary libraries, and just started talking via the winscard/PCSC protocol directly.
I'm not even requesting that I as the issuer be able to subordinate those keys. Just make them work without making me want to shoot anyone who mentions the word "security".
The security folks whine that nobody does security, but they sure don't make it very easy to do so when someone wants to.
I believe Google sells a product, the "identity aware proxy", that is very much like what existed internally. I haven't used it, so am unsure. But it sounds great.
That pretty much describes every security token system I have ever seen. Sadly.
https://static.googleusercontent.com/media/research.google.c...
https://www.businessinsider.com/none-of-googles-employees-ge...
After the setup, things worked ok, but there were a few limitations that made me more happy with just having the key on my computer.
The primary was that I had no way to validate that the key material was encrypted at rest, and no documentation even appeared to make claims about how the key material was stored. My setup used a fairly long PIN to replace what would have been a fairly long password for decrypting the key material stored on my computer. I wasn't really comfortable with using something simpler as a PIN.
It may be the case that I could have leaned more on the hardware for security and told myself that the limit to the number of password attempts should allow for a shorter PIN to be used. But I was looking for something that I could add as another layer to my existing process, rather than something that replaced it.
At the end of the day, using a smart card to store key material just made it harder for me to reason about the security of the key material itself due to the increased number of unknowns. And it was more inconvenient.
[0] https://f-droid.org/en/packages/org.sufficientlysecure.termb...
[1] https://f-droid.org/en/packages/org.sufficientlysecure.keych...
I have Pass working but SSH was always a glaring missing piece of the puzzle. Now if only I can convince an SFTP client to do this, I'll be really sitting pretty.
Oh and the yubikeys nowdays are closed source. If you want actual open source hardware and software, checkout the Nitrokey Start. It's cheaper and fully open source, hard and software. Its an openpgp token: https://raymii.org/s/articles/Nitrokey_Start_Getting_started...
If you want a smartcard, Nitrokey had Both the pro and the HSM. An openpgp smartcard and and smartcard-hsm (just pkcs#11).
Short pin is fine because after 3 tries the token is locked.
On the other hand there are no limits with software keys.
It uses these 3 to consistently generate a password for websites:
1. A secret that I've pre-programmed in the YubiKey (+ 2 other backup YubiKeys)
2. A "pin code" (either provided by me, or in my case - protected by my TouchID)
3. The website's name
If you want to take a peek, I always appreciate feedback. https://github.com/noliran/ykpass
In the end, I have to use gpg-agent's PuTTY support, which means no command-line SSH, only a separate PuTTY window when I want to do SSH sessions, and using plink for SSH auth for Git.
You're just combining "something you have" + "something you have". Unlike with a Yubikey, your fingerprint will always be with you when you have your laptop.
Biometric access is a terrible idea if you don't combine it with "something you know". Access to your laptop can now be coerced or compelled at any time.
Every commercial biometrics system I've ever seen that's worth a damn at least combines it with a pinpad.
Or maybe the Teleport people can just make this as painless as possible.
Or for keybase to make it painless. Don't try to support everything. Just start with only supporting Yubikeys. Then you can expand.
I bet most people only buy 1 though
When you lose the yubikey you import the master keys from the usb drive and all your access is there. Then you revoke the keys and start over.