Cookies Hacking

Reading time: 27 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

Cookiesには、ユーザーのブラウザでの動作を制御するいくつかの属性があります。これらの属性について、より受動的な声で説明します。

Expires and Max-Age

Cookieの有効期限はExpires属性によって決まります。対照的に、Max-age属性はCookieが削除されるまでの時間(秒単位)を定義します。Max-ageを選択することをお勧めします。これはより現代的な慣行を反映しています。

Domain

Cookieを受け取るホストはDomain属性によって指定されます。デフォルトでは、これはCookieを発行したホストに設定され、サブドメインは含まれません。しかし、Domain属性が明示的に設定されると、サブドメインも含まれます。これにより、サブドメイン間でのCookie共有が必要なシナリオで、Domain属性の指定が制限の少ないオプションとなります。たとえば、Domain=mozilla.orgを設定すると、developer.mozilla.orgのようなサブドメインでCookieにアクセスできます。

Path

Cookieヘッダーが送信されるために要求されたURLに存在しなければならない特定のURLパスは、Path属性によって示されます。この属性は/文字をディレクトリセパレーターとして考慮し、サブディレクトリ内での一致も可能にします。

Ordering Rules

同じ名前のCookieが2つある場合、送信されるCookieは以下に基づいて選択されます:

  • 要求されたURL内で最も長いパスに一致するCookie。
  • パスが同じ場合は、最も最近設定されたCookie。

SameSite

  • SameSite属性は、Cookieがサードパーティのドメインからのリクエストで送信されるかどうかを決定します。3つの設定があります:
  • Strict: サードパーティのリクエストでCookieが送信されるのを制限します。
  • Lax: サードパーティのウェブサイトによって開始されたGETリクエストでCookieが送信されることを許可します。
  • None: どのサードパーティのドメインからでもCookieが送信されることを許可します。

Cookieを設定する際には、これらの属性を理解することで、さまざまなシナリオで期待通りに動作することを確保できます。

Request TypeExample CodeCookies Sent When
Link<a href="..."></a>NotSet*, Lax, None
Prerender<link rel="prerender" href=".."/>NotSet*, Lax, None
Form GET<form method="GET" action="...">NotSet*, Lax, None
Form POST<form method="POST" action="...">NotSet*, None
iframe<iframe src="..."></iframe>NotSet*, None
AJAX$.get("...")NotSet*, None
Image<img src="...">NetSet*, None

Table from Invicti and slightly modified.
_SameSite_属性を持つCookieは、CSRF攻撃を軽減します。

*Chrome80(2019年2月)以降、CookieにSameSite属性がない場合のデフォルトの動作はLaxになります (https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/).
この変更を適用した後、ChromeではSameSiteポリシーのないCookie最初の2分間はNoneとして扱われ、その後はトップレベルのクロスサイトPOSTリクエストに対してLaxとして扱われます。

Cookies Flags

HttpOnly

これはクライアントがCookieにアクセスするのを防ぎます(例えば、Javascript経由で:document.cookie)。

Bypasses

  • ページがリクエストのレスポンスとしてCookieを送信している場合(例えば、PHPinfoページで)、XSSを悪用してこのページにリクエストを送り、レスポンスからCookieを盗むことが可能です(例はこちらを参照)。
  • TRACE HTTPリクエストを使用することでバイパス可能です。このHTTPメソッドが利用可能な場合、サーバーからのレスポンスは送信されたCookieを反映します。この技術はCross-Site Trackingと呼ばれます。
  • この技術は、モダンブラウザがJSからTRACEリクエストを送信することを許可しないことによって回避されます。ただし、IE6.0 SP2に対してTRACEの代わりに\r\nTRACEを送信するなど、特定のソフトウェアでのバイパスが見つかっています。
  • 別の方法は、ブラウザのゼロデイ脆弱性を悪用することです。
  • Cookie Jarオーバーフロー攻撃を実行することでHttpOnly Cookieを上書きすることが可能です:

Cookie Jar Overflow

  • これらのCookieを外部に持ち出すためにCookie Smuggling攻撃を使用することが可能です。

Secure

リクエストは、HTTPSなどの安全なチャネルを介して送信される場合にのみ、HTTPリクエストでCookieを送信します

Cookies Prefixes

__Secure-で始まるCookieは、HTTPSで保護されたページからsecureフラグとともに設定される必要があります。

__Host-で始まるCookieには、いくつかの条件が満たされなければなりません:

  • secureフラグで設定されなければなりません。
  • HTTPSで保護されたページから発信されなければなりません。
  • ドメインを指定することは禁じられており、サブドメインへの送信を防ぎます。
  • これらのCookieのパスは/に設定されなければなりません。

__Host-で始まるCookieは、スーパードメインやサブドメインに送信されることは許可されていないことに注意することが重要です。この制限は、アプリケーションCookieを隔離するのに役立ちます。したがって、すべてのアプリケーションCookieに__Host-プレフィックスを使用することは、セキュリティと隔離を強化するための良いプラクティスと見なされます。

Overwriting cookies

したがって、__Host-で始まるCookieの保護の1つは、サブドメインから上書きされるのを防ぐことです。たとえば、Cookie Tossing attacksを防ぎます。トークでCookie Crumbles: Unveiling Web Session Integrity Vulnerabilities (paper)では、パーサーを騙すことでサブドメインから__HOST-で始まるCookieを設定することが可能であることが示されています。たとえば、最初や最後に=を追加することによって...:

また、PHPでは、Cookie名の先頭に他の文字を追加することで、アンダースコア文字に置き換えられ、__HOST- Cookieを上書きすることが可能でした:

Cookies Attacks

カスタムCookieに機密データが含まれている場合は、特にCTFを行っている場合は確認してください。脆弱性があるかもしれません。

Decoding and Manipulating Cookies

Cookieに埋め込まれた機密データは常に精査されるべきです。Base64や類似の形式でエンコードされたCookieは、しばしばデコード可能です。この脆弱性により、攻撃者はCookieの内容を変更し、他のユーザーを偽装するために修正されたデータを再度Cookieにエンコードすることができます。

Session Hijacking

この攻撃は、ユーザーのCookieを盗んで、アプリケーション内でのそのアカウントへの不正アクセスを得ることを含みます。盗まれたCookieを使用することで、攻撃者は正当なユーザーを偽装できます。

Session Fixation

このシナリオでは、攻撃者が被害者を特定のCookieを使用してログインさせるように仕向けます。アプリケーションがログイン時に新しいCookieを割り当てない場合、攻撃者は元のCookieを持っているため、被害者を偽装できます。この技術は、被害者が攻撃者が提供したCookieでログインすることに依存しています。

サブドメインでXSSを見つけた場合サブドメインを制御している場合は、次を読んでください:

Cookie Tossing

Session Donation

ここでは、攻撃者が被害者に攻撃者のセッションCookieを使用させるように仕向けます。被害者は自分のアカウントにログインしていると信じて、攻撃者のアカウントのコンテキストで意図せずにアクションを実行します。

サブドメインでXSSを見つけた場合サブドメインを制御している場合は、次を読んでください:

Cookie Tossing

JWT Cookies

前のリンクをクリックして、JWTの可能な欠陥を説明するページにアクセスしてください。

Cookieで使用されるJSON Web Tokens (JWT)も脆弱性を示す可能性があります。潜在的な欠陥とそれを悪用する方法についての詳細情報を得るには、JWTのハッキングに関するリンクされた文書にアクセスすることをお勧めします。

Cross-Site Request Forgery (CSRF)

この攻撃は、ログイン中のユーザーに対して、現在認証されているWebアプリケーションで不要なアクションを実行させるものです。攻撃者は、脆弱なサイトへのすべてのリクエストに自動的に送信されるCookieを悪用できます。

Empty Cookies

(詳細は元の研究を参照してください)ブラウザは名前のないCookieの作成を許可しており、次のようにJavaScriptで示すことができます:

js
document.cookie = "a=v1"
document.cookie = "=test value;" // Setting an empty named cookie
document.cookie = "b=v2"

送信されたクッキー ヘッダーの結果は a=v1; test value; b=v2; です。興味深いことに、これは空の名前のクッキーが設定されている場合にクッキーを操作することを可能にし、空のクッキーを特定の値に設定することで他のクッキーを制御できる可能性があります。

js
function setCookie(name, value) {
document.cookie = `${name}=${value}`
}

setCookie("", "a=b") // Setting the empty cookie modifies another cookie's value

これにより、ブラウザはすべてのウェブサーバーによって a という名前のクッキーと b という値を持つクッキーとして解釈されるクッキー ヘッダーを送信します。

Chrome バグ: Unicode サロゲート コードポイントの問題

Chrome では、Unicode サロゲート コードポイントが設定されたクッキーの一部である場合、document.cookie が破損し、その後空の文字列を返します:

js
document.cookie = "\ud800=meep"

これにより、document.cookieが空の文字列を出力し、永続的な破損を示します。

パースの問題によるクッキーのスムグリング

(詳細は元の研究を参照) Java(Jetty、TomCat、Undertow)やPython(Zope、cherrypy、web.py、aiohttp、bottle、webob)を含むいくつかのウェブサーバーは、古いRFC2965サポートのためにクッキー文字列を誤って処理します。彼らは、セミコロンを含んでいても、ダブルクオートされたクッキー値を単一の値として読み取ります。これは通常、キーと値のペアを区切るべきです。

RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";

(Check further details in theoriginal research) サーバーによるクッキーの不適切な解析、特にUndertow、Zope、およびPythonのhttp.cookie.SimpleCookiehttp.cookie.BaseCookieを使用しているものは、クッキーインジェクション攻撃の機会を生み出します。これらのサーバーは新しいクッキーの開始を適切に区切ることができず、攻撃者がクッキーを偽装することを可能にします:

  • Undertowは、セミコロンなしで引用された値の直後に新しいクッキーを期待します。
  • Zopeは、次のクッキーの解析を開始するためにカンマを探します。
  • Pythonのクッキークラスは、スペース文字で解析を開始します。

この脆弱性は、クッキーベースのCSRF保護に依存するWebアプリケーションにとって特に危険であり、攻撃者が偽装されたCSRFトークンクッキーを注入し、セキュリティ対策を回避する可能性があります。この問題は、Pythonが重複したクッキー名を処理する方法によって悪化し、最後の出現が以前のものを上書きします。また、__Secure-および__Host-クッキーが不安全なコンテキストで扱われることに対する懸念を引き起こし、クッキーが偽装に対して脆弱なバックエンドサーバーに渡されると、認可のバイパスを引き起こす可能性があります。

Cookies $version

WAF Bypass

According to this blogpost, $Version=1というクッキー属性を使用して、バックエンドが古いロジックを使用してクッキーを解析する可能性があります。これはRFC2109によるものです。さらに、**$Domain$Path**などの他の値を使用して、クッキーに対するバックエンドの動作を変更することができます。

According to this blogpost クッキーサンドイッチ技術を使用してHttpOnlyクッキーを盗むことが可能です。これらは要件と手順です:

  • 明らかに無駄なクッキーがレスポンスに反映される場所を見つける
  • **$Version**という名前のクッキーを値1で作成する(これはJSからのXSS攻撃で行うことができます)し、初期位置を取得するためにより具体的なパスを指定します(Pythonのような一部のフレームワークではこのステップは必要ありません)
  • 反映されるクッキーを作成し、開いた二重引用符を残す値を持ち、前のクッキー($Version)の後に位置するように特定のパスを指定します
  • その後、正当なクッキーが順番に続きます
  • 二重引用符を閉じるダミークッキーを作成します

このようにして、被害者のクッキーは新しいクッキーのバージョン1の中に閉じ込められ、反映されるたびに反映されます。 e.g. from the post:

javascript
document.cookie = `$Version=1;`;
document.cookie = `param1="start`;
// any cookies inside the sandwich will be placed into param1 value server-side
document.cookie = `param2=end";`;

WAFバイパス

Cookies $version

前のセクションを確認してください。

引用文字列エンコーディングによる値分析のバイパス

この解析は、クッキー内のエスケープされた値をアンエスケープすることを示しています。したがって、"\a"は"a"になります。これはWAFをバイパスするのに役立つ場合があります:

  • eval('test') => forbidden
  • "\e\v\a\l\(\'\t\e\s\t\'\)" => allowed

クッキー名ブロックリストのバイパス

RFC2109では、カンマをクッキー値の区切りとして使用できることが示されています。また、等号の前後にスペースやタブを追加することも可能です。したがって、$Version=1; foo=bar, abc = quxのようなクッキーは、クッキー"foo":"bar, admin = qux"を生成するのではなく、クッキーfoo":"bar""admin":"qux"を生成します。2つのクッキーが生成され、adminの前後のスペースが削除されたことに注意してください。

クッキー分割による値分析のバイパス

最後に、異なるバックドアは、異なるクッキーヘッダーで渡された異なるクッキーを文字列として結合します。

GET / HTTP/1.1
Host: example.com
Cookie: param1=value1;
Cookie: param2=value2;

この例のようにWAFをバイパスすることを可能にするかもしれません:

Cookie: name=eval('test//
Cookie: comment')

Resulting cookie: name=eval('test//, comment') => allowed

追加の脆弱なクッキーチェック

基本チェック

  • クッキーは、ログインするたびに同じです。
  • ログアウトして、同じクッキーを使用してみてください。
  • 2つのデバイス(またはブラウザ)で同じアカウントに同じクッキーを使用してログインしてみてください。
  • クッキーに情報が含まれているか確認し、変更を試みてください。
  • ほぼ同じユーザー名でいくつかのアカウントを作成し、類似点が見えるか確認してください。
  • "ログイン状態を保持"オプションが存在する場合は、その動作を確認してください。存在し、脆弱である可能性がある場合は、他のクッキーを使用せずにログイン状態を保持のクッキーを常に使用してください。
  • パスワードを変更しても前のクッキーが機能するか確認してください。

高度なクッキー攻撃

ログイン時にクッキーが同じ(またはほぼ同じ)である場合、これはおそらくクッキーがアカウントのいくつかのフィールド(おそらくユーザー名)に関連していることを意味します。次に、以下を試みることができます:

  • 非常に似たユーザー名でたくさんのアカウントを作成し、アルゴリズムがどのように機能しているかを推測してみてください。
  • ユーザー名をブルートフォースしてみてください。クッキーがユーザー名の認証方法としてのみ保存されている場合、ユーザー名"Bmin"でアカウントを作成し、クッキーのすべてのビットブルートフォースすることができます。なぜなら、試すクッキーの1つは"admin"に属するものだからです。
  • パディング オラクルを試してください(クッキーの内容を復号化できます)。padbusterを使用してください。

パディングオラクル - Padbusterの例

bash
padbuster <URL/path/when/successfully/login/with/cookie> <COOKIE> <PAD[8-16]>
# When cookies and regular Base64
padbuster http://web.com/index.php u7bvLewln6PJPSAbMb5pFfnCHSEd6olf 8 -cookies auth=u7bvLewln6PJPSAbMb5pFfnCHSEd6olf

# If Base64 urlsafe or hex-lowercase or hex-uppercase --encoding parameter is needed, for example:
padBuster http://web.com/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2

Padbusterは複数回試行し、どの条件がエラー条件(無効なもの)であるかを尋ねます。

その後、クッキーの復号を開始します(数分かかる場合があります)。

攻撃が成功した場合、任意の文字列を暗号化してみることができます。たとえば、encrypt user=administratorを暗号化したい場合。

padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== 8 -cookies thecookie=1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== -plaintext user=administrator

この実行により、user=administratorという文字列が含まれた正しく暗号化され、エンコードされたクッキーが得られます。

CBC-MAC

クッキーにはいくつかの値があり、CBCを使用して署名される可能性があります。すると、値の整合性は、同じ値を使用してCBCで作成された署名になります。IVとしてヌルベクターを使用することが推奨されるため、このタイプの整合性チェックは脆弱である可能性があります。

攻撃

  1. ユーザー名 administ の署名を取得 = t
  2. ユーザー名 rator\x00\x00\x00 XOR t の署名を取得 = t'
  3. クッキーに値 administrator+t' を設定 (t'(rator\x00\x00\x00 XOR t) XOR t の有効な署名になります = rator\x00\x00\x00)

ECB

クッキーがECBを使用して暗号化されている場合、脆弱である可能性があります。
ログインすると、受け取るクッキーは常に同じでなければなりません。

検出と攻撃方法:

ほぼ同じデータ(ユーザー名、パスワード、メールなど)を持つ2つのユーザーを作成し、与えられたクッキー内のパターンを発見しようとします。

例えば「aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa」というユーザーを作成し、クッキーにパターンがあるかどうかを確認します(ECBは同じキーで各ブロックを暗号化するため、ユーザー名が暗号化されると同じ暗号化されたバイトが現れる可能性があります)。

使用されるブロックのサイズでパターンが存在するはずです。したがって、「a」をブロックのサイズ分繰り返した後に「admin」を追加したユーザー名を作成できます。その後、クッキーから「a」のブロックの暗号化パターンを削除することができます。そして、ユーザー名「admin」のクッキーを得ることができます。

参考文献

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする