Cookies Hacking
Cookie Attributes
クッキーには、ユーザーのブラウザでの動作を制御するいくつかの属性があります。これらの属性についての概要は以下の通りです。
Expires and Max-Age
クッキーの有効期限はExpires
属性によって決まります。一方、Max-age
属性は、クッキーが削除されるまでの時間(秒単位)を定義します。Max-age
を選択することをお勧めします。これはより現代的な慣行を反映しています。
Domain
クッキーを受け取るホストはDomain
属性によって指定されます。デフォルトでは、これはクッキーを発行したホストに設定され、サブドメインは含まれません。しかし、Domain
属性が明示的に設定されると、サブドメインも含まれます。これにより、サブドメイン間でのクッキー共有が必要なシナリオで役立つ、Domain
属性の指定が制限されないオプションとなります。たとえば、Domain=mozilla.org
を設定すると、developer.mozilla.org
のようなサブドメインでクッキーにアクセスできます。
Path
Cookie
ヘッダーが送信されるために要求されたURLに存在しなければならない特定のURLパスは、Path
属性によって示されます。この属性は/
文字をディレクトリセパレーターとして考慮し、サブディレクトリ内での一致も可能にします。
Ordering Rules
同じ名前のクッキーが2つある場合、送信されるクッキーは以下に基づいて選択されます:
要求されたURL内で最も長いパスに一致するクッキー。
パスが同じ場合は、最も最近設定されたクッキー。
SameSite
SameSite
属性は、クッキーがサードパーティのドメインからのリクエストで送信されるかどうかを決定します。3つの設定があります:Strict:サードパーティのリクエストでクッキーが送信されるのを制限します。
Lax:サードパーティのウェブサイトによって開始されたGETリクエストでクッキーが送信されることを許可します。
None:任意のサードパーティドメインからクッキーが送信されることを許可します。
クッキーを設定する際には、これらの属性を理解することで、さまざまなシナリオで期待通りに動作することを確保できます。
リクエストタイプ | 例コード | クッキーが送信される場合 |
リンク | <a href="..."></a> | NotSet*, Lax, None |
プリレンダリング | <link rel="prerender" href=".."/> | NotSet*, Lax, None |
フォームGET | <form method="GET" action="..."> | NotSet*, Lax, None |
フォームPOST | <form method="POST" action="..."> | NotSet*, None |
iframe | <iframe src="..."></iframe> | NotSet*, None |
AJAX | $.get("...") | NotSet*, None |
画像 | <img src="..."> | NetSet*, None |
表はInvictiからのもので、若干修正されています。 _SameSite_属性を持つクッキーは、CSRF攻撃を軽減します。ログインセッションが必要です。
*Chrome80(2019年2月)以降、SameSite属性を持たないクッキーのデフォルトの動作はLaxになります (https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/). この変更を適用した後、ChromeではSameSiteポリシーを持たないクッキーは最初の2分間はNoneとして扱われ、その後はトップレベルのクロスサイトPOSTリクエストに対してLaxとして扱われます。
Cookies Flags
HttpOnly
これはクライアントがクッキーにアクセスするのを防ぎます(例えばJavascript経由:document.cookie
)。
バイパス
ページがリクエストのレスポンスとしてクッキーを送信している場合(例えばPHPinfoページ)、XSSを悪用してこのページにリクエストを送り、レスポンスからクッキーを盗むことが可能です(例はこちらを参照)。
TRACE HTTPリクエストを使用することでバイパス可能です。このHTTPメソッドが利用可能な場合、サーバーからのレスポンスは送信されたクッキーを反映します。この技術はクロスサイトトラッキングと呼ばれます。
この技術は、モダンブラウザがJSからTRACEリクエストを送信することを許可しないことによって回避されます。ただし、IE6.0 SP2に対して
TRACE
の代わりに\r\nTRACE
を送信するなど、特定のソフトウェアでのバイパスが見つかっています。別の方法は、ブラウザのゼロデイ脆弱性を悪用することです。
クッキージャーオーバーフロー攻撃を実行することでHttpOnlyクッキーを上書きすることが可能です:
Cookie Smuggling攻撃を使用してこれらのクッキーを外部に持ち出すことが可能です。
Secure
リクエストは、HTTPSなどの安全なチャネルを介して送信される場合にのみ、HTTPリクエストでクッキーを送信します。
Cookies Prefixes
__Secure-
で始まるクッキーは、HTTPSで保護されたページからsecure
フラグとともに設定される必要があります。
__Host-
で始まるクッキーには、いくつかの条件が満たされなければなりません:
secure
フラグで設定されなければなりません。HTTPSで保護されたページから発信されなければなりません。
ドメインを指定することは禁じられており、サブドメインへの送信を防ぎます。
これらのクッキーのパスは
/
に設定されなければなりません。
__Host-
で始まるクッキーは、スーパードメインやサブドメインに送信されることは許可されていないことに注意することが重要です。この制限は、アプリケーションクッキーを隔離するのに役立ちます。したがって、すべてのアプリケーションクッキーに__Host-
プレフィックスを使用することは、セキュリティと隔離を強化するための良いプラクティスと見なされます。
Overwriting cookies
したがって、__Host-
で始まるクッキーの保護の1つは、サブドメインからの上書きを防ぐことです。たとえば、Cookie Tossing attacksを防ぎます。トークでCookie Crumbles: Unveiling Web Session Integrity Vulnerabilities(論文)では、パーサーを騙すことでサブドメインから__HOST-で始まるクッキーを設定することが可能であることが示されています。たとえば、最初や最後に"="を追加することなどです:
また、PHPでは、クッキー名の先頭に他の文字を追加することで、アンダースコア文字に置き換えられ、__HOST-
クッキーを上書きすることが可能でした:
Cookies Attacks
カスタムクッキーに機密データが含まれている場合は、特にCTFをプレイしている場合は、それを確認してください。脆弱性があるかもしれません。
Decoding and Manipulating Cookies
クッキーに埋め込まれた機密データは常に精査されるべきです。Base64や類似の形式でエンコードされたクッキーは、しばしばデコード可能です。この脆弱性により、攻撃者はクッキーの内容を変更し、修正されたデータを再度クッキーにエンコードすることで他のユーザーを偽装することができます。
Session Hijacking
この攻撃は、ユーザーのクッキーを盗むことで、アプリケーション内のそのユーザーのアカウントに不正にアクセスすることを含みます。盗まれたクッキーを使用することで、攻撃者は正当なユーザーを偽装できます。
Session Fixation
このシナリオでは、攻撃者が被害者を特定のクッキーを使用してログインさせるように仕向けます。アプリケーションがログイン時に新しいクッキーを割り当てない場合、攻撃者は元のクッキーを持っているため、被害者を偽装できます。この技術は、被害者が攻撃者が提供したクッキーでログインすることに依存しています。
サブドメインでXSSを見つけた場合やサブドメインを制御している場合は、次をお読みください:
Cookie TossingSession Donation
ここでは、攻撃者が被害者に攻撃者のセッションクッキーを使用させるように仕向けます。被害者は自分のアカウントにログインしていると信じて、攻撃者のアカウントのコンテキストで意図せずにアクションを実行します。
サブドメインでXSSを見つけた場合やサブドメインを制御している場合は、次をお読みください:
Cookie Tossing前のリンクをクリックして、JWTの可能な欠陥を説明するページにアクセスしてください。
クッキーで使用されるJSON Web Tokens(JWT)も脆弱性を示す可能性があります。潜在的な欠陥とそれを悪用する方法についての詳細情報を得るには、JWTハッキングに関するリンクされた文書にアクセスすることをお勧めします。
Cross-Site Request Forgery (CSRF)
この攻撃は、ログイン中のユーザーに対して、現在認証されているWebアプリケーションで不要なアクションを実行させるものです。攻撃者は、脆弱なサイトへのすべてのリクエストに自動的に送信されるクッキーを悪用できます。
Empty Cookies
(詳細は元の研究を参照してください)ブラウザは名前のないクッキーの作成を許可しており、次のようにJavaScriptで示すことができます:
送信されたクッキー ヘッダーの結果は a=v1; test value; b=v2;
です。興味深いことに、これは空の名前のクッキーが設定されている場合にクッキーを操作することを可能にし、空のクッキーを特定の値に設定することで他のクッキーを制御する可能性があります。
これにより、ブラウザはすべてのウェブサーバーによって a
という名前のクッキーと b
という値を持つクッキーとして解釈されるクッキー ヘッダーを送信します。
Chromeのバグ: Unicodeサロゲートコードポイントの問題
Chromeでは、Unicodeサロゲートコードポイントがセットクッキーの一部である場合、document.cookie
が破損し、その後空の文字列を返します:
この結果、document.cookie
は空の文字列を出力し、永続的な破損を示します。
パースの問題によるクッキーのスモグリング
(詳細は元の研究を参照) Java(Jetty、TomCat、Undertow)やPython(Zope、cherrypy、web.py、aiohttp、bottle、webob)を含むいくつかのウェブサーバーは、古いRFC2965サポートのためにクッキー文字列を誤って処理します。彼らは、セミコロンを含んでいても、ダブルクオートされたクッキー値を単一の値として読み取ります。これは通常、キーと値のペアを区切るべきです。
Cookie Injection Vulnerabilities
(詳細は元の研究を参照してください) サーバーによるクッキーの不適切な解析、特にUndertow、Zope、およびPythonのhttp.cookie.SimpleCookie
とhttp.cookie.BaseCookie
を使用しているものは、クッキーインジェクション攻撃の機会を生み出します。これらのサーバーは新しいクッキーの開始を適切に区切ることができず、攻撃者がクッキーを偽装することを可能にします:
Undertowは、セミコロンなしで引用された値の直後に新しいクッキーを期待します。
Zopeは、次のクッキーの解析を開始するためにカンマを探します。
Pythonのクッキークラスは、スペース文字で解析を開始します。
この脆弱性は、クッキーに基づくCSRF保護に依存するWebアプリケーションにおいて特に危険です。攻撃者が偽装されたCSRFトークンクッキーを注入できるため、セキュリティ対策を回避する可能性があります。この問題は、Pythonが重複したクッキー名を処理する方法によって悪化します。最後の出現が以前のものを上書きします。また、__Secure-
および__Host-
クッキーが不安全なコンテキストで扱われることに対する懸念も生じ、クッキーが偽装に対して脆弱なバックエンドサーバーに渡されると、認可のバイパスにつながる可能性があります。
Extra Vulnerable Cookies Checks
Basic checks
クッキーは、ログインするたびに同じです。
ログアウトして、同じクッキーを使用してみてください。
2つのデバイス(またはブラウザ)で同じアカウントに同じクッキーを使用してログインしてみてください。
クッキーに情報が含まれているか確認し、変更を試みてください。
ほぼ同じユーザー名で複数のアカウントを作成し、類似点が見えるか確認してください。
"remember me"オプションが存在する場合、それがどのように機能するか確認してください。存在し、脆弱である可能性がある場合は、他のクッキーなしでremember meのクッキーを常に使用してください。
パスワードを変更しても前のクッキーが機能するか確認してください。
Advanced cookies attacks
クッキーがログイン時に同じ(またはほぼ同じ)である場合、これはおそらくそのクッキーがアカウントのいくつかのフィールド(おそらくユーザー名)に関連していることを意味します。次に、あなたは:
非常に似たユーザー名でたくさんのアカウントを作成し、アルゴリズムがどのように機能しているかを推測してみてください。
ユーザー名をブルートフォースしてみてください。クッキーがあなたのユーザー名の認証方法としてのみ保存されている場合、ユーザー名"Bmin"でアカウントを作成し、クッキーのすべてのビットをブルートフォースすることができます。なぜなら、あなたが試すクッキーの1つは"admin"に属するものだからです。
Padding Oracleを試してください(クッキーの内容を復号化できます)。padbusterを使用してください。
Padding Oracle - Padbuster examples
Padbusterは複数回の試行を行い、どの条件がエラー条件(無効なもの)であるかを尋ねます。
その後、クッキーの復号を開始します(数分かかる場合があります)。
攻撃が成功した場合、任意の文字列を暗号化してみることができます。たとえば、encrypt user=administratorを暗号化したい場合。
この実行により、文字列 user=administrator が内部に含まれた正しく暗号化され、エンコードされたクッキーが得られます。
CBC-MAC
クッキーには何らかの値があり、CBCを使用して署名される可能性があります。すると、その値の整合性は、同じ値を使用してCBCで作成された署名になります。IVとしてヌルベクターを使用することが推奨されるため、このタイプの整合性チェックは脆弱である可能性があります。
攻撃
ユーザー名 administ の署名を取得 = t
ユーザー名 rator\x00\x00\x00 XOR t の署名を取得 = t'
クッキーに値 administrator+t' を設定する (t' は (rator\x00\x00\x00 XOR t) XOR t = rator\x00\x00\x00 の有効な署名になります)
ECB
クッキーがECBを使用して暗号化されている場合、脆弱である可能性があります。 ログインすると、受け取るクッキーは常に同じでなければなりません。
検出と攻撃方法:
ほぼ同じデータ(ユーザー名、パスワード、メールなど)を持つ2つのユーザーを作成し、与えられたクッキー内のパターンを発見しようとします。
例えば「aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa」というユーザーを作成し、クッキーにパターンがあるか確認します(ECBは同じキーで各ブロックを暗号化するため、ユーザー名が暗号化されると同じ暗号化されたバイトが現れる可能性があります)。
使用されるブロックのサイズでパターンが存在するはずです。したがって、「a」をブロックのサイズ分繰り返した後に「admin」を追加したユーザー名を作成できます。その後、クッキーから「a」のブロックの暗号化パターンを削除することができます。そして、ユーザー名「admin」のクッキーを得ることができます。
参考文献
Last updated