質問

具体的には、これは、サーバー上のセッションを識別するためにクライアント セッション Cookie を使用する場合に関係します。

Web サイト全体に SSL/HTTPS 暗号化を使用するのが最良の答えでしょうか。また、中間者攻撃が既存のクライアント セッション Cookie を盗聴できないという最善の保証がありますか?

次に、セッション Cookie に保存されているセッション値自体に何らかの暗号化を使用するのが最善策でしょうか。

悪意のあるユーザーがマシンに物理的にアクセスできる場合でも、ファイルシステムを参照して有効なセッション Cookie を取得し、それを使用してセッションをハイジャックすることができます。

役に立ちましたか?

解決

セッション値を暗号化しても効果はありません。セッション Cookie はすでに任意の値であるため、暗号化すると盗聴可能な別の任意の値が生成されるだけです。

唯一の本当の解決策は HTTPS です。サイト全体で SSL を使用したくない場合 (パフォーマンスに懸念がある可能性があります)、機密領域のみを SSL で保護することで問題を解決できる可能性があります。これを行うには、まずログイン ページが HTTPS であることを確認します。ユーザーがログインするとき、通常のセッション Cookie に加えて、セキュア Cookie (ブラウザが SSL リンク経由でのみ送信することを意味します) を設定します。次に、ユーザーが「機密」領域の 1 つにアクセスしたときに、HTTPS にリダイレクトし、その安全な Cookie の存在を確認します。実際のユーザーはそれを持っていますが、セッションハイジャッカーは持っていません。

編集:この回答はもともと 2008 年に書かれたものです。2016 年現在、サイト全体に SSL を導入しない理由はありません。平文の HTTP はもう必要ありません。

他のヒント

SSL はスニッフィング攻撃にのみ役立ちます。攻撃者があなたのマシンにアクセスした場合、あなたの安全な Cookie もコピーできると思います。

少なくとも、古い Cookie はしばらくすると価値が失われるようにしてください。ハイジャック攻撃が成功したとしても、Cookie が機能しなくなると阻止されます。ユーザーが 1 か月以上前にログインしたセッションの Cookie を持っている場合は、パスワードを再入力するように求めます。ユーザーがサイトの「ログアウト」リンクをクリックするたびに、古いセッション UUID が再度使用できないようにしてください。

このアイデアがうまくいくかどうかはわかりませんが、次のようになります。セッション Cookie にシリアル番号を追加します。おそらく次のような文字列です。

SessionUUID、シリアル番号、現在の日付/時刻

この文字列を暗号化し、セッション Cookie として使用します。シリアル番号を定期的に変更します (おそらく Cookie が 5 分経過したときに変更してから、Cookie を再発行します)。必要に応じて、ページビューごとに再発行することもできます。サーバー側では、そのセッションに対して発行した最後のシリアル番号を記録しておいてください。誰かが間違ったシリアル番号を含む Cookie を送信した場合、攻撃者が以前に傍受した Cookie を使用している可能性があることを意味するため、セッション UUID を無効にし、ユーザーにパスワードを再入力して新しい Cookie を再発行するように求めます。

ユーザーは複数のコンピュータを所有しているため、複数のアクティブなセッションが存在する可能性があることに注意してください。コンピュータを切り替えるたびに再度ログインを強制するようなことは行わないでください。

PHP セキュリティに関する本を読んでみようかと考えたことはありますか?強くお勧めします。

私は、SSL 認定されていないサイトに対して次の方法で多くの成功を収めてきました。

  1. 同じアカウントでの複数のセッションを禁止し、IP アドレスのみでこれをチェックしていないことを確認してください。むしろ、ログイン時に生成され、ユーザーセッションとともにデータベースに保存されているトークンや、IP アドレス、HTTP_USER_AGENT などによってチェックします。

  2. 関係ベースのハイパーリンクを使用すると、リンクが生成されます(例: http://example.com/secure.php?token=2349df98sdf98a9asdf8fas98df8 )リンクは、Xバイト(優先サイズ)ランダムな塩漬けMD5文字列で追加されます。ページのリダイレクト上、ランダムに生成されたトークンは要求されたページに対応します。

    • リロード時に、いくつかのチェックが行われます。
    • 発信元IPアドレス
    • HTTP_USER_AGENT
    • セッショントークン
    • 要点がわかります。
  3. 有効期間が短いセッション認証 Cookie。上で投稿したように、セッションの有効性への直接参照の 1 つである安全な文字列を含む Cookie を使用することは良いアイデアです。x 分ごとに期限切れにし、そのトークンを再発行し、セッションを新しいデータと再同期します。データに不一致がある場合は、ユーザーをログアウトするか、セッションを再認証してもらいます。

私はこのテーマの専門家ではありませんが、この特定のトピックについては少し経験があります。これが誰かの役に立てば幸いです。

// Collect this information on every request
$aip = $_SERVER['REMOTE_ADDR'];
$bip = $_SERVER['HTTP_X_FORWARDED_FOR'];
$agent = $_SERVER['HTTP_USER_AGENT'];
session_start();

// Do this each time the user successfully logs in.
$_SESSION['ident'] = hash("sha256", $aip . $bip . $agent);

// Do this every time the client makes a request to the server, after authenticating
$ident = hash("sha256", $aip . $bip . $agent);
if ($ident != $_SESSION['ident'])
{
    end_session();
    header("Location: login.php");
    // add some fancy pants GET/POST var headers for login.php, that lets you
    // know in the login page to notify the user of why they're being challenged
    // for login again, etc.
}

これは、ユーザーのセッションに関する「コンテキスト」情報、つまり単一セッションの存続期間中に変更すべきではない情報をキャプチャすることです。ユーザーは米国と中国の両方で同時にコンピューターを使用するわけではありません。したがって、同じセッション内で IP アドレスが突然変更された場合は、セッション ハイジャックの試みを強く示唆するため、セッションを終了してユーザーに再認証を強制することでセッションを保護します。これによりハッキングの試みが阻止され、攻撃者はセッションにアクセスする代わりにログインを強制されます。ユーザーに試行を通知します (少し ajax を使用します)。そして、ユーザーは少しイライラして通知を受け、セッション/情報は保護されます。

ユーザー エージェントと X-FORWARDED-FOR を導入して、プロキシ/ネットワークの背後にあるシステムのセッションの一意性を取得するために最善を尽くします。さらに多くの情報を使用できる場合がありますので、自由に創造力を発揮してください。

100%ではありませんが、かなり効果があります。

ユーザーが Web サイトから離れて戻ってきたときに、セッションを保護したり、セッションを期限切れにしたりするためにできることは他にもあります。おそらく、再度ログインを強制することになります。空の HTTP_REFERER (URL バーにドメインが入力されている) をキャプチャすることでユーザーの離脱と復帰を検出したり、HTTP_REFERER の値がドメインと等しいかどうかを確認したりできます (ユーザーが外部/細工されたリンクをクリックして、URL バーにアクセスした)サイト)。

セッションを期限切れにし、無期限に有効なままにしないでください。

Cookie はセッション ハイジャックの攻撃ベクトルの 1 つであるため、Cookie に依存しないでください。Cookie は盗まれる可能性があります。

で説明されている Secure Cookie プロトコルを試してください。 これ Liu、Kovacs、Huang、Gouda による論文:

文書に記載されているように:

クライアントとサーバーの間で実行される安全なCookieプロトコルは、次の4つのサービスを提供する必要があります。認証、機密性、完全性、およびリプレイ防止。

導入の容易さについては、次のとおりです。

効率の観点から、私たちのプロトコルにはデータベースの検索や公開キーの暗号化は含まれません。展開性の観点から、当社のプロトコルは既存のWebサーバーに簡単に展開でき、インターネットCookieの仕様を変更する必要はありません。

要するに:安全で軽量で、私にとっては素晴らしいものです。

セッション ハイジャックを 100% 防ぐ方法はありませんが、何らかのアプローチで攻撃者がセッションをハイジャックする時間を短縮することはできます。

セッションハイジャックを防ぐ方法:

1 - 常に SSL 証明書を使用したセッションを使用します。

2 - httponly を true に設定してセッション Cookie のみを送信します (JavaScript がセッション Cookie にアクセスするのを防ぎます)

2 - ログイン時とログアウト時にセッション再生成 ID を使用します(注:連続した Ajax リクエストがある場合は、複数のセッションを作成する可能性があるため、リクエストごとにセッションの再生成を使用しないでください)。

3 - セッションタイムアウトを設定する

4 - ブラウザ ユーザー エージェントを $_SESSION 変数に保存し、リクエストごとに $_SERVER['HTTP_USER_AGENT'] と比較します

5 - トークン Cookie を設定し、その Cookie の有効期限を 0 (ブラウザが閉じるまで) に設定します。リクエストごとに cookie 値を再生成します (ajax リクエストの場合は、トークン cookie を再生成しません)。元:

    //set a token cookie if one not exist
    if(!isset($_COOKIE['user_token'])){
                    //generate a random string for cookie value
        $cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM));

        //set a session variable with that random string
        $_SESSION['user_token'] = $cookie_token;
        //set cookie with rand value
        setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true);
    }

    //set a sesison variable with request of www.example.com
    if(!isset($_SESSION['request'])){
        $_SESSION['request'] = -1;
    }
    //increment $_SESSION['request'] with 1 for each request at www.example.com
    $_SESSION['request']++;

    //verify if $_SESSION['user_token'] it's equal with $_COOKIE['user_token'] only for $_SESSION['request'] > 0
    if($_SESSION['request'] > 0){

        // if it's equal then regenerete value of token cookie if not then destroy_session
        if($_SESSION['user_token'] === $_COOKIE['user_token']){
            $cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM));

            $_SESSION['user_token'] = $cookie_token;

            setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true);
        }else{
            //code for session_destroy
        }

    }

            //prevent session hijaking with browser user agent
    if(!isset($_SESSION['user_agent'])){
        $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
    }

    if($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']){
      die('session hijaking - user agent');
    }

注記:ajaxリクエストでトークンクッキーを再生しないでください注:上記のコードは一例です。注記:ユーザーがログアウトした場合は、Cookie トークンとセッションを破棄する必要があります。

6 - 一部のユーザーの IP はリクエストごとに変わるため、セッション ハイジャックを防ぐためにユーザー IP を使用するのは良い方法ではありません。有効なユーザーに影響を与えるもの

7 - 個人的にはセッション データをデータベースに保存しますが、どの方法を採用するかはあなた次第です

私のアプローチに間違いを見つけた場合は、修正してください。セッションハイジャックを防ぐその他の方法がある場合は、教えてください。

セッション ID には増加する整数を使用しないようにしてください。GUID またはその他のランダムに生成された長い文字列を使用する方がはるかに優れています。

セッションハイジャックに対する保護を作成する方法は数多くありますが、それらはすべてユーザーの満足度を低下させるか、安全ではありません。

  • IP および/または X-FORWARDED-FOR チェック。これらは機能し、かなり安全です...しかし、ユーザーの痛みを想像してみてください。WiFi を備えたオフィスに来て、新しい IP アドレスを取得すると、セッションが失われます。再度ログインする必要があります。

  • ユーザーエージェントがチェックします。上記と同様に、ブラウザの新しいバージョンがリリースされ、セッションが失われます。さらに、これらは非常に簡単に「ハッキング」されます。ハッカーにとって偽の UA 文字列を送信することは簡単です。

  • ローカルストレージトークン。ログオン時にトークンを生成し、ブラウザーのストレージに保存し、暗号化された Cookie (サーバー側で暗号化) に保存します。これによるユーザーへの副作用はありません (localStorage はブラウザのアップグレードを通じて維持されます)。これは、隠蔽によるセキュリティにすぎないため、それほど安全ではありません。さらに、JS にロジック (暗号化/復号化) を追加して、さらに難読化することもできます。

  • Cookieの再発行。おそらくこれが正しい方法です。重要なのは、一度に 1 つのクライアントのみが Cookie を使用できるようにすることです。したがって、アクティブなユーザーは 1 時間以内に Cookie を再発行することになります。新しいクッキーが発行されると、古いクッキーは無効になります。ハッキングは依然として可能ですが、実行するのははるかに困難です。ハッカーまたは正当なユーザーのいずれかがアクセスを拒否されます。

ログインフェーズ中に、クライアントとサーバーが秘密のソルト値に同意できると考えてみましょう。その後、サーバーは更新ごとにカウント値を提供し、クライアントが (シークレット ソルト + カウント) のハッシュで応答することを期待します。潜在的なハイジャッカーには、この秘密のソルト値を取得する方法がないため、次のハッシュを生成できません。

私の知る限り、セッションオブジェクトはWebサーバーに保存されているため、クライアントからはアクセスできません。ただし、セッション ID は Cookie として保存され、Web サーバーがユーザーのセッションを追跡できるようになります。

セッション ID を使用したセッション ハイジャックを防ぐために、リモート アドレスとリモート ポートという 2 つの属性の組み合わせを使用して作成されたハッシュ文字列をセッション オブジェクト内に保存できます。この文字列は、リクエスト オブジェクト内の Web サーバーでアクセスできます。これらの属性は、ユーザー セッションをユーザーがログインしたブラウザに結び付けます。

ユーザーが同じシステム上の別のブラウザまたはシークレット モードからログインした場合、IP アドレスは同じままですが、ポートは異なります。したがって、アプリケーションにアクセスすると、ユーザーには Web サーバーによって別のセッション ID が割り当てられます。

以下は、あるセッションから別のセッションにセッション ID をコピーして実装およびテストしたコードです。かなりうまくいきます。抜け穴がある場合は、どのようにシミュレーションしたか教えてください。

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    HttpSession session = request.getSession();
    String sessionKey = (String) session.getAttribute("sessionkey");
    String remoteAddr = request.getRemoteAddr();
    int remotePort = request.getRemotePort();
    String sha256Hex = DigestUtils.sha256Hex(remoteAddr + remotePort);
    if (sessionKey == null || sessionKey.isEmpty()) {
        session.setAttribute("sessionkey", sha256Hex);
        // save mapping to memory to track which user attempted
        Application.userSessionMap.put(sha256Hex, remoteAddr + remotePort);
    } else if (!sha256Hex.equals(sessionKey)) {
        session.invalidate();
        response.getWriter().append(Application.userSessionMap.get(sessionKey));
        response.getWriter().append(" attempted to hijack session id ").append(request.getRequestedSessionId()); 
        response.getWriter().append("of user ").append(Application.userSessionMap.get(sha256Hex));
        return;
    }
    response.getWriter().append("Valid Session\n");
}

に示されている例を使用して、SHA-2 アルゴリズムを使用して値をハッシュしました。 SHA-256 baeldung でのハッシュ

コメントをお待ちしております。

リスクを軽減するために、発信元 IP をセッションに関連付けることもできます。この方法では、攻撃者がセッションを使用できるようにするには、同じプライベート ネットワーク内にいる必要があります。

リファラーヘッダーをチェックすることもオプションですが、それらはより簡単に偽装されます。

次の方法で保護します。

$ip=$_SERVER['REMOTE_ADDER'];
$_SESSEION['ip']=$ip;
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top