Version $Id: yubikey.html,v 1.16 2018/06/28 08:50:19 madhatta Exp $
The yubikey
is a small USB dongle from
Yubico which generates one-time
passwords (OTPs) and pretends to be a USB
keyboard in order to enter the OTP into
the keyboard datastream. I found out about them by chance - I can't remember how -
and decided to buy one for experimentation. A major feature is that,
having neither a real-time clock nor a display and thus needing no batteries
either, they're really rather cheap. Including postage, mine cost less
than £20, and you definitely won't get a SecurID dongle for that.
Also, all the yubikey back-end software is generally available under GPL or other free licences, so you generate the secrets for your tokens, you load them onto your tokens yourself, you protect them as you see fit, and you validate them on the back-end as seems best to you. In essence, the security is your responsibility, not someone else's. I regarded that as a major nice-to-have until RSA screwed the pooch by probably losing the master list of secret seeds for their SecurID tokens, at which point control became a must-have. Whilst RSA is still refusing to say exactly what they lost, at least one major secure customer was compromised as a result. So I reiterate: it's always better to be in control of your own secrets. If you trust someone else to look after them, this trust may be unjustified or - even worse - you may find they won't tell you whether it was unjustified or not. |
I say "more-secure" not "secure" in the title because it looks as if it'll still be single-factor authentication, as right now not all methods of validating the yubikey OTP support the use of a personal PIN as well. But yubikey authentication is still much better than straight username-password as the dongle is not easily copied, and the OTP data is, well, only usable once.
Not that this is a major issue, but I must confess that another attraction of the yubikey is that, it being lightweight, thin, and waterproof, I can wear it around my neck like a sort of missile key or digital dog-tag. Geek marine! Semper pi(nguis)!
Fast links to:
The yubikey uses an AES key to generate one-time passwords with a unique identifying nonce, two counters and some timer-based salt. You plug it into your USB port; the hosted system thinks it's a USB keyboard. When an OTP is required you place your bare finger gently on the teeny touch pad for a second or so, and it injects the next OTP into the keyboard stream, just as if you yourself had typed it. That makes it very easy to use with any application that takes password data, whether CLI, web client, or a custom client like PuTTY or TOAD or system-config. The back-end has to do the work of authenticating the OTP; the front-end can be very general. It's clever.
An important design feature is that the yubikey is write-only as far as the AES key is concerned. The yubikey will happily sit there and give you OTPs created with the key until the counters wrap round, but it won't give the key back to anyone. Therefore, if you install a key not known to the yubikey's user, the user can't easily produce a second device that will generate a similar OTP stream.
The yubikey comes preloaded with an AES key known to yubico, and if you plan to take advantage of their internet-accessible authentication infrastructure you may wish to leave it there. It's also perfectly possible to run your own authentication infrastructure, and if you plan to do that, you should generate your own secrets and write them to the yubikey. Or you can do both:
I'll explain this in more detail later, but one nice wrinkle of the v2
yubikeys is that they support two profiles, which
I shall refer to as slot-1 and slot-2. In
use, these are differentiated by length of touch on the sensor; a quick
press generates a token from the slot-1 data, a press of 3-4 seconds
generates one from slot-2 data. Their website doesn't make clear, but
their tech support confirms, that both slots can be in OTP mode. I intend
to use slot-1 myself; I'll keep the AES key secret, and build my
own authentication servers. But I intend to upload slot-2's AES key to
yubikey, and use the infrastructure they provide when authenticating to the
world.
RTFM; the manual's at
http://yubico.com/files/YubiKey_manual-2.0.pdf.
The tools to install my own secrets onto the key were already in the
Fedora 12 repository, which was a pleasant surprise. I did a
I want a secret key in slot 1, for my use, and a key to be
uploaded to yubico for public use in slot 2. Having had a nice chat
with tech support, it was clear that there's no way at this time to
move the yubico-preinstalled key from slot 1 to slot 2 (but keep an eye on
this forum thread).
So for now, it was clear that I had to put new keys in
both slots. Since I had a working key in slot 1, I decided to start by
trying to program slot 2.
For reference, here's some test output from my (yubico-provided)
key in slot 1:
Specifically, I tried to put a key on-board with
Ah, OK, that's what STATIC_TICKET meant. How do I turn that
off?
Well, that's all very well, but it's shorter than the standard output
the pre-configured slot 1 gave me, which you can see above. Since this is
the slot I plan to use with the yubico servers, I'd better make it have the
same format. How about
No, that doesn't look right, yet. By mistake, I nearly overwrote the
key in slot 1 and discovered that the default config_flags for slot 1
were empty. So I tried to turn them all off for slot 2, with
I then repeated the exercise for my two slots using strong AES keys, which
I generated with
I uploaded my yubikey at the above link, waited five minutes, and used
the demo page to confirm that they'd got it just fine.
At
the wiki,
yubico say that
Clavid
provide a yubikey-enabled OpenID service. I went to
their signup page and
signed up very quickly using my slot-2 key and the username madhatter. I then put the
following code fragment at the top of
my main webpage.
Note to self: clavid's management portal is at
https://www.clavid.com/portal, to which I may (sensibly) also
authenticate with my yubikey.
The PAM module came from
http://www.securixlive.com/yubipam/download.php
and doesn't appear to be under any real development at the moment. That
provides the server-side bit and it's licensed under GPL.
I unpacked it, installed the pam-devel package, did a
./configure && make then a
make install as root, and followed the rest of
the instructions in the
INSTALL file in the distro as regards adding a yubikey auth group to
group-own the /etc/yubikey file, and sgid'ing the check binary.
As per the README file in the distro, I changed my
/etc/pam.d/sshd from
I added my password to the yubikey file with
I'm definitely in the database, and replay attacks definitely don't work
(as they most definitely should not):
I could have used ykpasswd without the actual key to hand
if I knew the public and
private UID strings, in hex. From the output above,
I found that the public UID (00 00 00 89 87 3d) is the same as my modhex
fixed string (ccccccjkjiet) using
yubico's modhex calculator. From this I
presume that
I created a local guest user and became him to avoid any issues with
SSH agents, identities, etc. Then I did
I found that I also had to enable ChallengeResponseAuthentication
in /etc/ssh/sshd_config with
Then I got success:
I tried a reply attack by pasting the OTP into a text buffer and presenting
it twice, the second time I got:
Yubico also provide a PAM implementation at
http://code.google.com/p/yubico-pam/wiki/YubikeyAndSSHViaPAM
but this authenticates off yubico's central server, which is not desirable
in this application. Shame.
Having done the above, changing /etc/pam.d/sudo to start
On my colocated box, I don't currently use sudo. I'd like to, but I
don't want sudoers to have the option to use password authentication; the
yubikey will be mandatory. In this case, I made a copy of
/etc/pam.d/system-auth called /etc/pam.d/system-yubiauth,
then deleted all non-auth lines
and commented out the following line in /etc/pam.d/system-yubiauth:
Now, if a user prompted for a yubikey OTP just hits return, the
sudo fails instead of passing him/her to password authentication.
Squirrelmail plugin at
http://code.google.com/p/yubico-squirrelmail-plugin/, also under GPL2.
Putting my own AES keys into the yubikey
yum install ykpers
and they were installed. In case your repository doesn't have them, they
came from
http://code.google.com/p/yubikey-personalization/
and are under the BSD licence.
cccccccbkuctvnckbcrfllkgerjcetnufdedutdffuvv
cccccccbkuctfhekfubctlrvbcljutlhthbirnnhjlri
cccccccbkucthuecfihvlfcuefjtrnlghutkddbendee
so I followed what I thought was the right incantation to put a key in
slot 2. These have to be done as root, by the way, since arbitrary access
is required to the USB device.
[root@risby]# ykpersonalize -2 -a 9349f5c8bbb7f3b4016039e6094b3f01 -o fixed=vvnbfekh
Firmware version 2.1.1 Touch level 1793 Program sequence 1
Configuration data to be written to key configuration 2:
fixed: m:vvnbfekh
uid: h:000000000000
key: h:9349f5c8bbb7f3b4016039e6094b3f01
acc_code: h:000000000000
ticket_flags: APPEND_CR
config_flags: STATIC_TICKET|STRONG_PW1|STRONG_PW2|MAN_UPDATE|OATH_FIXED_MODHEX1|OATH_FIXED_MODHEX2|OATH_FIXED_MODHEX
Commit? (y/n) [n]: y
after which I tried pressing the button for three seconds, and nothing came
out. I found quickly that you have to unplug and replug the key after a
programming exercise. Then I got:
VVn25ekhgitnhdndlfujijubvighjdebtjdgicvj
VVn25ekhgitnhdndlfujijubvighjdebtjdgicvj
[root@risby]# ykpersonalize -2 -a 9349f5c8bbb7f3b4016039e6094b3f01 -o fixed=vvnbfekh -o -static-ticket
Firmware version 2.1.1 Touch level 1859 Program sequence 3
Configuration data to be written to key configuration 2:
fixed: m:vvnbfekh
uid: h:000000000000
key: h:9349f5c8bbb7f3b4016039e6094b3f01
acc_code: h:000000000000
ticket_flags: APPEND_CR
config_flags: STRONG_PW1|STRONG_PW2|MAN_UPDATE|OATH_FIXED_MODHEX1|OATH_FIXED_MODHEX2|OATH_FIXED_MODHEX
Commit? (y/n) [n]: y
which gave me output like this:
VVn25ekhbnudvedjtdegideltebhfbtidbthigin
VVn25ekhnvjgrrfvhvuhnuvgitdlvcbcjblcblft
VVn25ekhlnndnbvekdjnuifurukhijbcjfjnibbb
[root@risby]# ykpersonalize -2 -a 9349f5c8bbb7f3b4016039e6094b3f01 -o fixed=vvnbfekh -o -static-ticket -o send-ref
Firmware version 2.1.1 Touch level 1795 Program sequence 3
Configuration data to be written to key configuration 2:
fixed: m:vvnbfekh
uid: h:000000000000
key: h:9349f5c8bbb7f3b4016039e6094b3f01
acc_code: h:000000000000
ticket_flags: APPEND_CR
config_flags: SEND_REF|STRONG_PW1|STRONG_PW2|MAN_UPDATE|OATH_FIXED_MODHEX1|OATH_FIXED_MODHEX2|OATH_FIXED_MODHEX
Commit? (y/n) [n]: y
which gave me
!VVn25ekhlldbdiejvfduvvjgrhlgljgtcgvjgeth
!VVn25ekhudrdbffbrgtkknlgidbujurklvdltfje
[root@risby]# ykpersonalize -2 -o fixed=vvcccccccccc -a 00000000000000000000000000000000 -o -static-ticket -o -strong-pw1 -o -strong-pw2 -o -man-update
Firmware version 2.1.1 Touch level 1795 Program sequence 3
Configuration data to be written to key configuration 2:
fixed: m:vvcccccccccc
uid: h:000000000000
key: h:00000000000000000000000000000000
acc_code: h:000000000000
ticket_flags: APPEND_CR
config_flags:
Commit? (y/n) [n]: y
and, mirabile dictu, that seems to have done it:
cccccccbkuctnftgflceklebrflklrkdgvrehvkcjrgj from slot 1
cccccccbkuctfntgdiehdjegckvibievdrrlngbiluki from slot 1
vvccccccccccvubjibchdivdekfitklicrevrtlckrbu from slot 2
vvccccccccccuclbbhkdkrdhrllekdfujrjduttlgbkj from slot 2
dd if=/dev/random bs=1k count=1|sha1sum
and which I don't intend to post here. I did use a fixed field
starting with "vv" for slot 2, the one I intend to share with yubico, which
they enable you to do
here. I also added the
-o uid=0123456789ab field when generating my "strong" key in slot
1, just in case leaving the UID field full of zeroes weakens the crypto
(but using 12 random hex digits, not the ones above).
Using my slot-2 key to authenticate to public servers
I use OpenID to authenticate to livejournal. Coincidentally, I discovered
that my browser had forgotten the login credentials I use to authenticate
to my current OpenID provider.
<link rel="openid.server" href="http://www.clavid.com/provider/openid">
<link rel="openid.delegate" href="http://madhatter.clavid.com">
and told LJ that I wanted to authenticate as www.teaparty.net, as I usually
do. I promptly got shunted off to the Clavid please authenticate using
your yubikey page, supplied my slot-2 key
with a long press, and hey presto! I was reading my friends'
LJ postings. Tip of the hat to Clavid: thank you!
Using my slot-1 key to authenticate to my own servers
Using sshd
#%PAM-1.0
auth required pam_sepermit.so
auth include password-auth
account required pam_nologin.so
[...]
to
#%PAM-1.0
auth required pam_sepermit.so
auth sufficient pam_yubikey.so verbose_otp
auth include password-auth
account required pam_nologin.so
[...]
[root@risby pam.d]# ykpasswd -a --user madhatta -k abcabcabcabcabcabcabcabcabcabcab -o here i supplied a slot-1 OTP
Adding Yubikey entry for madhatta
Using public UID: 00 00 00 89 87 3d
Using private UID: 01 23 45 67 89 ab
Completed successfully.
[madhatta@risby madhatta]$ ykvalidate --user madhatta ccccccjkjietjvfrcvvbvrdllrggjgdkkjvtbkddbtjc
OTP is VALID.
[madhatta@risby madhatta]$ ykvalidate --user madhatta ccccccjkjietjvfrcvvbvrdllrggjgdkkjvtbkddbtjc
OTP is INVALID!
ykpasswd -a --user madhatta -k abcabcabcabcabcabcabcabcabcabcab -f 00000089873d -p 0123456789ab
would have worked just as well, though I have not tried it.
[guest@risby ~]$ ssh madhatta@risby
madhatta@risby's password:
provided the OTP password, but got
Permission denied, please try again.
while /var/log/facility/authpriv Mar 8 09:24:22 risby yk_chkpwd[22644]: password check failed for user (madhatta)
Mar 8 09:24:22 risby unix_chkpwd[22645]: password check failed for user (madhatta)
Mar 8 09:24:22 risby sshd[22641]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=risby.home.teaparty.net user=madhatta
Mar 8 09:24:24 risby sshd[22641]: Failed password for madhatta from 192.168.3.11 port 59028 ssh2
# Change to no to disable s/key passwords
ChallengeResponseAuthentication yes
#ChallengeResponseAuthentication no
[guest@risby ~]$ ssh madhatta@risby
Yubikey OTP: ccccccjkjiethrubinjedfgcbntgrfjjbfkdditlerbc
Last login: Mon Mar 8 10:28:42 2010 from risby.home.teaparty.net
[madhatta@risby ~]$
[guest@risby ~]$ ssh madhatta@risby
Yubikey OTP: ccccccjkjiethrubinjedfgcbntgrfjjbfkdditlerbc
Yubikey OTP: ccccccjkjietviinkkidricrbktviivuhikutjterlub
Last login: Mon Mar 8 10:29:40 2010 from risby.home.teaparty.net
[madhatta@risby ~]$
Note how the first OTP, which is the one from the previous example retried,
simply fails silently; only a new, valid OTP succeeds.
Using sudo
#%PAM-1.0
auth sufficient pam_yubikey.so
auth include system-auth
...
makes sudo work happily with OTPs, which is extremely useful for me.
#auth sufficient /lib/security/$ISA/pam_unix.so likeauth nullok
and changed the start of /etc/pam.d/sudo to read
#%PAM-1.0
auth sufficient pam_yubikey.so
auth include system-yubiauth
account include system-auth
...
Using squirrelmail
MORE NEEDED. SCRATCH PAD STARTS: