Lab 04 - Authentication in Linux


  • Hashing
  • Linux PAM
  • Multi-Factor Authentication


You may use the UPB's OpenStack cloud to instantiate a Virtual Machine. Read these instructions if you wanna know how!


Hashing is the process of converting data — text, numbers, files, or anything, really — into a fixed-length string of letters and numbers. Data is converted into these fixed-length strings, or hash values, by using a special algorithm called a hash function.

Linux Pluggable Authentication Modules (PAM) is a suite of libraries that allow a Linux system administrator to configure methods to authenticate users.

“pam_exec” is a PAM module that can be used to run an external command.

Multi-factor authentication (MFA) is a multi-step account login process that requires users to enter more information than just a password. For example, along with the password, users might be asked to enter a code sent to their email, answer a secret question, or scan a fingerprint. A second form of authentication can help prevent unauthorized account access if a system password has been compromised.


In the current security lab, we'll explore the fundamentals of Linux authentication.

We'll start by examining how the OS performs hashing. First, we'll crack it and then we'll replicate it using Python.

Then, we'll utilize the “pam_exec” module to set up a custom Python script for user authentication. By exploiting a weak password vulnerability, we will be able to perform a successful login.

Finally, we'll enhance security measures by implementing Multi-Factor Authentication (MFA) with Google Authenticator.

01. [5p] Setup

We use Docker:

docker pull
mkdir ~/auth-lab
docker run --rm --name auth-lab -v $(pwd)/auth-lab/:/home/hacker/auth-lab -it

The ~/auth-lab folder is used as persistent volume so you won't lose + sync your work inside the container!

Download the lab archive inside the ~/auth-lab directory and unzip it.

Analyse the users and groups on the system. What user are we interested in?

02. [15p] Password Cracking

Use John the Ripper to crack our user's password. You need to run it as super user on the file that contains the passwords.

We want to use the default mode “wordlist” with the default location /usr/share/john/password.lst.

If you are getting an error “No password hashes loaded (see FAQ)”, you need to specify the format of the hash. It is named the same as the Linux password hashing function ;)


03. [15p] Password Hashing

Fill in the TODOs in to generate a new password hash. Using your super user privileges, manually overwrite the old password of our user.

Test if you were successful by trying to log in (su) using the new password.


04. [5p] Account Locking

As we want to use a Python script to log in to the user account we worked on so far, you need to delete and lock its password so that password-based authentication is disabled for this user account.


05. [10p] Linux PAM

We wish to write our own authentication module in Python.

For this, we must modify the common-auth Linux PAM configuration file (look in /etc/pam.d) and add this as the first rule:

auth	sufficient expose_authtok stdout quiet <>

As we want to use the script to authenticate only our special user, and because it will be called for all users, it should be sufficient to authenticate using it, but not required.

In order for authentication to be successfully performed using Python, we need 3 features, which can be achieved by passing the proper options to the module:

  • perform reads in the Python script,
  • perform prints from the Python script,
  • do not print anything else.


06. [20p] Python Script

Edit and fill in TODOs(6.*).

When you're done, crack the new password hash and try to log in ;)

Note that the password hash is hardcoded in Python (you will also find the algorithm by cracking it!) without any salt. Once you figure it out, use Python's hashlib to compute the input's user_hash and compare them!

07. [30p] Multi-Factor Authentication

Finally, let's add two-factor authentication to our script!

Edit, input a 32-byte secret and print its QR enrollment code to the console. After this, run the script and enroll the key inside a RFC 6238 (TOTP) compatible (e.g.: Google Authenticator, TOTP Authenticator, KeePassXC etc.).

Solve the remaining TODOs(7.*) in to integrate your MFA (note: the TOTP's secret key should be the same!).

Hint / workaround: PAM only gives you one input() with the user-typed password (then closes stdin, any following reads will get EOF). So, in order to read both a password and a numeric TOTP code, you must read them all at once (use whatever convention you desire, e.g.: password then 6-digit code either concatenated or split by space, then parse/extract it in Python).

Custom .so PAM plugins have no such limitations (but you must then write them in a system programming language).

If you're getting an error (e.g., invalid padding) while scanning QR / verifying the TOTP, make sure TOTP_SECRET is 32 bytes in length!



Please take a minute to fill in the feedback form for this lab.

isc/labs/04.txt · Last modified: 2024/03/24 23:00 by florin.stancu
CC Attribution-Share Alike 3.0 Unported Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0