Requirement 8: Assign a unique ID to each person with computer access

8.1 Assign all users a unique ID before allowing them to access system components or cardholder data.

In our post about Rootsh logging we touched on the PCI DSS Requirement that all users must use a unique user id and never use shared accounts. This is where that requirement is made more explicit.

In the linux world the most common shared account you are likely to come across as a system administrator is the root account, and we covered how we can safely disable this once sudo is properly configured.

But even if we have unique accounts on every system which is in, or connected to, the cardholder data environment, we still have more work to do.

8.2 In addition to assigning a unique ID, employ at least one of the following methods to authenticate all users:

  • Something you know, such as a password or passphrase
  • Something you have, such as a token device or smart card
  • Something you are, such as a biometric

8.3 Incorporate two-factor authentication for remote access (network-level access originating from outside the network) to the network by employees, administrators, and third parties. (For example, remote authentication and dial-in service (RADIUS) with tokens; terminal access controller access control system (TACACS) with tokens; or other technologies that facilitate two-factor authentication.)

Note: Two-factor authentication requires that two of the three authentication methods (see Requirement 8.2 for descriptions of authentication methods) be used for authentication. Using one factor twice (for example, using two separate passwords) is not considered two-factor authentication.

So before any user can gain access to the cardholder data environment, they must undergo a two factor authentication. There are many commercial solutions for this which involve distribution of tokens or the use of biometrics, but we were looking for an open-source route which did not involve additional hardware.

One Time Passwords

We need 2 out of the 3 methods listed in Requirement 8.2 to have true two-factor authentication.

The first method, “something you know”, is the users’ standard system password (for their unique user id). More on the requirements for this in a later post.

An accepted second method is a one-time password. You’ll note Requirement 8.3 above mentions two separate passwords are not sufficient, so how can we use a one-time passwords for the second authentication method?

This is because one time passwords are in effect “something you have” and not “something you know”. You need to be in possession of a means of password generation whether that be a token, a mobile phone to receive it as an SMS, or even a paper list. People don’t, and generally can’t, memorise a one-time password for each login.

S/Key System

The S/Key system is a means of generating one-time passwords based on a random seed, a secret key, and a sequence number. A user can use an offline calculator to generate these passwords as needed.

S/Key takes an initial secret (which ideally should never be typed into anything except an offline device), and along with a random seed, applies a one-way hash function to this secret n times. Lets say n was 500.

The server then stores the 500th hash result. There is no way of moving backwards through the hash chain to expose the initial secret so this is perfectly safe.

Upon login, the user is required to supply the 499th hash result. The server can easily check if it is given the correct answer by applying the hash function to the 499th hash, to see if it equals the 500th hash result. If it does, the 499th hash result is stored and the user is authenticated.

Next login will require the 498th hash result and so on. And because we cannot move backwards through the hash chain, the user must use an S/Key calculator to produce the desired result by supplying the secret, and applying the hash the required number of times to it.

It may sound complicated, but it is very easy in practice, so lets look at an implementation.

SSH Gateways & Firewall Configuration

Before we move onto installation of a one-time password system, we should mention the network design. Two factor authentication is required for all “remote access”. Unless you have few enough machines in your environment that you’d be happy to install one-time password implementations on all of them, we’d highly recommend designating two or more SSH gateway machines which must be remotely logged into first before any of the rest of your environment can be accessed.

The firewall should be configured to only allow inbound traffic on port 22 to your SSH gateways, and all SSH gateways would have one time passwords enforced in addition to standard system level user passwords. So to remotely access any machine in your environment, you are forced to undergo two factor authentication. Once on a gateway machine, you can SSH internally to other machines in the environment using user passwords only.

OPIE Installation

OPIE stands for One-Time Password in Everything and is an implementation which is packaged for Debian.

On a designated SSH gateway server, do the following to install:

apt-get install libpam-opie opie-server

Then you need to configure SSH so that it requires authentication from the OPIE PAM module as well as the current method of authentication.

We found we needed the following changes.

In /etc/ssh/sshd_config we needed:

ChallengeResponseAuthentication yes
...
PasswordAuthentication yes
...
UsePAM yes

Then in /etc/pam.d/sshd, after the @include common-auth line, add:

auth            required        pam_opie.so

(we preferred to have this line outside of /etc/pam.d/common-auth so that when installing or configuring other PAM modules, the OPIE requirement would be left alone).

This means, once the standard common-auth authentication has been successful, pam_opie.so is then called… these are our two factors of authentication.

So to activate this (but don’t do it yet!) we would:

/etc/init.d/ssh restart

Setting up OPIE Users

Of course, if we activated OPIE now, no-one would be able to log in since we first need to initialise the users.

For maximum security, the user should have an offline S/Key calculator ready for use at this point. There are many implementations around for iOS or Android etc. so choose whichever you find easiest to use.

A user would log into the SSH gateway server and run:

opiepasswd

opiepasswd never asks for the initial secret. This is important since if it was sniffed then all the S/Key passwords generated would be compromised. Only the offline S/Key calculator needs the initial secret.

opiepasswd by default asks for a response from your S/Key calculator for a the 499th password and supplies the random(ish) salt to use:

[david@debian:~]$ opiepasswd
Adding david:
You need the response from an OTP generator.
New secret pass phrase:
    otp-md5 499 de6448
    Response: 

Now on your calculator you supply the challenge 499 de6448, a secret, and select md5 as your hash method. You will then be provided with a response similar to the following to enter:

VALE EMMA DIG LEW OTTO SALT

The server is now initialised for this user. You can see inside /etc/opiekeys that this password has been recorded (in hex) as the 499th for user david:

david 0499 de6448           f32f743a123c9bac  Sep 27,2012 12:36:38

Once OPIE is activated, on the next login, libpam-opie will challenge me with:

$ ssh david@ssh_gate1
Password:
otp-md5 498 de6448 ext, Response:

And again, the calculator is used to provide the response.

Low Tech OPIE

If the user doesn’t have, or prefers not to use, a mobile device capable to running a S/Key calculator, two-factor authentication can still be achieved.

One way would be to use a separate, local linux machine to generate a list of passwords.
The user can install opie-server:

apt-get install opie-server

then generate a list of one-time passwords based on a secret key and chosen sequence number and salt (increase -n for more):

[david@debian:~]$ opiekey -n 20 499 lo123
Using the MD5 algorithm to compute response.
Reminder: Don't use opiekey from telnet or dial-in sessions.
Enter secret pass phrase: 
480: AMRA INN VEND BULL YAWN LACE
481: DRUG DOLT CURD BIEN SEC BALM
482: BID HUH MOLE SNAG WOLF MEN
483: NEAT ADDS COED SULK DUNE MOVE
484: LINK SOFA DON TOOK WONT GAL
485: LORD FOND MILK VET PAW EEL
486: MAIL TRAY FLAT NEED KUDO BYTE
487: LOIS FOSS RIDE FAST GUST KANT
488: SOOT TOP TOWN MEND NIB WATT
489: DANK ASIA FORE WORM BLUR LOW
490: HATE WELL ALOE BETH HAP GREG
491: SILK CUP CANE NEON WAVE EM
492: BOY MOO SILT NOR ARTY LAND
493: KARL SOB AMEN HUGH KNOW TACK
494: LOAF SWAN SOD JOE ONES MOW
495: WON NAY BEEN TUBA BARE KEY
496: DOLE SAUL CAFE SNUB DOVE TRUE
497: GIG SLAB DEAR HOLM FIR MALE
498: MUCK SINE COST HEEL BODE DIET
499: SANG BOOK CHUM CAKE MINI GAFF

This old-fashioned user can then print this list off and keep it with them for future reference when needing to log in. Very low tech indeed, but it’s really not all that different to having a token.

Then on the SSH gateway, to set up the user for the first time, we would run opiepasswd as before except we specify the sequence 499, and salt lo123, which the user used on their local machine – note the response is the same as number 499 on the list:

[david@debian:~]$ opiepasswd -s lo123 -n 499
Adding david:
You need the response from an OTP generator.
New secret pass phrase:
    otp-md5 499 lo123
    Response: SANG BOOK CHUM CAKE MINI GAFF

ID david OTP key is 499 lo123
SANG BOOK CHUM CAKE MINI GAFF

So the user is set up with the last key from the list and will work their way down it every time they log in.