John the Ripper and Password Policy Enforcement

Kali LinuxBeginner
Practice Now

Introduction

In today's digital landscape, strong password policies are crucial for protecting sensitive information. However, even with policies in place, vulnerabilities can exist. This lab will guide you through the process of using John the Ripper, a powerful password cracking tool, to assess the effectiveness of existing password policies. You will learn how to identify weaknesses, recommend stronger policies, and understand how to implement automated compliance checks to enhance overall security. This hands-on experience will provide you with practical skills in password security auditing and enforcement.

Analyze Existing Password Policies

In this step, you will begin by understanding how to analyze existing password policies on a Linux system. While we won't be modifying system-wide policies directly in this lab, understanding where these policies are configured is crucial for auditing. We will focus on examining common configuration files that dictate password complexity, age, and lockout settings.

First, let's examine the /etc/login.defs file, which contains global configuration settings for the shadow password suite. This file defines parameters like password aging, minimum password length, and maximum password age.

Use the grep command to look for password-related settings in /etc/login.defs:

grep -E "PASS_MAX_DAYS|PASS_MIN_DAYS|PASS_WARN_AGE|ENCRYPT_METHOD" /etc/login.defs

You should see output similar to this, though values might vary:

PASS_MAX_DAYS	99999
PASS_MIN_DAYS	0
PASS_WARN_AGE	7
ENCRYPT_METHOD SHA512

Next, we'll look at /etc/pam.d/common-password, which is a PAM (Pluggable Authentication Modules) configuration file that controls password complexity rules. This file often includes modules like pam_cracklib.so or pam_pwquality.so which enforce rules like requiring mixed case, digits, and special characters.

Use cat to view the contents of /etc/pam.d/common-password:

cat /etc/pam.d/common-password

You will see a lot of lines, but pay attention to lines containing pam_pwquality.so or pam_cracklib.so and their parameters (e.g., minlen, difok, ucredit, lcredit, dcredit, ocredit).

password        [success=1 default=ignore]      pam_unix.so obscure sha512 shadow
password        requisite                       pam_pwquality.so retry=3 minlen=8 difok=3 reject_username enforce_for_root
password        optional                        pam_gnome_keyring.so
password        optional                        pam_kwallet.so
password        optional                        pam_systemd.so

Finally, let's check the /etc/security/pwquality.conf file, which provides more granular control over password quality settings when pam_pwquality.so is used.

cat /etc/security/pwquality.conf

You might see settings like minlen, dcredit, ucredit, lcredit, ocredit, maxrepeat, etc.

## Configuration for the pam_pwquality module
#
## The setting of the PAM module is usually in /etc/pam.d/common-password
#
## minlen = 8
## difok = 3
## dcredit = -1
## ucredit = -1
## lcredit = -1
## ocredit = -1
## minclass = 0
## maxrepeat = 0
## maxsequence = 0
## gecoscheck = 0
## dictcheck = 1
## usercheck = 1
## enforce_for_root

By examining these files, you can get a good understanding of the current password policy settings on the system.

Use John the Ripper to Test Policy Effectiveness

In this step, you will use John the Ripper (JtR) to test the effectiveness of password policies. We will simulate a scenario where you have access to a password hash file and attempt to crack weak passwords.

First, let's create a dummy password file for demonstration purposes. We will create a file named passwords.txt with some weak passwords.

echo "user1:password123" > ~/project/passwords.txt
echo "user2:welcome" >> ~/project/passwords.txt
echo "user3:labexrocks" >> ~/project/passwords.txt

Now, we need to convert these plaintext passwords into a format that John the Ripper can understand. We'll use unshadow (a component of JtR) to combine a dummy /etc/passwd and /etc/shadow like file. For simplicity, we'll just use the passwords.txt file directly with JtR's stdin mode for cracking.

Let's create a simple wordlist file named wordlist.txt that John the Ripper will use to try and crack the passwords.

echo "password123" > ~/project/wordlist.txt
echo "welcome" >> ~/project/wordlist.txt
echo "labexrocks" >> ~/project/wordlist.txt
echo "secret" >> ~/project/wordlist.txt
echo "123456" >> ~/project/wordlist.txt

Now, use John the Ripper to crack the passwords from passwords.txt using the wordlist.txt.

john --format=raw-md5 --wordlist=~/project/wordlist.txt ~/project/passwords.txt

You might see output similar to this, indicating cracked passwords:

Using default input encoding: UTF-8
Loaded 3 password hashes with no different salts (Raw-MD5 [MD5])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
password123 (user1)
welcome (user2)
labexrocks (user3)
3g 0:00:00:00 DONE (2023-10-27 08:30) 100.0% 3g/s 100.0p/s 100.0c/s 100.0C/s password123 welcome labexrocks
Session completed.

To view the cracked passwords, you can use the --show option:

john --show ~/project/passwords.txt

Output:

user1:password123

user2:welcome

user3:labexrocks

3 password hashes cracked, 0 left

This demonstrates how easily weak passwords can be cracked using a simple wordlist.

Identify Gaps in Password Policies

In this step, you will identify the gaps in the simulated password policies based on the cracking results from the previous step. The fact that John the Ripper could easily crack the passwords indicates significant weaknesses.

Based on the cracked passwords (password123, welcome, labexrocks), here are some common gaps that allowed them to be cracked:

  1. Lack of Complexity Requirements: The passwords welcome and labexrocks are simple dictionary words or easily guessable phrases. password123 is a common pattern. A strong policy should enforce a mix of uppercase letters, lowercase letters, numbers, and special characters.
  2. Insufficient Length: While password123 and labexrocks are 11 and 10 characters long respectively, they are still vulnerable due to their simplicity. Policies should enforce a minimum length, typically 12 characters or more, to increase the search space for attackers.
  3. No Dictionary Word Checking: The policy did not prevent users from choosing common dictionary words or simple variations.
  4. No Common Pattern Checking: Passwords like password123 follow predictable patterns that are often included in cracking wordlists.
  5. Lack of Password History/Reuse Prevention: If users are allowed to reuse old passwords, even if they were once strong, they become vulnerable if those old passwords are leaked.

To simulate identifying these gaps, let's consider what a stronger password policy might look like. For instance, if our current policy allows minlen=8 and no specific character class requirements, then welcome (7 chars) would fail, but password123 (11 chars, no special chars) would pass. The cracking results highlight that even if a password meets a basic length requirement, it might still be weak if complexity and dictionary checks are not enforced.

Think about how the pam_pwquality.so module parameters (like minlen, dcredit, ucredit, lcredit, ocredit, dictcheck) could be adjusted to prevent such weak passwords. For example, setting dcredit=-1 would require at least one digit, ucredit=-1 for uppercase, etc.

This step is primarily conceptual, focusing on analyzing the results of the previous cracking exercise to understand policy deficiencies.

Recommend Stronger Password Policies

In this step, you will formulate recommendations for stronger password policies based on the identified gaps. Effective password policies balance security with usability.

Here are some recommendations for a more robust password policy:

  1. Minimum Length: Increase the minimum password length to at least 12-14 characters. Longer passwords are exponentially harder to crack.
    • Example PAM setting: minlen=12 in /etc/security/pwquality.conf or pam_pwquality.so minlen=12 in /etc/pam.d/common-password.
  2. Complexity Requirements: Enforce the use of a mix of character types:
    • Uppercase letters (A-Z)
    • Lowercase letters (a-z)
    • Numbers (0-9)
    • Special characters (!@#$%^&*()_+-=[]{}|;':",./<>?)
    • Example PAM setting: dcredit=-1 ucredit=-1 lcredit=-1 ocredit=-1 in /etc/security/pwquality.conf or pam_pwquality.so dcredit=-1 ucredit=-1 lcredit=-1 ocredit=-1 in /etc/pam.d/common-password.
  3. Dictionary and Common Pattern Checking: Prevent the use of common dictionary words, common names, and easily guessable patterns (like password123, qwerty, 123456).
    • Example PAM setting: dictcheck=1 usercheck=1 in /etc/security/pwquality.conf or pam_pwquality.so dictcheck=1 usercheck=1 in /etc/pam.d/common-password.
  4. Password History/Reuse Prevention: Prevent users from reusing a certain number of their previous passwords. This mitigates the risk if an old password is compromised.
    • Example PAM setting: remember=5 with pam_unix.so in /etc/pam.d/common-password (e.g., password required pam_unix.so obscure sha512 shadow remember=5).
  5. Account Lockout Policy: Implement an account lockout policy after a certain number of failed login attempts to deter brute-force attacks.
    • Example PAM setting: Using pam_tally2.so or pam_faillock.so in /etc/pam.d/common-auth (e.g., auth required pam_faillock.so deny=3 unlock_time=600).
  6. Regular Password Changes (with caution): While traditionally recommended, frequent mandatory password changes can lead to users choosing simpler, more predictable passwords. A better approach is to enforce strong complexity and length, and only require changes if a breach is suspected.

To demonstrate a conceptual change, let's imagine we are updating a policy. We will not actually modify system files, but you can see how the pwquality.conf file could be edited.

Open a dummy file to simulate policy recommendations:

nano ~/project/recommended_policy.txt

Add the following content to the file:

## Recommended Password Policy Settings
minlen = 14
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1
dictcheck = 1
usercheck = 1
maxrepeat = 3
maxsequence = 3

Save and exit nano (Ctrl+S, Ctrl+X).

These settings would enforce a minimum length of 14 characters, require at least one digit, uppercase, lowercase, and special character, and prevent dictionary words and usernames.

Implement Automated Policy Compliance Checks

In this step, you will learn about implementing automated policy compliance checks. While direct system-wide policy enforcement is done via PAM and other configuration files, automated checks can be used to regularly audit user passwords or system configurations against defined policies.

For this lab, we will simulate a simple compliance check using a shell script. This script will check if a dummy user's password meets a basic length requirement. In a real-world scenario, such scripts would be more complex, potentially integrating with tools like OpenSCAP or custom scripts to audit actual password hashes (if permitted and ethical) or configuration files.

First, let's create a dummy user and a dummy password hash file to simulate a system state. We will not create actual system users.

echo "testuser:\$6\$salt\$hashedpassword" > ~/project/dummy_shadow.txt

Now, create a simple shell script named check_password_compliance.sh that checks if the password length for testuser in dummy_shadow.txt is greater than a certain value (e.g., 10 characters).

nano ~/project/check_password_compliance.sh

Add the following content to the script:

#!/bin/bash

## This script simulates a basic password length compliance check.
## In a real scenario, you would parse actual shadow file entries
## or use more sophisticated tools.

MIN_LENGTH=10
PASSWORD_HASH=$(grep "testuser" ~/project/dummy_shadow.txt | cut -d':' -f2)

## For demonstration, we'll just check the length of a placeholder hash.
## In reality, you'd need to crack or analyze the actual hash.
## Here, we're just checking if the hash string itself is long enough,
## which is NOT how real password length checks work, but serves as a
## placeholder for a compliance check.

if [ ${#PASSWORD_HASH} -ge $MIN_LENGTH ]; then
  echo "Compliance Check: testuser password hash length meets minimum requirement ($MIN_LENGTH characters)."
  exit 0
else
  echo "Compliance Check: testuser password hash length DOES NOT meet minimum requirement ($MIN_LENGTH characters)."
  exit 1
fi

Save and exit nano (Ctrl+S, Ctrl+X).

Make the script executable:

chmod +x ~/project/check_password_compliance.sh

Now, run the compliance check script:

~/project/check_password_compliance.sh

You should see output indicating compliance based on the dummy hash length:

Compliance Check: testuser password hash length meets minimum requirement (10 characters).

This simple example illustrates the concept of an automated compliance check. In a production environment, such scripts could be scheduled to run periodically using cron to ensure continuous adherence to password policies. More advanced checks would involve parsing actual password hashes (if allowed and with proper security considerations), checking against dictionary lists, or integrating with security compliance frameworks.

Summary

In this lab, you gained practical experience in auditing and enforcing password policies. You learned how to analyze existing password policy configurations on a Linux system by examining key files like /etc/login.defs, /etc/pam.d/common-password, and /etc/security/pwquality.conf. You then used John the Ripper to demonstrate how easily weak passwords can be cracked, highlighting the importance of robust policies. Based on these findings, you formulated recommendations for stronger password policies, focusing on length, complexity, and dictionary checks. Finally, you explored the concept of automated compliance checks by creating a simple script to verify password policy adherence. This lab provides a foundational understanding of password security auditing, equipping you with skills to identify and mitigate password-related vulnerabilities.