hacktricks/pentesting-web/race-condition.md

16 KiB
Raw Blame History

レースコンディション


Trickestを使用して、世界で最も先進的なコミュニティツールによって強化されたワークフローを簡単に構築し、自動化します。
今すぐアクセスを取得:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

RCの悪用

RCの悪用の主な問題は、リクエストが非常に短い時間差通常> 1msで並行して処理される必要があることです。次のセクションでは、これを可能にするためのさまざまな解決策が提案されています。

シングルパケット攻撃

HTTP2では、1つのTCP接続で2つのリクエストを送信できますHTTP/1.1ではシーケンシャルである必要があります)。
シングルパケットの使用により、ネットワークの揺らぎの影響が完全に排除されるため、これは明らかにレースコンディション攻撃の可能性があります。ただし、2つのリクエストでは信頼性のあるレース攻撃には十分ではありません。これは、サーバーサイドの揺らぎによるものです。これは、CPUの競合などの制御できない変数によって引き起こされるアプリケーションのリクエスト処理時間の変動です。

しかし、HTTP/1.1の 'last-byte sync' 技術を使用すると、各リクエストからわずかなフラグメントを保留し、その後、1つのTCPパケットで20〜30のリクエストを完了することができます。

各リクエストの大部分を事前に送信するには:

  • リクエストにボディがない場合、すべてのヘッダーを送信しますが、END_STREAMフラグは設定しないでください。END_STREAMが設定された空のデータフレームを保留します。
  • リクエストにボディがある場合、ヘッダーと最後のバイトを除くすべてのボディデータを送信します。最後のバイトを含むデータフレームを保留します。

次に、最終フレームの送信の準備をします:

  • 初期フレームが送信されたことを確認するために、100ms待ちます。
  • TCP_NODELAYが無効になっていることを確認します。Nagleのアルゴリズムが最終フレームをバッチ処理することが重要です。
  • ローカル接続をウォームアップするためにpingパケットを送信します。これを行わないと、OSネットワークスタックは最初の最終フレームを別のパケットに配置します。

最後に、保留していたフレームを送信します。Wiresharkを使用して、それらが1つのパケットに着地したことを確認できるはずです。

{% hint style="info" %} 特定のサーバーの静的ファイルでは機能しませんが、静的ファイルはレースコンディション攻撃には関係ありません。しかし、静的ファイルはRC攻撃には関係ありません。 {% endhint %}

この技術を使用すると、ネットワークの揺らぎに関係なく、20〜30のリクエストがサーバーに同時に到着することができます。

ターゲットアーキテクチャに適応する

多くのアプリケーションはフロントエンドサーバーの背後にあり、これらは一部のリクエストを既存の接続を介してバックエンドに転送し、他のリクエストに対しては新しい接続を作成することを決定する場合があります。

その結果、アプリケーションの動作に一貫性のないリクエストタイミングを帰属しないようにすることが重要です。また、フロントエンドのリクエストルーティングは通常、接続ごとに行われるため、攻撃を実行する前にいくつかの無関係なリクエストをサーバーサイドで行うことで、リクエストのタイミングをスムーズにすることができる場合があります。

PHPはデフォルトでセッションIDに対してロックをかけるため、バッチ内のすべてのリクエストに別々のセッションを使用する必要があります。そうしないと、リクエストは順次処理されます。

{% hint style="warning" %} この技術の詳細については、https://portswigger.net/research/smashing-the-state-machineの元のレポートを参照してください。 {% endhint %}

この技術の使用方法については、https://github.com/PortSwigger/turbo-intruder/blob/master/resources/examples/race-single-packet-attack.pyのturbo intruderの単純な例を確認できます。

また、Burp SuiteのRepeaterでは、新しい 'Send group in parallel' オプションを使用して利用できます。

Raw BF

以前の研究の前に、以下のペイロードが使用されました。これらは、RCを引き起こすために可能な限り速くパケットを送信しようとするものです。

  • Turbo Intruder
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
pipeline=False
)
a = ['Session=<session_id_1>','Session=<session_id_2>','Session=<session_id_3>']
for i in range(len(a)):
engine.queue(target.req,a[i], gate='race1')
# open TCP connections and send partial requests
engine.start(timeout=10)
engine.openGate('race1')
engine.complete(timeout=60)

def handleResponse(req, interesting):
table.add(req)
  • Python - asyncio
import asyncio
import httpx

async def use_code(client):
resp = await client.post(f'http://victim.com', cookies={"session": "asdasdasd"}, data={"code": "123123123"})
return resp.text

async def main():
async with httpx.AsyncClient() as client:
tasks = []
for _ in range(20): #20 times
tasks.append(asyncio.ensure_future(use_code(client)))

# Get responses
results = await asyncio.gather(*tasks, return_exceptions=True)

# Print results
for r in results:
print(r)

# Async2sync sleep
await asyncio.sleep(0.5)
print(results)

asyncio.run(main())
  • 侵入者: リクエスト侵入者に送信し、オプションメニュー内でスレッド数30に設定し、Nullペイロードを選択して30を生成します。

RC方法論

RCの影響

リミットオーバーラン

これは、アクションを実行できる回数を制限する場所現れる脆弱性がある最も基本的なタイプの競合状態です。たとえば、ウェブストアで同じ割引コードを複数回使用することです。このレポートこのバグ****には、非常に簡単な例があります。

隠れたサブステート

他の最も複雑なRCは、攻撃者がアクセスすることを意図されていなかった状態を悪用する可能性のあるマシンのサブステートを利用しますが、攻撃者がアクセスするための小さなウィンドウがあります。

  1. 潜在的な隠れた興味深いサブステートを予測する

最初のステップは、それに書き込むか、それからデータを読み取り、それを重要な何かに使用するすべてのエンドポイントを特定することです。たとえば、ユーザーは登録、プロファイル編集、パスワードリセットの開始、パスワードリセットの完了によって変更されるデータベーステーブルに保存される場合があります。

エンドポイントごとに、以下の3つの重要な質問を使用して、衝突が起こりにくいエンドポイントを除外できます。各オブジェクトと関連するエンドポイントについて、次のように尋ねます。

1) 状態はどのように保存されていますか?

永続的なサーバーサイドのデータ構造に保存されているデータは、悪用に適しています。一部のエンドポイントは、パスワードリセットなど、JWTをメールで送信することによって動作するように、完全にクライアントサイドに状態を保存します。これらは安全にスキップできます。

アプリケーションは、ユーザーセッションに一部の状態を保存することがよくあります。これらは通常、サブステートに対してある程度保護されています - これについては後で詳しく説明します。

2) 編集または追加していますか?

既存のデータを編集する操作(アカウントの主なメールアドレスを変更するなど)は、十分な衝突の可能性がありますが、既存のデータに追加するだけの操作(追加のメールアドレスを追加するなど)は、リミットオーバーラン攻撃以外の脆弱性に対しては脆弱性がありません。

3) 操作は何にキー付けられていますか?

ほとんどのエンドポイントは、ユーザ名、パスワードリセットトークン、ファイル名などの「キー」を使用して特定のレコードで操作します。成功した攻撃には、同じキーを使用する2つの操作が必要です。たとえば、2つの考えられるパスワードリセットの実装を想像してみてください。

  1. 手がかりを探る

この時点で、潜在的に興味深いエンドポイントに対していくつかのRC攻撃を実行して、通常のものと比較して予期しない結果を見つけようとします。応答の変化や、異なるメールの内容やセッションの目に見える変化など、予想される応答からの逸脱は、何かが間違っていることを示す手がかりになる可能性があります。

  1. コンセプトを証明する

最後のステップは、コンセプトを証明し、攻撃を実行可能なものにすることです。

一括リクエストを送信すると、初期のリクエストペアが脆弱なエンドステートをトリガーする場合がありますが、後のリクエストがそれを上書き/無効にし、最終的な状態は攻撃できない状態になります。このシナリオでは、不要なリクエストをすべて削除する必要があります - 2つのリクエストでほとんどの脆弱性を悪用できます。ただし、2つのリクエストにすると、攻撃はタイミングに敏感になるため、攻撃を複数回リトライするか、自動化する必要がある場合があります。

隠れたサブステートの事例研究

商品の支払いと追加

このラボをチェックして、支払いを行い、追加のアイテムを追加して支払う必要がないことを確認してください。

他のメールの確認

アイデアは、メールアドレスを確認し、同時に変更して、プラットフォームが新しいメールアドレスを確認するかどうかを確認することです。

2つのメールアドレスにメールを変更

この解説によると、Gitlabはこの方法で乗っ取られる可能性がありました。なぜなら、Gitlabは1つのメールのメール確認トークンを他のメールに送信する可能性があるからです。

OAuth2の永続性

いくつかのOAuthプロバイダがあります。これらのサービスは、プロバイダが登録したユーザーを認証し、アプリケーションがそのデータにアクセスすることを許可するために、クライアントOAUthプロバイダ内の一部のデータにアクセスすることを許可する必要があります。
したがって、ここまでは、Google/Linkdin/Githubなどの一般的なログインで、次のようなページが表示されます: "Application <InsertCoolName> wants to access you information, do you want to allow it?"

authorization_codeの競合状態

問題は、それを受け入れ、自動的に**authorization_codeを悪意のあるアプリケーションに送信すると発生します。その後、このアプリケーションはOAUthサービスプロバイダ内の競合状態を悪用して、authorization_codeから複数のAT/RT**_認証トークン/リフレッシ


Trickestを使用して、世界で最も高度なコミュニティツールによって強化されたワークフローを簡単に構築して自動化します。 今すぐアクセスを取得:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}