質問

どうしてそうなっちゃうんですかこれ 決定版ガイドをフォームによるwebサイトの認証 予防急-消防のログインが試み.

最良の実践例#1:短時間に遅れることが大きくなるにつれて増加する数の試みが失敗に終わったように:

1失敗した試みがありますの遅延
2の試みが失敗に終わった=2秒の遅延
3の試みが失敗に終わった=4秒の遅延
4つの試みが失敗に終わった=8秒の遅延
5つの試みが失敗に終わった=16秒
など。

DoS攻撃、この制度は非常に困難なものの、他方、潜在的な脅威であるから遅れが重要になります。

んどう実装するこのように自分のログインシステムPHP?

役に立ちましたか?

解決

できなけ防止のたDoS攻撃によるチェーン側をシングルはホームページからダウンロードユーザ名です。地獄できないもんを防止急-消防のログインを試みます。

なぜですか? で攻撃できる複数のIPsとローカルユーザーアカウントにお越側の試み.

れによって掲載して他るべき追跡調査する予定であるすべてのログインに失敗した試みのサイトに関してタイムスタンプか:

CREATE TABLE failed_logins (
    id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(16) NOT NULL,
    ip_address INT(11) UNSIGNED NOT NULL,
    attempted DATETIME NOT NULL,
    INDEX `attempted_idx` (`attempted`)
) engine=InnoDB charset=UTF8;

クに関する注意ip_address分野:きのデータを取得するデータは、それぞれ、INET_ATON()およびINET_NTOA()を本質的には相当に変換するipアドレスから符号なし整数です。

# example of insertion
INSERT INTO failed_logins SET username = 'example', ip_address = INET_ATON('192.168.0.1'), attempted = CURRENT_TIMESTAMP;
# example of selection
SELECT id, username, INET_NTOA(ip_address) AS ip_address, attempted;

決定の遅延値に基づく 総合 ログイン失敗回数を与えられた時間(15分です。るべき基本統計データから引き failed_logins テーブルとしてでは 経時変化 に基づくユーザー数をどのようそれらの多くはリコール(タイプ)パスワードになります。


> 10 failed attempts = 1 second
> 20 failed attempts = 2 seconds
> 30 failed attempts = reCaptcha

クエリのテーブル毎に失敗したログインの検索を試みログイン失敗回数の指定された期間、15分:


SELECT COUNT(1) AS failed FROM failed_logins WHERE attempted > DATE_SUB(NOW(), INTERVAL 15 minute);

多数の場合に一定時間以上のお客様限定、執行側は力のすべてのユーザーの利用酔(すなわちreCaptcha)までの数の試みが失敗に終わった以上、指定された期間以下はzemax®ファイルをご参照ください。

// array of throttling
$throttle = array(10 => 1, 20 => 2, 30 => 'recaptcha');

// retrieve the latest failed login attempts
$sql = 'SELECT MAX(attempted) AS attempted FROM failed_logins';
$result = mysql_query($sql);
if (mysql_affected_rows($result) > 0) {
    $row = mysql_fetch_assoc($result);

    $latest_attempt = (int) date('U', strtotime($row['attempted']));

    // get the number of failed attempts
    $sql = 'SELECT COUNT(1) AS failed FROM failed_logins WHERE attempted > DATE_SUB(NOW(), INTERVAL 15 minute)';
    $result = mysql_query($sql);
    if (mysql_affected_rows($result) > 0) {
        // get the returned row
        $row = mysql_fetch_assoc($result);
        $failed_attempts = (int) $row['failed'];

        // assume the number of failed attempts was stored in $failed_attempts
        krsort($throttle);
        foreach ($throttle as $attempts => $delay) {
            if ($failed_attempts > $attempts) {
                // we need to throttle based on delay
                if (is_numeric($delay)) {
                    $remaining_delay = time() - $latest_attempt - $delay;
                    // output remaining delay
                    echo 'You must wait ' . $remaining_delay . ' seconds before your next login attempt';
                } else {
                    // code to display recaptcha on login form goes here
                }
                break;
            }
        }        
    }
}

使用reCaptchaである一定の閾値を攻撃から複数の拠点が停止し、通常のサイトのユーザーのような経験を大幅に遅れのための正当な失敗したログインのことを伝え、"よくやった!

他のヒント

次の3つの基本的な方法があります。店舗セッション情報、店舗クッキー情報や店舗のIP情報を

あなたがセッション情報を使用する場合は、

、エンドユーザ(攻撃者)は、強制的に新しいセッションを呼び出すことができ、あなたの戦術バイパスして、遅延なしで再度ログイン。セッションは非常に単純で、単にセッション変数にユーザーの最後の既知のログイン時刻を格納し、実装し、現在の時間に対してそれと一致するようにしている、と確認し遅延が十分な長されています。

あなたはクッキーを使用している場合、攻撃者は単にクッキーを拒否することができ、すべてのすべてで、これは実際に実行可能なものではありません。

あなたは、好ましくは、データベースに、何らかの形でIPアドレスからストアログイン試行する必要がありますIPアドレスを追跡する場合。ユーザーの試行がログオンするときに、単にIPのあなたの記録リストを更新。あなたは、いくつかの時間で活動されていないIPアドレスをダンプ、合理的な間隔でこのテーブルをパージする必要があります。落とし穴は(常に落とし穴があります)、一部のユーザーは、IPアドレスを共有することになるかもしれない、と境界条件であなたの遅延が不注意のユーザーに影響を与える可能性があるということです。あなた以来だ追跡はログインを失敗した、とだけ失敗したログイン、これはあまりにも多くの痛みを引き起こすべきではありません。

ログインプロセスのニーズは両方の成功と失敗したログインのためにその速度を下げます。ログイン試行自体は速く、約1秒未満であってはなりません。それがある場合は、ブルートフォースは、成功は失敗よりも短いので試みが失敗したことを知って遅延を使用しています。その後、より多くの組み合わせが毎秒評価することができます。

はマシンごとの同時ログイン試行回数は、ロードバランサによって制限する必要があります。最後に、あなただけの同じユーザーまたはパスワードが複数のユーザー/パスワードログイン試行によって再使用されている場合に追跡する必要があります。人間はより速くminiteあたり200語程度以上入力することはできません。だから、連続または同時ログイン試行miniteあたりより速く200本の言葉はマシンのセットからです。それはあなたの顧客ではないとして、これらは、このように安全にブラックリストにパイプすることができます。ホストあたりのブラックリスト時間は約1秒よりも大きくする必要はありません。これは決して人間の不便さが、ブルートフォースの試みシリアルまたはパラレルにかかわらます。

で大混乱を果たしています

40億の別々のIPアドレス上で並列に実行し、毎秒1つの組み合わせで2つの* 10 ^ 19の組み合わせは、探索空間としての排気に158年かかるだろう。 40億回の攻撃者に対して、ユーザーごとに最後の1日に、あなたは最低でも9ヶ所の長い完全にランダムな英数字のパスワードが必要です。 、少なくとも13ヶ所のロングパスフレーズで1.7 * 10 ^ 20個の組み合わせを、ユーザーのトレーニングを検討します。

この遅延は、パスワードのハッシュファイルではなく、ブルートフォースあなたのサイトを盗むために、攻撃者が動機となります。使用して、技術をハッシング、命名、承認されました。 1秒間のインターネットIPの全人口を禁止、dealy人間には理解されることなく、並列の攻撃の影響を制限します。最後に、あなたのシステムが禁止システムにいくつかの応答なしで1秒間に1000回の以上の失敗したログオン試行を可能にし、セキュリティ計画は上の仕事に大きな問題がある場合。修正ということは、最初にすべての応答を自動化します。

session_start();
$_SESSION['hit'] += 1; // Only Increase on Failed Attempts
$delays = array(1=>0, 2=>2, 3=>4, 4=>8, 5=>16); // Array of # of Attempts => Secs

sleep($delays[$_SESSION['hit']]); // Sleep for that Duration.

またはCyroのにより示唆されるようにます:

sleep(2 ^ (intval($_SESSION['hit']) - 1));

これは、ビット荒いですが、基本的なコンポーネントがあります。あなたがこのページを更新する場合は、遅延を更新するたびに長くなります。

また、あなたがIPによって失敗した試行の回数をチェックし、データベースにカウントを保つことができます。 IPに基づいて、それを使用して、あなたの側にデータを保持することにより、あなたは遅れを停止するために彼らのCookieをクリアすることができることからユーザーを防ぐます。

基本的には、最初のコードは次のようになります:

$count = get_attempts(); // Get the Number of Attempts

sleep(2 ^ (intval($count) - 1));

function get_attempts()
{
    $result = mysql_query("SELECT FROM TABLE WHERE IP=\"".$_SERVER['REMOTE_ADDR']."\"");
    if(mysql_num_rows($result) > 0)
    {
        $array = mysql_fetch_assoc($array);
        return $array['Hits'];
    }
    else
    {
        return 0;
    }
}

StoreはIPによって、データベース内の試みを失敗します。 (ログインシステムを持っているので、私はあなたがこれを行う方法をよく知っていると仮定します。)

明らかに、セッションが魅力的な方法であるが、実際に専用の誰かが非常に簡単に彼らは単に完全にスロットルを回避するために失敗した試みに彼らのセッションクッキーを削除することができますことを実現することができます。

ログインしようとするには、

は、最新の試みの時間があった、とどのように多くの最近の(たとえば、最後の15分)ログイン試行フェッチます。

$failed_attempts = 3; // for example
$latest_attempt = 1263874972; // again, for example
$delay_in_seconds = pow(2, $failed_attempts); // that's 2 to the $failed_attempts power
$remaining_delay = time() - $latest_attempt - $delay_in_seconds;
if($remaining_delay > 0) {
    echo "Wait $remaining_delay more seconds, silly!";
}

あなたはセッションを使用することができます。いつでもユーザーがログインに失敗し、あなたは試行回数を格納した値を増やします。あなたは試行回数から必要な遅延を把握したり、ユーザーが同様にセッションに再試行するよう許可されている実際の時間を設定することができます。

Aより信頼性の高い方法は、その特定のIPアドレスのデータベース内の試みと新しいトライ-時間を保存することです。

IMHO、DOS攻撃に対する防御は良くない、あなたのPHPコードで、ウェブサーバレベル(または多分ネットワークハードウェア内)で取り扱われます。

私は一般的にログイン履歴やログインの試行テーブルを作成します。試行の表では、遅延に必要かどうかを確認するためのテーブルに対して、ユーザ名、パスワード、IPアドレスなどのクエリをログに記録します。 Iは、与えられた時間(例えば時間)で20を超える試行を完全に遮断することをお勧めします。

上記の議論を1として、セッション、クッキーやIPアドレスは有効ではない - すべては、攻撃者によって操作することができます。

。 これはで伐採から有効なユーザーをブロックすることによって、サイトにDOSへの攻撃を可能にすること。

あなたはブルートフォース攻撃を防ぎたい場合は、唯一の現実的な解決策を提供したユーザ名に試行回数をベースにある、しかし、ノート>

例えばます。

$valid=check_auth($_POST['USERNAME'],$_POST['PASSWD']);
$delay=get_delay($_POST['USERNAME'],$valid);

if (!$valid) {
   header("Location: login.php");
   exit;
}
...
function get_delay($username,$authenticated)
{
    $loginfile=SOME_BASE_DIR . md5($username);
    if (@filemtime($loginfile)<time()-8600) {
       // last login was never or over a day ago
       return 0;
    }
    $attempts=(integer)file_get_contents($loginfile);
    $delay=$attempts ? pow(2,$attempts) : 0;
    $next_value=$authenticated ? 0 : $attempts + 1;
    file_put_contents($loginfile, $next_value);
    sleep($delay); // NB this is done regardless if passwd valid
    // you might want to put in your own garbage collection here
 }
書かれたように、この手続き漏れのセキュリティ情報という

注 - すなわち、それはユーザーがログイン(攻撃者のための応答時間が0に低下しますしよう)したときに表示するシステムを攻撃する誰かのために可能になります。遅延は、ファイルの以前の遅延とタイムスタンプに基づいて計算されるように、あなたはチューニングアルゴリズムも可能性があります。

HTH

C

クッキーまたはセッションベースの方法は、この場合、当然役に立ちません。アプリケーションは、以前のログイン試行のIPアドレスまたはタイムスタンプ(あるいはその両方)を確認しなければならない。

攻撃者は、複数のIPからの彼/彼女の要求を開始すると、複数のユーザーが同じIPからサーバーに接続する場合は面倒なことができていた場合、

アンIPチェックをバイパスすることができます。後者の場合、誰かが一定の期間のために、そのユーザー名でログインするから同じIPを共有するすべての人を妨げる数回のログインに失敗します。

は、タイムスタンプのチェックは、上記と同じ問題を抱えている:誰もがちょうど複数回試みることによって、特定のアカウントにログインから皆を防ぐことができます。最後の試行のためのキャプチャの代わりに、長い待ち時間を使用すると、おそらく良い回避策です。

ログインシステムは防ぐ必要がある唯一の余分なものは、試行チェック機能で競合状態です。例えば、次の擬似コードで

$time = get_latest_attempt_timestamp($username);
$attempts = get_latest_attempt_number($username);

if (is_valid_request($time, $attempts)) {
    do_login($username, $password);
} else {
    increment_attempt_number($username);
    display_error($attempts);
}
攻撃者は、ログインページにの同時の要求を送信した場合、

はどうなりますか?おそらく、すべての要求は、同じ優先度で実行されます、そしてチャンスは他の人が2行目を過ぎた前に何の要求がincrement_attempt_number命令になっていないということです。だから、すべてのリクエストは、同じ$時間と$試行値を取得し、実行されます。セキュリティ問題のこの種を防止することは、複雑なアプリケーションのために困難なことや、データベースのいくつかのテーブル/行のロックとロック解除が含まもちろん、アプリケーションのダウンを遅くすることができます。

短い答えは:Doがこれをしません。あなたは、あなたもあなたの状況を悪化させる可能性があり、ブルート強制から身を守ることはありません。

提案されたソリューションのいずれも動作しないでしょう。あなたがスロットリングのための任意のパラメータとしてIPを使用している場合、攻撃者は単にIPの膨大な数を越えた攻撃にまたがるます。あなたがセッション(クッキー)を使用する場合、攻撃者はただのクッキーをドロップします。全ての合計あなたはブルート強制的に攻撃者が克服できなかったものは絶対に存在しないこと、であると考えることができます。

は一つのことにはかかわらず、ある - 。あなたはちょうどあなたがユーザがスロットルログインしようとした頻度を追跡する他のすべてのパラメータを見ていない、そうでログインしようとしたユーザ名に依存しています。しかし、攻撃者があなたを傷つけるしたいと考えています。彼はこのことを認識した場合、彼はブルートフォースユーザー名だけでもされます。

これは、彼らがログインしようとすると、ほぼすべてのユーザーのあなたの最大値に絞られているになります。あなたのウェブサイトは無用になります。攻撃者:成功

あなたは200msの周りのために一般的には、パスワードのチェックを遅らせる可能性 - ウェブサイトのユーザーは、ほとんどのことを気付くことはありません。しかし、ブルート収納箱はなります。 (ここでも彼はIPアドレスにまたがる可能性が)しかし、このすべてのものがブルート強制またはDDoS攻撃からあなたを守るんだろう - 。あなたがいないプログラムでできる限り

これを行うための唯一の方法は、インフラストラクチャを使用しています。

あなたはあなたのパスワードをハッシュする代わりに、MD5やSHA-Xのbcryptの使用する必要があります誰かがあなたのデータベースを盗んであれば(私はあなたが共有または管理対象ホスト上にあると思いますので)、これは多くの困難パスワードを解読するようになります。

申し訳ありませんが、あなたを失望が、ここですべてのソリューションが弱点を持っているし、バックエンドのロジック内でそれらを克服する方法はありません。

のために

cballuoは、優れた答えを提供します。私はちょうどサポートのmysqliのその更新されたバージョンを提供することで恩返しをしたかったです。私は少しSQL文およびその他の小さなもので、テーブル/フィールドの列を変更しますが、それはmysqliの同等を探している人を助ける必要があります。

function get_multiple_rows($result) {
  $rows = array();
  while($row = $result->fetch_assoc()) {
    $rows[] = $row;
  }
  return $rows;
}

$throttle = array(10 => 1, 20 => 2, 30 => 5);

$query = "SELECT MAX(time) AS attempted FROM failed_logins";    

if ($result = $mysqli->query($query)) {

    $rows = get_multiple_rows($result);

$result->free();

$latest_attempt = (int) date('U', strtotime($rows[0]['attempted'])); 

$query = "SELECT COUNT(1) AS failed FROM failed_logins WHERE time > DATE_SUB(NOW(), 
INTERVAL 15 minute)";   

if ($result = $mysqli->query($query)) {

$rows = get_multiple_rows($result);

$result->free();

    $failed_attempts = (int) $rows[0]['failed'];

    krsort($throttle);
    foreach ($throttle as $attempts => $delay) {
        if ($failed_attempts > $attempts) {
                echo $failed_attempts;
                $remaining_delay = (time() - $latest_attempt) - $delay;

                if ($remaining_delay < 0) {
                echo 'You must wait ' . abs($remaining_delay) . ' seconds before your next login attempt';
                }                

            break;
        }
     }        
  }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top