Two-factor SSH authentication with U2F hardware security key

Standard

I’m shocked at the lack of documentation on using a U2F security key for two-factor SSH authentication. Luckily, it isn’t too difficult, thanks to the fact that Yubico has done a lot of the hard work for us.

A prerequisite for this guide is compiling and installing the pam_u2f.so module. Luckily, there is a fair amount of documentation online on how to do this. You’ll also need a system that can run the u2f-host command. Instructions for getting set with these are here and here, respectively. You will need both of these for both the server andclient.

If you are working with a remote system which you do not have physical access to, I recommend making sure you have a backup SSH session open at all times, as failings in the SSHd or the PAM configuration can cause you to be locked out. You are warned.

Requirements
First, come up with a unique name for the system you wish to SSH in to. This doesn’t have to be wholly unique, just make sure it doesn’t collide with anything else on the key, really.
For this example, we’ll use backupserver.
You’ll also need to know which account you wish to secure. For this example, we’ll use root.
For this tutorial, I used a MacOS X system to generate the key and responses, and secured a CentOS 7 system. Instructions should be easily adaptable to other operating systems.

Registering the key
We now need to register a new key with your U2F device. In order to do this, we’ll use pamu2fcfg.

On the system with the U2F device connected, run the following command:
pamu2cfg -o pam://backupserver -i pam://backupserver -u root
Make sure to change ‘backupserver’ and ‘root’ to what you decided earlier.
Your U2F device should then start flashing. Touch it to continue.
After you’ve touched the device, you’ll be left with something similar to this on the command line:
root:cCaQUJyqmU68z6KVAdpyk2871wuRVtgDbXCKq5A8zqBj577vdUhdLKeOQG4l9yG-t7Ze8wgtsdF7l0GEjO0g-A,04f32cb3dd0b0b1ac20517050ab1dd2700f410f638675c7ebe18b9607459171c8b82de6d1a1d5d25429157db43943033b741c0c376c375ce460628bd7464677fb4
This is the U2F key definition. The first part is the username the key is for, and the second part contains both the key handle and the user key. These are seperated by commas.

Configuring the U2F definition
Now login to the server you are wanting to protect, and execute the following command, making sure to replace the data with the output you got from the above command (in quotes). Example:
echo 'root:cCaQUJyqmU68z6KVAdpyk2871wuRVtgDbXCKq5A8zqBj577vdUhdLKeOQG4l9yG-t7Ze8wgtsdF7l0GEjO0g-A,04f32cb3dd0b0b1ac20517050ab1dd2700f410f638675c7ebe18b9607459171c8b82de6d1a1d5d25429157db43943033b741c0c376c375ce460628bd7464677fb4' > /etc/u2f_mappings

This will create a file which we’ll use to tell the PAM module to find your key information.

Configuring SSH
Next, let’s prepare the SSHd configuration. We have to ensure to turn on ChallengeResponseAuthentication and we must make sure SSHd is set to use PAM.
Open up /etc/ssh/sshd_config using your favourite editor.
Make sure to set the following:

ChallengeResponseAuthentication yes

It is probably already defined, so search for it and set it to Yes, or uncomment it.
And also make sure UsePAM is set to Yes.

UsePAM Yes

Now reload SSHd:

systemctl reload sshd

Configuring PAM
Next we need to modify the PAM SSH configuration. Open up /etc/pam.d/sshd. It should look a bit like this:

#%PAM-1.0
auth required pam_sepermit.so
auth substack password-auth
auth include postlogin
account required pam_nologin.so
account include password-auth
password include password-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open env_params
session optional pam_keyinit.so force revoke
session include password-auth
session include postlogin

Under:

auth substack password-auth

Add the following, replacing backupserver with the name you chose above:

auth required pam_u2f.so origin=pam://backupserver appid=pam://backupserver authfile=/etc/u2f_mappings manual

This configuration will ensure that the security key challenge-response is done after the password authentication.

Testing and Logging In
Now, it’s time to test this configuration. Log in to the server in a new session to test if it works.
After you supply your password, you should be met with the following prompt.

Now please copy-paste the below challenge(s) to 'u2f-host -aauthenticate -o pam://backupserver'
{ "keyHandle": "Rr3ZPpbO6fuCF1_w1RgxY2Ft6FpZ3CtABHgeySshQpH470dbVlZCbFIjUEzut3JxQrCoUWJfo4YKjAxJxL2MwA", "version": "U2F_V2", "challenge": "zwkjaDcNdfjMSqOKIq84ZsF9MlS8M0P3rmHCB7PSuKo", "appId": "pam:\/\/backupserver" }
Now, please enter the response(s) below, one per line.
[0]:

On your system, run the following — replacing the u2f-host command and challenge with what you are asked for:

echo '{ "keyHandle": "Rr3ZPpbO6fuCF1_w1RgxY2Ft6FpZ3CtABHgeySshQpH470dbVlZCbFIjUEzut3JxQrCoUWJfo4YKjAxJxL2MwA", "version": "U2F_V2", "challenge": "zwkjaDcNdfjMSqOKIq84ZsF9MlS8M0P3rmHCB7PSuKo", "appId": "pam:\/\/backupserver" }' | u2f-host -aauthenticate -o pam://backupserver

You should get a response like this:

{ "signatureData": "AQAAADwwRQIhANLPROgaGa5NYrTBY8qK8bCuy3Vc_LI6wZdrFhquyt0lAiA4ppzdGv277g853EW1TKJMC788TwxWV4SOPUPltDGyYA==", "clientData": "eyAiY2hhbGxlbmdlIjogIm1DTDBxel9aV1NvR1pHcElSZk1GYm5WSkcyNHBGMG1tTjR4Z2s4Z3VIU3MiLCAib3JpZ2luIjogInBhbTpcL1wvYmFja3Vwc2VydmVyIiwgInR5cCI6ICJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiB9", "keyHandle": "Rr3ZPpbO6fuCF1_w1RgxY2Ft6FpZ3CtABHgeySshQpH470dbVlZCbFIjUEzut3JxQrCoUWJfo4YKjAxJxL2MwA" }

Paste that into your SSH session, and press Enter. Provided you supplied a correct password and challenge response, you should be logged in.

Getting AMD switchable graphics working on Hackintosh OS X

Standard

So this needs a little bit of backstory —
A few months ago, my laptop had died, so I decided to borrow my boyfriend’s old MacBook Pro for a few weeks.
I loved it. I didn’t exactly love the MacBook Pro, but I absolutely loved OS X. The developer tools for my type of work (web development) are just frankly 10 years ahead of their Windows counterparts. It looks far more visually appealing than Windows or even Linux.

So, when I fixed my laptop, I couldn’t settle for Windows. I didn’t want to go out and buy a MacBook Pro — as the hardware I have is already future proof for the next 3 years.

I investigated the Hackintosh community, and to my amazement almost all the hardware was supported out of box and is well documented. But absolutely everyone said that AMD switchable graphics do not work and there is no way to get it to work.
For me to use a system full-time, it has to have full hardware support. This is the main reason why I don’t use Linux. I have to always settle for “oh it works but not correctly”.

I got a copy of the AMD card VBIOS by using the following tool to dump the system BIOS. From reading around, I saw that the VBIOS is around ~63K in size, so I found the VBIOS through trial and error.
I then gave this to Clover (the Hackintosh UEFI boot utility).

This seemed to work. Although I could tell the graphics card was actually Screen Shot 2015-08-31 at 18.33.38initalized by OS X, I couldn’t use it at all. This made me think there must be a way of tricking Apple’s Mux control into activating it.
Some users’ had reported success with tricking the system to use it through some EDID forcing, but this cannot work on my hardware as I know the display goes through the Intel card and there is no way to switch this.

Getting curious, I looked around for a tool that would show more information about the graphical environment.Screen Shot 2015-08-31 at 18.37.09
I found that the card was there, and was available! I was even able to select it and render through it. The FPS was significantly higher than the Intel card, which shows conclusively that there is some rendering going on at the dGPU level.

This made me think of the following problems:

  • This card will only EVER work with OpenGL applications that allow offline renderers. As with this system there is no Mux that allows it to be entirely switched.
  • I will need some way of forcing EVERY OpenGL application to use the AMD renderer. This will probably result in a low-level library hook.

Problem 1 is not able to solved easily, as far as I’m aware, and I’m not willing to waste any time on it.

Problem 2 however, was slightly easier and could be accomplished.
Digging around the Apple OpenGL documentation, I found a function that does what I need to do. CGLSetVirtualScreen()
The problem is calling this at the right time, and inside each targetted application.
Reading further into the Apple developer documentation, I found that even OpenGL application has to call CGLCreateContext() to get an OpenGL context. The sensible way of doing this would be to hook that function, then calling the original, then setting the virtual screen to what we want, then return back to the original application.

And.. it worked!
Screen Shot 2015-08-30 at 19.15.56
I haven’t been able to get anything but Chrome and Chess working with this (mostly as I haven’t tried anything else), and I can’t be bothered writing some system-level thing to do this with every application, someone else can do this if they can be bothered.

The full source code is here in zip form, and includes a build script and an example to run in Chrome. You’ll probably have to modify both the launcher script and the source for your system.
If you cannot do this yourself, then contact me and I can do at a price.
switchable.zip

TetherUnblocked – bypass Tether restrictions

Standard

Android only.

For the past few weeks I’ve been working an application that allows you to bypass Tethering restrictions on Three UK.

They have a very interesting blocking policy which, as far as I can tell, looks for the following things:

  • User-Agent Headers – It seems that if ‘Windows’ in included in the User Agent, the request will be blocked and the Tethering notification will be triggered. It seems although using Linux user agents seemingly don’t trigger this. Most likely because it would be a lot harder to match, as most mobile devices that are connected to their network are Linux based.
  • World of Warcraft – A login request to World of Warcraft seems to trigger the Tethering block. This is very interesting. As a game which uses very little bandwidth, it is a bit pointless that this would be blocked. But alas, it’s a great way to detect a PC user and as such, using it is blocked.
  • Torrenting – Any type of torrenting will cause a Tethering block. This is not even just restricted to PC-based Tethering, attempting to Tether on your phone will cause the same problem. It seems that they just don’t want that on their network.
    You can get past this on uTorrent by setting protocol encryption to ‘Forced’ and unticking ‘Allow incoming legacy connections’.

I’ve included my application to get past these blocks below. This is a beta testing version, and as such it will expire in one month.  The application works by concealing your User Agent. However, please test it and let me know what you think.
The application requires root, a kernel with iptables and armv7a device. It requires at least Android 4.0.3, although if there is any demand I may lower the version requirement. It has been tested on a Nexus 5 and Xperia Z2.

Although this is solely designed for Three UK, it should work on other networks which block by User Agent header. Please let me know if it works on your network or not.

Likewise, this should work on Three UK. If you manage to find a way to trigger the block while using this application, let me know!

Download here