ブルートフォースアタックとは、特別な手段を使わずにあらゆる可能性を尽くした攻撃手法です。より正式な名前は徹底的な攻撃、つまりすべての可能性を使い果たす攻撃です。
アクセス制御の場合、一般的なブルート フォース攻撃では、攻撃者がシステムへのログインを多数回試行します。ほとんどの場合、ユーザー名はわかっており、パスワードは推測するだけで済みます。
ブルートフォース攻撃にはスキルがありませんが、辞書攻撃にはある程度のスキルがあるようです。最大の違いは、推測する際の知性です。辞書攻撃は、ブルート フォース攻撃のように考えられるすべての状況を網羅するのではなく、最も可能性の高い状況のリストを網羅するだけです。
検証の試行を防止したり、許可されるエラーの数を制限したりすることは比較的効果的なセキュリティ対策ですが、その際のジレンマは、正規のユーザーに影響を与えずに攻撃者を特定してブロックする方法です。
この場合、一貫性を判断すると、この 2 つを区別するのに役立ちます。この方法は、第 4 章で説明したセッション ハイジャックを防止する方法とよく似ていますが、正規のユーザーではなく攻撃者を特定する必要がある点が異なります。
次の HTML フォームを考えてみましょう:
CODE: <form action="http://example.org/login.php" method="POST"> <p>Username: <input type="text" name="username" /></p> <p>Password: <input type="password" name="password" /></p> <p><input type="submit" /></p> </form>
攻撃者はこのフォームを表示し、正規のデータを http://www.php.cn/ に POST するスクリプトを作成します:
CODE: <?php $username = 'victim'; $password = 'guess'; $content = "username=$username&password=$password"; $content_length = strlen($content); $http_request = ''; $http_response = ''; $http_request .= "POST /login.php HTTP/1.1\r\n"; $http_request .= "Host: example.org\r\n"; $http_request .= "Content-Type: application/x-www-form-urlencoded\r\n"; $http_request .= "Content-Length: $content_length\r\n"; $http_request .= "Connection: close\r\n"; $http_request .= "\r\n"; $http_request .= $content; if ($handle = fsockopen('example.org', 80)) { fputs($handle, $http_request); while (!feof($handle)) { $http_response .= fgets($handle, 1024); } fclose($handle); /* Check Response */ } else { /* Error */ } ?>
このスクリプトを使用すると、攻撃者は単にループを追加して、異なるパスワードの試行を継続し、試行のたびに $http_response 変数をチェックすることもできます。 $http_response 変数が変更されると、正しいパスワードが推測されたと考えることができます。
この種の攻撃を防ぐために講じられるセキュリティ対策は数多くあります。ブルート フォース攻撃では、すべての HTTP リクエストがパスワードを除いてまったく同じであることに気付きました。パスワードは非常に重要です。
一定回数の試行が失敗した後にアカウントを一時的に凍結することは効果的な防御策ですが、攻撃者が正当なユーザーのアプリケーションへのアクセスに影響を与えないようにするために、アカウントを凍結するためのより決定的なアプローチを検討することもできます。
ブルート フォース攻撃をより困難にし、成功する可能性を低くするプロセスもあります。これは、単純な封じ込めメカニズムで効果的に行うことができます。
CODE: <?php /* mysql_connect() */ /* mysql_select_db() */ $clean = array(); $mysql = array(); $now = time(); $max = $now - 15; $salt = 'SHIFLETT'; if (ctype_alnum($_POST['username'])) { $clean['username'] = $_POST['username']; } else { /* ... */ } $clean['password'] = md5($salt . md5($_POST['password'] . $salt)); $mysql['username'] = mysql_real_escape_string($clean['username']); $sql = "SELECT last_failure, password FROM users WHERE username = '{$mysql['username']}'"; if ($result = mysql_query($sql)) { if (mysql_num_rows($result)) { $record = mysql_fetch_assoc($result); if ($record['last_failure']> $max) { /* Less than 15 seconds since last failure */ } elseif ($record['password'] == $clean['password']) { /* Successful Login */ } else { /* Failed Login */ $sql = "UPDATE users SET last_failure = '$now' WHERE username = '{$mysql['username']}'"; mysql_query($sql); } } else { /* Invalid Username */ } } else { /* Error */ } ?>
上記の例では、最後に認証が失敗した後、同じユーザーによる再試行の頻度が制限されます。失敗してから 15 秒以内に再試行すると、パスワードが正しいかどうかに関係なく、検証は失敗します。これがこの計画のキーポイントです。ただし、試行失敗後に 15 秒間アクセスをブロックするだけでは十分ではありません。この時点では、入力が何であっても出力は一貫しており、ログインが成功した場合にのみ出力が異なります。そうしないと、攻撃者は単に一貫性のない出力を調べて、ログインが成功したかどうかを判断する可能性があります。
上記は PHP セキュリティ - ブルート フォース アタックの内容です。その他の関連コンテンツについては、PHP 中国語 Web サイト (www.php.cn) にご注意ください。