Skip to content

Latest commit

 

History

History
134 lines (90 loc) · 5.77 KB

File metadata and controls

134 lines (90 loc) · 5.77 KB

Level01 Writeup

Overview

Level01 focuses on cracking a DES-encrypted password hash found in the /etc/passwd file. This challenge teaches us about legacy Unix password storage mechanisms and password cracking techniques.


Step 1: Finding the Hash

As mentioned in my level00 writeup, while exploring the system I examined the /etc/passwd file and discovered an interesting entry for the flag01 user:

cat /etc/passwd

The entry revealed:

flag01:42hDRfypTqqnw:3001:3001::/home/flag/flag01:/bin/bash

The second field 42hDRfypTqqnw appeared to be a password hash, which would be the key to solving this level.


Step 2: Hash Analysis

I began analyzing the hash to understand its format and characteristics. After some research, I learned that historically, /etc/passwd could store passwords using various hashing algorithms. The type of hash can be identified by examining the format:

Hashes without a dollar sign prefix are traditional DES crypt (13 characters). Hashes with a dollar sign use the format $id$salt$hash, where the id indicates the algorithm: $1$ for MD5, $2$ or variants for Blowfish (bcrypt), $5$ for SHA-256, and $6$ for SHA-512.

Based on the hash length of 13 characters and the absence of a dollar sign prefix, I determined this was a DES crypt hash. DES crypt follows a specific structure where the first 2 characters always represent the salt used during encryption, and DES-based passwords are always 13 characters long consisting of alphanumeric characters as well as . and /. In this case, the salt is 42, and the remaining 11 characters hDRfypTqqnw form the actual hash.

An important constraint of DES crypt is that passwords are limited to a maximum of 8 characters. This limitation, combined with the weak encryption algorithm, makes DES hashes particularly vulnerable to cracking attempts.


Step 3: Attempting to Crack the Password

My first approach was to try several online password cracking tools. I tested the hash on CrackStation, Hashes.com, and CMD5.org, but unfortunately, none of these services were able to find the password in their databases. This suggested the password wasn't a common dictionary word or frequently used password.

I then learned about John the Ripper, a powerful password cracking tool that can perform both dictionary attacks and brute-force attacks. John the Ripper uses various techniques to crack passwords, including trying words from wordlists, applying rules and mutations, and systematically testing different character combinations.

This research gave me an idea: instead of relying on external tools, I could write my own C++ program to crack the password using the crypt() function available in Unix systems.


Step 4: Writing the Password Cracker

I started developing a C++ program with a simple concept: generate password candidates and hash each one using the salt 42, then compare the result with our target hash 42hDRfypTqqnw.

My initial approach was to try all possible character combinations with lengths from 1 to 8 characters. However, I quickly realized this brute-force method had a serious time complexity problem. Even with just lowercase letters, trying all combinations would take an extremely long time.

Then I had a better idea: instead of generating passwords myself, I could use a wordlist containing common passwords. This dictionary attack approach would be much faster since it focuses on passwords that people actually use. I downloaded a wordlist (password.lst) and modified my program to read passwords from the file, hash each one, and compare it with the target hash.

Here's the final C++ program:

#include <iostream>
#include <fstream>
#include <unistd.h>
#include <string>

using namespace std;

bool	check(string &hash, string &salt, string &password)
{
	string passhash(crypt(password.c_str(), salt.c_str()));
	if (passhash == hash)
	{
		cout << "Password found: " << password << endl;
		return true;
	}
	return false;
}

int main()
{
	string hash = "42hDRfypTqqnw";
	string salt = "42";
	string password;
	ifstream wordlist("password.lst");
	if (!wordlist.is_open())
	{
		cout << "Error opening file." << endl;
		return 1;
	}
	while (getline(wordlist, password))
	{
		if (check(hash, salt, password))
			return 0;
	}
	cout << "Password not found." << endl;
	return 1;
}

To compile and run the program:

g++ -o crack crack.cpp
./crack

The wordlist approach worked perfectly! The program found the password in a very short time: abcdefg


Step 5: Capturing the Flag

With the password in hand, getting the flag was straightforward. I switched to the flag01 user and executed the getflag command:

su flag01
# Password: abcdefg
getflag

The flag was successfully retrieved: f2av5il02puano7naaf6adaaf


Conclusion

This level provided valuable insights into password security and cryptographic weaknesses. DES crypt, while revolutionary in its time, has several critical vulnerabilities that make it unsuitable for modern use. The 13-character hash format with its 2-character salt and 8-character password limitation creates a relatively small search space for attackers.

The challenge also demonstrated the effectiveness of dictionary attacks versus pure brute-force methods. By using a wordlist of common passwords, we reduced the cracking time from potentially hours or days to just seconds. This highlights why using common or simple passwords is so dangerous, even with encryption.

Modern systems have addressed these weaknesses by moving password hashes to the /etc/shadow file, which is only readable by root, and using much stronger hashing algorithms like SHA-256 or SHA-512 with proper salting and key stretching techniques.


Flag: f2av5il02puano7naaf6adaaf

Next Level: Level02