コンピュータ ネットワーク セキュリティにおいて、セッション固定攻撃は、ある人が別の人のセッション IDを固定 (検索または設定) できるようにするシステムの脆弱性を悪用しようとします。ほとんどのセッション固定攻撃は Web ベースであり、そのほとんどはURL (クエリ文字列) または POST データから受け入れられるセッション ID に依存しています。
攻撃シナリオ
アリスは銀行に口座を持っているhttp://unsafe.example.com/
マロリーはアリスの銀行から彼女のお金を狙うつもりです。
アリスはマロリーに対してある程度の信頼を寄せており、マロリーが送ってくるリンクを訪問します。
単純な攻撃シナリオ
単純なシナリオ:
http://unsafe.example.com/Mallory は、 が任意のセッション識別子を受け入れ、クエリ文字列からセッション識別子を受け入れ、セキュリティ検証を行わないことを確認しました。http://unsafe.example.com/したがって、 は安全ではありません。- マロリーはアリスに電子メールを送信します。「ねえ、これを見てください。私たちの銀行に、すばらしい新しい口座概要機能があります。
http://unsafe.example.com/?SID=I_WILL_KNOW_THE_SID」マロリーは SID を に固定しようとしていますI_WILL_KNOW_THE_SID。 - アリスは興味を持って訪問します
http://unsafe.example.com/?SID=I_WILL_KNOW_THE_SID。通常のログオン画面がポップアップ表示され、アリスはログオンします。 - マロリーが訪問し
http://unsafe.example.com/?SID=I_WILL_KNOW_THE_SID、アリスのアカウントに無制限にアクセスできるようになりました。
サーバーが生成したSIDを使用した攻撃
サーバーがサーバー生成のセッション識別子のみを受け入れる場合、固定化の危険はないというのが誤解です。これは誤りです。
シナリオ:
- Mallory がアクセスし
http://vulnerable.example.com/、返される SID を確認します。たとえば、サーバーは次のように応答する場合がありますSet-Cookie: SID=0D6441FEA4496C2。 - マロリーはアリスに電子メールを送信できるようになりました。「当銀行のこの新しい便利な機能をチェックしてください。
http://vulnerable.example.com/?SID=0D6441FEA4496C2」 - アリスは固定セッション識別子を使用してログオンします
SID=0D6441FEA4496C2。 - マロリーが訪問し
http://vulnerable.example.com/?SID=0D6441FEA4496C2、アリスのアカウントに無制限にアクセスできるようになりました。
クロスサブドメインCookieを使用した攻撃
このタイプの攻撃は、ユーザーのブラウザの脆弱性に依存しない点を除けば、クロスサイト Cookie 攻撃に似ています。むしろ、ワイルドカード Cookie がサブドメインによって設定され、それらの Cookie が他のサブドメインに影響を及ぼす可能性があるという事実に依存します。
シナリオ:
- ウェブサイトが
www.example.com信頼できない第三者にサブドメインを配布する - そのような当事者の1人であるマロリーは、現在を支配しており
evil.example.com、アリスを自分のサイトに誘い込む。 - への訪問はアリスのブラウザ上の
evil.example.comドメインにセッションクッキーを設定します.example.com - アリスが訪問すると
www.example.com、この Cookie がリクエストとともに送信され、アリスはマロリーの Cookie によって指定されたセッションを持つことになります。 - アリスがログオンすると、マロリーは彼女のアカウントを使用できるようになります。
www.example.comこの攻撃が完了すると、マロリーはアリスとして
アクセスできるようになります。
セッション固定攻撃[1]を悪用するためには、必ずしもユーザーのログインは必須ではありません。また、これらの認証されていない攻撃は、サブドメイン間の Cookie 攻撃に限定されませんが、サブドメイン攻撃の影響は、これらの認証されていないシナリオに関連しています。たとえば、Mallory は、悪意のあるサイトの URL を提供して、セッションを認証されていないシナリオに固定し、それらの手法を使用してターゲットを悪用する可能性があります。これには、認証されていないシナリオ (フォームや登録など) を悪用するシナリオと、確立されたセッションをユーザーに提供してログインを完全にバイパスする機能の両方が含まれます。
たとえば、マロリーがwww.example.comにユーザーA1iceを作成し、そのユーザーをログインさせて現在の有効なセッション ID を取得するとします。次に、マロリーはevil.example.comの URL でアリスを罠にかけ、そのセッション Cookie をアリスのブラウザに固定し (前述のとおり)、特定のトランザクション (または、より広範な使用) を完了するためにwww.example.comにリダイレクトします。こうして、マロリーは元のログインからセッションをゴースト化して、データをスクレイピングし、'www.example.com' で 'A1ice' として操作を実行できます。アリスがうまく騙されてアカウントにクレジットカードを保存した場合、マロリーはそのカードを使って購入を行う可能性があります。
対策
GET / POST変数からのセッション識別子を受け入れない
URL (クエリ文字列、GET 変数) または POST 変数内のセッション識別子は、この攻撃を簡素化するため推奨されません。GET / POST 変数を設定するリンクやフォームを作成するのは簡単です。
- ユーザーがアドレスバーから「興味深いリンク」を切り取ってチャット、フォーラム、コミュニティなどに貼り付けると、SID が他の人に漏洩します。
- SID はさまざまな場所 (ブラウザ履歴ログ、Web サーバー ログ、プロキシ ログなど) に保存されます。
注意: クッキーはタブとポップアップされたブラウザ ウィンドウ間で共有されます。システムで同じドメイン (www.example.com/?code=site1 と www.example.com/?code=site2) にアクセスする必要がある場合、タブ間でクッキーが競合する可能性があります。
この制限を克服するには、URL でセッション識別子を送信することが必要になる場合があります。可能であれば、cookie でドメインの競合が発生しないように、site1.example.com または site2.example.com を使用してください。これにより、追加の SSL 証明書のコストが発生する可能性があります。
この動作は、別のタブを開いて検索結果を並べて表示しようとすると、多くのサイトで見られます。セッションの 1 つが使用できなくなります。
最善の解決策: 本人確認
この攻撃は、ユーザーがログインするときにセッション ID を変更することで、大部分回避できます。ユーザー固有のすべてのリクエストで、ユーザーがサイトで認証される (「ログイン」する) 必要がある場合、攻撃者は被害者のログイン セッションの ID を知る必要があります。ただし、被害者が固定セッション ID のリンクにアクセスすると、自分として「重要な」操作を行うには、アカウントにログインする必要があります。この時点で、セッション ID は変更され、攻撃者は匿名セッション ID で「重要な」操作を行うことができなくなります。
同様の手法を使用してフィッシング問題を解決できます。ユーザーが自分のアカウントを 2 つのパスワードで保護すれば、フィッシングの問題をかなり解決できます。
この手法は、クロスサイトリクエストフォージェリ攻撃 に対しても有効です。
解決策: HTTP Cookieにセッション識別子を保存する
最近のほとんどのシステムでは、セッション識別子はデフォルトでHTTP Cookieに保存されます。セッションシステムが GET/POST 値を無視する限り、セキュリティ レベルは中程度です。[引用が必要]ただし、このソリューションはクロスサイト リクエスト フォージェリに対して脆弱であり、REST のステートレス要件を満たしていません。
解決策: SSL / TLSセッション識別子を利用する
HTTPSセキュリティを有効にすると、一部のシステムではアプリケーションがSSL/TLSセッション識別子を取得できるようになります。SSL/TLS セッション識別子の使用は非常に安全ですが、多くの Web 開発言語では、そのための堅牢な組み込み機能が提供されていません。
リクエストごとにSIDを再生成する
セッション固定化に対する対策は、リクエストごとに新しいセッション識別子 (SID) を生成することです。これを実行すると、攻撃者がユーザーを騙して既知の SID を受け入れさせたとしても、攻撃者が SID を再利用しようとしたときにその SID は無効になります。このようなシステムの実装は、次の例に示すように簡単です。
- HTTP リクエストから以前のセッション識別子を取得します
OLD_SID。 OLD_SIDが null、空、または SID= を持つセッションが存在しない場合はOLD_SID、新しいセッションを作成します。NEW_SID安全な乱数ジェネレータを使用して新しいセッション識別子を生成します。- セッションを SID= で識別する
NEW_SID(SID= では識別しなくなるOLD_SID) - 新しい SID をクライアントに送信します。
例:
マロリーがアリスを騙して を訪問させることに成功した場合http://victim.example.com/?SID=I_KNOW_THE_SID、次の HTTP リクエストが に送信されますvictim.example.com:
GET /?SID=I_KNOW_THE_SID HTTP / 1.1
ホスト: victim.example.com
victim.example.comは を受け入れますがSID=I_KNOW_THE_SID、これは通常は良くありません。ただし、victim.example.comはセッションの再生成を実行するため安全です。victim.example.com次の応答が返されます。
HTTP / 1.1 200 OK
Cookie の設定: SID=3134998145AB331F
SID=3134998145AB331Fアリスは、マロリーには知られていない無効な を使用しますSID=I_KNOW_THE_SID。したがって、マロリーはセッション固定の試みに失敗します。
残念ながら、セッションの再生成は常に可能であるとは限りません。ActiveX や Java アプレットなどのサードパーティ製ソフトウェアが使用されている場合、およびブラウザ プラグインがサーバーと通信している場合に問題が発生することが知られています。サードパーティ製ソフトウェアによってログアウトが発生したり、セッションが 2 つの別々のセッションに分割されたりする可能性があります。
セッションの実装に GET または POST 変数を介した SID の送信が含まれる場合、ユーザーは以前のリクエストからの古い無効なセッション識別子を使用することになるため、ほとんどのブラウザの「戻る」ボタンが使用できなくなる可能性があります。
サーバーが生成したSIDのみを受け入れる
セキュリティを向上させる方法の 1 つは、サーバーによって生成されていないセッション識別子を受け入れないことです。ただし、前述のように、これによってすべてのセッション固定攻撃を防止できるわけではありません。
if ( ! isset ( $_SESSION [ 'SERVER_GENERATED_SID' ])) {
session_destroy (); // セッション内のすべてのデータを破棄します
}
session_regenerate_id (); // 新しいセッション識別子を生成します
$_SESSION [ 'SERVER_GENERATED_SID' ] = true ;
ログアウト機能
ログアウト機能は、ユーザーがセッションでそれ以上のリクエストを許可しないように指定できるため便利です。したがって、攻撃はセッションがアクティブな間のみ有効です。次のコードはクロスサイト リクエスト フォージェリチェックを実行しないため、攻撃者がユーザーを Web アプリケーションから強制的にログアウトさせる可能性があることに注意してください。
if ( logout ) {
session_destroy (); // セッション内のすべてのデータを破棄する
}
古いSIDのタイムアウト
この防御は実装が簡単で、無人のまま放置されたマシンを使用して許可されていないユーザーが許可されたユーザーのアカウントにアクセスするのを防ぐ保護手段を提供するという利点があります。
その SID による最後のアクセスのタイムスタンプを含むセッション変数を保存します。その SID が再度使用されるときに、現在のタイムスタンプをセッションに保存されているタイムスタンプと比較します。差が事前定義された数値 (たとえば 5 分) より大きい場合は、セッションを破棄します。それ以外の場合は、現在のタイムスタンプでセッション変数を更新します。
リファラーが疑わしい場合はセッションを破棄する
ページにアクセスすると、ほとんどの Web ブラウザはReferrerヘッダー (このページに到達するためにたどったリンクを含むページ) を設定します。
ユーザーがログインしているサイトが、そのサイト外からリンクされる可能性が低いサイト (銀行の Web サイトやWeb メールなど) であり、ユーザーが長時間ログインしたままになるようなサイトでない場合は、リファラーはそのサイトからのものである必要があります。その他のリファラーは疑わしいと見なす必要があります。ただし、元のリクエストが HTTPS ページからのものである場合は、リファラーが削除されるため、このセキュリティ システムに頼ることはできません。
たとえば、http://vulnerable.example.com/次のセキュリティ チェックを採用できます。
if ( strpos ( $_SERVER [ 'HTTP_REFERER' ], 'http://vulnerable.example.com/' ) !== 0 ) {
session_destroy (); // セッション内のすべてのデータを破棄する
}
session_regenerate_id (); // 新しいセッション識別子を生成する
追加情報がセッション全体を通じて一貫していることを確認する
セキュリティをさらに強化する 1 つの方法は、ユーザーが同じエンド ユーザー (クライアント) であるように見せることです。これにより、セッション固定やその他の攻撃を実行することが少し難しくなります。
RFC 3704 やその他のスプーフィング防止対策に準拠するネットワークが増えるにつれて、IP アドレスは「同一ソース」識別子としてより信頼性が増します。したがって、セッション全体を通じてソース IP アドレスが一貫していることを確認することで、Web サイトのセキュリティを向上できます。
これは次のように実行できます。
if ( $_SERVER [ 'REMOTE_ADDR' ] != $_SESSION [ 'PREV_REMOTEADDR' ]) {
session_destroy (); // セッション内のすべてのデータを破棄します
}
session_regenerate_id (); // 新しいセッション識別子を生成します
$_SESSION [ 'PREV_REMOTEADDR' ] = $_SERVER [ 'REMOTE_ADDR' ];
ただし、このアプローチを採用する前に考慮すべき点がいくつかあります。
- 複数のユーザーが 1 つの IP アドレスを共有する場合があります。NATを使用して建物全体で 1 つの IP アドレスを共有することも珍しくありません。
- 1 人のユーザーが一貫性のない IP アドレスを持つ場合があります。これは、プロキシの背後にいるユーザー ( AOL の顧客など) に当てはまります。また、一部のモバイル/ローミング ユーザーや、負荷分散されたインターネット接続の背後にいるユーザーにも当てはまります。IPv6プライバシー拡張機能が有効になっているユーザーは、いつでも IPv6 プライバシー アドレスを変更できます。
- リクエストは IPv4 と IPv6 間で移動するため、デュアル スタック クライアントでは確実に動作しません。
- モバイル ユーザーもアドレス間を移動するため、モバイル ユーザーの場合は確実に動作しません。
一部のサイトでは、セキュリティの強化が利便性の欠如を上回りますが、他のサイトではそうではありません。
ユーザーエージェント
ブラウザは、"User-Agent" HTTP ヘッダーによって自身を識別します。このヘッダーは通常、使用中に変更されることはありません。変更された場合、非常に疑わしいものとなります。Web アプリケーションは、悪意のあるユーザーによるセッションの盗難を防ぐために、User-Agent 検出を使用する場合があります。ただし、これは簡単に回避できます。攻撃者は自分のサイトで被害者のユーザー エージェントを簡単に取得し、攻撃中に偽装できるためです。この提案されたセキュリティ システムは、隠蔽によるセキュリティに依存しています。
if ( $_SERVER [ 'HTTP_USER_AGENT' ] != $_SESSION [ ' PREV_USERAGENT' ]) {
session_destroy (); // セッション内のすべてのデータを破棄します
}
session_regenerate_id (); // 新しいセッション識別子を生成します
$_SESSION [ 'PREV_USERAGENT' ] = $_SERVER [ 'HTTP_USER_AGENT' ];
ただし、このアプローチを採用する前に考慮すべき点がいくつかあります。
- インターネットカフェでは、複数のユーザーが同じブラウザのユーザーエージェントを使用している可能性があります。
- 複数のユーザーが同じデフォルト ブラウザーを使用している可能性があります (例: Windows XP SP3 の Internet Explorer 6、または携帯電話のミニ ブラウザー)。
ただし、ユーザーエージェントは、ごくまれに合法的に変更されることがあります。次の例は同じユーザーです。
- 前回のリクエスト以降に画面が回転したスマートフォン
Mozilla/5.0 (Linux; U; Android 2.2; en-us; DROID2 Build/VZW) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 854X480 motorola DROID2Mozilla/5.0 (Linux; U; Android 2.2; en-us; DROID2 Build/VZW) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 480X854 motorola DROID2
- Internet Explorer 互換モード:
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
- 複数のサーバーに分散されたプロキシを介して Web サイトにアクセスするユーザー (すべてのサーバーが最新バージョンのプロキシ ソフトウェアにアップグレードされていない)
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6 (FlipboardProxy/0.0.5; +http://flipboard.com/browserproxy)Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6 (FlipboardProxy/1.1; +http://flipboard.com/browserproxy)
多層防御
多層防御とは、複数の対策を組み合わせることです。考え方は単純です。1 つの障害は簡単に克服できますが、複数の障害を克服するのは非常に困難になる可能性があります。
多層防御戦略には以下が含まれます。
- HTTPS を有効にする (他の問題から保護するため)
- 正しい構成 (外部 SID を受け入れない、タイムアウトを設定するなど)
- セッションの再生成、ログアウトのサポートなどを実行します。
HTTP リファラーは SSL/TLS (HTTPS) では渡されません。
次の PHP スクリプトは、このような対策をいくつか組み合わせて、多層防御の方法で実行する方法を示しています。
if ( isset ( $_GET [ 'LOGOUT' ]) ||
$_SERVER [ 'REMOTE_ADDR' ] !== $_SESSION [ 'PREV_REMOTEADDR' ] ||
$_SERVER [ 'HTTP_USER_AGENT' ] !== $_SESSION [ 'PREV_USERAGENT' ]) {
session_destroy ();
}
session_regenerate_id (); // 新しいセッション識別子を生成する
$_SESSION [ 'PREV_USERAGENT' ] = $_SERVER [ 'HTTP_USER_AGENT' ];
$_SESSION [ 'PREV_REMOTEADDR' ] = $_SERVER [ 'REMOTE_ADDR' ];
このコードは、現在の REMOTE_ADDR (ユーザーの IP アドレス) と User-agent を、以前のリクエストの REMOTE_ADDR と User-agent と比較することに注意してください。これは、上で説明したように、一部のサイトでは不便な場合があります。
参照
参考文献
- ^ 認証されていないセッション固定攻撃に関する記事
外部リンク
- セキュリティコーナー: セッション固定
- Web ベース アプリケーションにおけるセッション固定の脆弱性 (PDF)
- セッション固定ビデオの例
- Web アプリケーション セキュリティ コンソーシアムの脅威分類
