In this lab, you will learn how to identify and exploit weak password vulnerabilities in web applications using Python. You will practice common password cracking techniques to understand how attackers compromise systems. This practical exercise will help you develop essential cybersecurity skills while emphasizing the importance of strong password policies.
Exploring the Target Website
In this step, we will gather information about our target website, a crucial first phase in any security assessment. Before attempting any password cracking, it's important to understand how the login system works and what security measures are in place.
Open your web browser and navigate to http://localhost:8080/. You can access this by clicking on the Web 8080 tab in the LabEx environment.
Note: In the LabEx virtual machine, the web server operates on a temporary public network. This means the domain name you see may not be "localhost" but an actual accessible domain. This is normal and does not affect the lab exercise.
Carefully examine the login form. Take note of the following:
The site requires both a username and a password - this is called credential-based authentication.
There are no visible clues about valid usernames or password requirements. This is intentional security through obscurity.
Attempt to log in using a few random combinations of usernames and passwords. For example:
Username: test, Password: password123
Username: admin, Password: admin
Username: user, Password: 12345
These are common default credentials that many beginners might use. You should receive an "Invalid username or password" message for each attempt.
Based on your observations, we can make some educated guesses about the login system:
It doesn't reveal whether a username exists or not. This is called username enumeration protection - a good security practice that prevents attackers from discovering valid accounts.
There's no apparent limit on the number of login attempts. In security terms, this is called lack of rate limiting, which could allow brute force attacks in a real-world scenario.
This initial reconnaissance phase is what security professionals call "footprinting" - gathering basic information about the target system. Understanding these details will help us plan our password cracking approach more effectively in the next steps.
Creating a Password Dictionary
Now that we've gathered information about the login system, we'll create a dictionary of potential passwords. In cybersecurity, a password dictionary is simply a text file containing a list of possible passwords that might be tried against a login system. This is a fundamental technique used in password cracking attempts, and understanding it helps us build better defenses.
Open the terminal on the Desktop. The terminal is where we'll execute commands to create our password file.
In the terminal, enter the following command to create and populate the passwords.txt file:
This command uses a special bash feature called a "here document" (heredoc). It's a convenient way to create files with multiple lines of content directly from the command line. Let's break down what's happening:
cat << EOF > filename: This tells bash to take all input until it sees "EOF" and redirect it to the specified file
The text between the first EOF and the second EOF becomes the file's content
The final EOF signals the end of input
After execution, you'll find a new file named passwords.txt in the ~/project/password_lab/ directory. This file contains 30 of the most commonly used weak passwords. Notice how many are simple words, number sequences, or slight variations - these are exactly the types of passwords that make systems vulnerable.
In actual security testing, professionals might use dictionaries containing:
Hundreds of thousands of password combinations
Words from multiple languages and dictionaries
Common password patterns and mutations
Previously leaked passwords from security breaches
Remember: While we're using this small dictionary for educational purposes to understand attack methods, attempting to crack passwords without explicit permission is both illegal and unethical. This exercise helps us learn how to build stronger authentication systems by understanding common weaknesses.
Writing the Password Cracking Script
With our password dictionary in place, we'll now create a Python script to automate the process of testing these passwords against our target website. This script will simulate how attackers systematically try different password combinations, helping us understand the importance of strong passwords.
Open the terminal on the Desktop if it's not already open. The terminal is where we'll write and execute our Python code.
Enter the following command to open a new file named password_cracker.py in the nano text editor:
nano ~/project/password_lab/password_cracker.py
Nano is a simple text editor that comes pre-installed in most Linux systems. We'll use it to write our Python script.
Copy and paste the following Python code into the nano editor:
import requests
import time
def crack_password(username, password_list):
url = 'http://localhost:8080'
for password in password_list:
response = requests.post(url, data={'username': username, 'password': password.strip()})
if 'Login successful!' in response.text:
print(f"Succeeded! {username} with password: {password.strip()}")
else:
print(f"Failed attempt for {username} with password: {password.strip()}")
time.sleep(0.1) ## Small delay to avoid overwhelming the server
def main():
usernames = ['admin', 'user', 'root', 'administrator', 'webmaster']
with open('passwords.txt', 'r') as f:
passwords = f.readlines()
for username in usernames:
print(f"Attempting to crack password for user: {username}")
crack_password(username, passwords)
if __name__ == '__main__':
main()
Save the file and exit nano by pressing Ctrl+X, then Y, and finally Enter. This sequence saves our changes and returns us to the terminal.
Let's examine how this script works in detail:
The crack_password function:
Takes a username and a list of passwords as input.
Uses the requests library to send HTTP POST requests to our test website.
For each password, it removes extra spaces with strip() and tries to login.
Checks the response for "Login successful!" to identify correct passwords.
Includes a 0.1 second delay between attempts to prevent server overload.
The main function:
Defines common administrator usernames that attackers often target.
Opens our password dictionary file (passwords.txt) and reads all lines.
Loops through each username, attempting all passwords in our dictionary.
The if __name__ == '__main__': line ensures the script runs when executed directly.
This script demonstrates a basic brute-force attack pattern. It systematically tries every password in our dictionary against each username. The time delay is crucial - real attackers often use similar delays to avoid detection by security systems that monitor for rapid login attempts.
Remember, this is purely for educational purposes. In real-world scenarios, performing such actions without explicit permission is illegal. We're learning these techniques to better understand and defend against them, not to engage in unauthorized access.
Running the Password Cracking Script
Now that we've prepared our password cracking script, let's execute it and examine how it works in practice. This hands-on demonstration will show you exactly how weak passwords can be compromised using basic techniques.
First, we need to navigate to the directory containing our script. In the terminal, type:
cd ~/project/password_lab
This command changes your working directory to where we stored our Python script. It's important to be in the correct directory so the system can find and run our file.
To execute the script, use the Python interpreter with this command:
python password_cracker.py
When you press enter, the script will begin running. It works by systematically trying common passwords from a predefined list against sample user accounts.
Observe the output carefully as the script runs. You'll see real-time feedback showing each attempt. Here's what typical output looks like:
labex:password_lab/ $ python password_cracker.py
Attempting to crack password for user: admin
Failed attempt for admin with password: 123456
Failed attempt for admin with password: password
Failed attempt for admin with password: qwerty
Failed attempt for admin with password: letmein
Failed attempt for admin with password: admin
Failed attempt for admin with password: welcome
Failed attempt for admin with password: monkey
Failed attempt for admin with password: 123456789
Failed attempt for admin with password: 1234567890
Failed attempt for admin with password: superman
Succeeded! admin with password: supersecret123
Notice how the script tries common weak passwords in sequence until it finds a match. This is called a dictionary attack, where we test passwords from a list of likely candidates.
After the script completes, consider these important questions about the results:
Which user accounts had weak passwords that were successfully cracked?
How many attempts were needed before finding each correct password?
What patterns do you notice in the passwords that were successfully guessed?
Why do you think some passwords resisted cracking while others didn't?
This exercise clearly shows why simple passwords are dangerous. In our test case, the account "admin" with password "supersecret123" was vulnerable because it appeared in our dictionary of common passwords. Even though it contains letters and numbers, its predictability made it easy to crack.
Remember: This demonstration is for educational purposes only. Using these techniques on real systems without explicit permission is illegal. Our goal is to understand security weaknesses so we can create stronger password policies and better protect systems.
Improving Password Security
Now that we've successfully cracked some weak passwords, let's implement proper security measures to prevent such attacks. In this section, we'll create a password strength checker and a secure registration system. These are fundamental security practices used by professional web applications.
Open the WebIDE Tab in the LabEx VM. WebIDE is a web-based integrated development environment that allows you to write, run, and debug code directly in your browser. It's similar to the VS Code editor but runs in the browser. WebIDE is suitable for editing longer code files.
In the file explorer on the left side of the screen, click on the app.py file to open it in the editor. This is where we'll add our security improvements.
Add the following function after the users dictionary to implement password strength checks. This function uses regular expressions (regex) to validate password complexity:
import re
def is_strong_password(password):
if len(password) < 12:
return False
if not re.search(r'[A-Z]', password):
return False
if not re.search(r'[a-z]', password):
return False
if not re.search(r'\d', password):
return False
if not re.search(r'[!@#$%^&*(),.?":{}|<>]', password):
return False
return True
This function checks if a password meets modern security standards by verifying:
Minimum length of 12 characters (longer passwords are harder to crack)
At least one uppercase letter (A-Z)
At least one lowercase letter (a-z)
At least one digit (0-9)
At least one special character (!@#$% etc.)
Now we'll create a secure registration page. Add this code block before the if __name__ == '__main__': line. This creates a new route in our web application:
Navigate to the Web 8080 tab, and add /register to the URL to access the new registration form:
Test the security by trying to register with a weak password like "password123". The system should reject it with an error message.
Now register with a properly strong password that meets all criteria. For example:
Username: labex
Password: S3cureP@ssw0rd-2024
Notice how this password includes all required character types and is sufficiently long.
Let's test our improved security against the password cracker. First, modify the password_cracker.py script to target our new account:
Open the terminal and enter:
nano ~/project/password_lab/password_cracker.py
Find the line that says usernames = ['admin', 'user', 'root', 'administrator', 'webmaster']
Replace it with usernames = ['labex'] to target our new account
Run the modified script:
python ~/project/password_lab/password_cracker.py
The script should fail to crack the password, demonstrating how strong password policies effectively prevent brute force attacks. This shows why modern applications enforce complex password requirements.
Summary
In this lab, you have learned the fundamentals of ethical password cracking and web application security testing. You practiced reconnaissance techniques to identify vulnerabilities, created password dictionaries, and automated attack simulations using Python scripts.
Through this hands-on experience, you've gained insights into how weak passwords can be exploited and the importance of implementing robust security measures. The lab demonstrated practical countermeasures like strong password policies that can effectively protect systems from common attacks.