# レースコンディション
\
[**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks)を使用して、世界で最も高度なコミュニティツールによって強化された**ワークフローを簡単に構築**し、自動化します。\
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
* **サイバーセキュリティ企業で働いていますか?** HackTricksで**会社を宣伝**したいですか?または、**最新バージョンのPEASSにアクセスしたり、HackTricksをPDFでダウンロード**したいですか?[**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)をチェックしてください!
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)をご覧ください。独占的な[**NFT**](https://opensea.io/collection/the-peass-family)のコレクションです。
* [**公式のPEASS&HackTricks swag**](https://peass.creator-spring.com)を手に入れましょう。
* [**💬**](https://emojipedia.org/speech-balloon/) [**Discordグループ**](https://discord.gg/hRep4RUj7f)または[**telegramグループ**](https://t.me/peass)に**参加**するか、**Twitter**で**フォロー**してください[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
* **ハッキングのトリックを共有するには、PRを** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **と** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **に送信してください。**
## RCの悪用
RCの悪用の主な問題は、リクエストが非常に短い時間差(通常> 1ms)で並行して処理される必要があることです。次のセクションでは、これを可能にするためのさまざまな解決策が提案されています。
### シングルパケット攻撃(HTTP/2)/ ラストバイト同期(HTTP/1.1)
HTTP2では、**1つのTCP接続で2つのリクエストを送信**できます(HTTP/1.1では順次送信する必要があります)。\
1つのTCPパケットの使用は、ネットワークの揺らぎの影響を完全に**排除**するため、レースコンディション攻撃にも潜在的な可能性があります。ただし、**2つのリクエストでは信頼性のあるレース攻撃には十分ではありません**。これは、**サーバーサイドの揺らぎ**によるものです。これは、CPUの競合などの制御できない変数によって引き起こされるアプリケーションのリクエスト処理時間の変動です。
しかし、HTTP/1.1の '**ラストバイト同期**' 技術を使用すると、各リクエストからわずかなフラグメントを保留し、その後、**1つのTCPパケットで20〜30のリクエストを完了**することができます。
**各リクエストの大部分を事前に送信**するには:
- リクエストにボディがない場合、すべてのヘッダーを送信しますが、END\_STREAMフラグは設定しません。END\_STREAMが設定された空のデータフレームを保留します。
- リクエストにボディがある場合、ヘッダーと最後のバイトを除くすべてのボディデータを送信します。最後のバイトを含むデータフレームを保留します。
次に、**最終フレームの送信の準備**をします:
- 初期フレームが送信されたことを確認するために、100ms待ちます。
- TCP\_NODELAYが無効になっていることを確認します。Nagleのアルゴリズムが最終フレームをバッチ処理することが重要です。
- ローカル接続をウォームアップするためにpingパケットを送信します。これを行わないと、OSネットワークスタックは最初の最終フレームを別のパケットに配置します。
最後に、保留していたフレームを送信します。Wiresharkを使用して、それらが1つのパケットに着地したことを確認できるはずです。
{% hint style="info" %}
特定のサーバーの静的ファイルでは**機能しません**が、静的ファイルはレースコンディション攻撃には関係ありません。しかし、静的ファイルはRC攻撃には関係ありません。
{% endhint %}
この技術を使用すると、ネットワークの揺らぎに関係なく、20〜30のリクエストがサーバーに同時に到着することができます。
**ターゲットアーキテクチャに適応する**
多くのアプリケーションはフロントエンドサーバーの背後にあり、これらは一部のリクエストを既存の接続を介してバックエンドに転送し、他のリクエストのために新しい接続を作成する場合があります。
そのため、アプリケーションの動作による一貫性のないリクエストタイミングをロックメカニズムなどのアプリケーションの動作に帰することは重要ではありません。また、フロントエンドのリクエストルーティングは通常、接続ごとに行われるため、攻撃を実行する前にサーバーサイドの接続ウォーミングを実行することで、リクエストのタイミングをスムーズにすることができる場合があります(これは、実際の攻撃を開始する前にいくつかのリクエストを送信するだけです)。
#### セッションベースのロックメカニズム
一部のフレームワークでは、**リクエストロック**としての形式を使用して、データの誤った破損を防ぐことを試みています。たとえば、**PHPのネイティブセッションハンドラ**モジュールは、**1つのセッションあたり1つのリクエストのみ**を処理します。
このような動作を見つけることは非常に重要です。なぜなら、これによって簡単に悪用できる脆弱性が隠されてしまう可能性があるからです。すべてのリクエストが順次処理されていることに気付いた場合は、それぞれのリクエストを異なるセッショントークンを使用して送信してみてください。
#### **レート制限またはリソース制限の乱用**
接続のウォーミングが効果がない場合、この問題に対するさまざまな解決策があります。
Turbo Intruderを使用すると、クライアント側で短い遅延を導入することができます。ただし、これには実際の攻撃リクエストを複数のTCPパケットに分割する必要があるため、シングルパケット攻撃技術を使用することはできません。その結果、高ジッターターゲットでは、どのような遅延を設定しても攻撃が確実に機能しない可能性があります。
代わりに、一般的なセキュリティ機能を乱用することでこの問題を解決することができるかもしれません。
Webサーバーは、リクエストがあまりにも速く送信された場合に処理を遅延させることがよくあります。ダミーリクエストを大量に送信してレート制限またはリソース制限を意図的にトリガーすることで、適切なサーバーサイドの遅延を引き起こすことができるかもしれません。これにより、遅延実行が必要な場合でも、シングルパケット攻撃が実行可能になります。
{% hint style="warning" %}
この技術についての詳細は、[https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)の元のレポートを参照してください。
{% endhint %}
#### 攻撃の例
* **Tubo Intruder - HTTP2シングルパケット攻撃(1エンドポイント)**:リクエストを**Turbo Intruder**(`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`)に送信できます。リクエスト内の**`%s`**のようなブルートフォースしたい値を変更し、ドロップダウンから**`examples/race-single-packer-attack.py`**を選択します。
**異なる値を送信する**場合は、クリップボードからワードリストを使用する次のコードに変更できます。
```python
passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')
```
{% hint style="warning" %}
ウェブがHTTP2をサポートしていない場合(HTTP1.1のみ)、`Engine.BURP2`の代わりに`Engine.THREADED`または`Engine.BURP`を使用してください。
{% endhint %}
* **Tubo Intruder - HTTP2シングルパケット攻撃(複数のエンドポイント)**:RCEをトリガーするために1つのエンドポイントにリクエストを送信し、その後他の複数のエンドポイントにリクエストを送信する必要がある場合、`race-single-packet-attack.py`スクリプトを次のように変更できます:
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2
)
# Hardcode the second request for the RC
confirmationReq = '''POST /confirm?token[]= HTTP/2
Host: 0a9c00370490e77e837419c4005900d0.web-security-academy.net
Cookie: phpsessionid=MpDEOYRvaNT1OAm0OtAsmLZ91iDfISLU
Content-Length: 0
'''
# For each attempt (20 in total) send 50 confirmation requests.
for attempt in range(20):
currentAttempt = str(attempt)
username = 'aUser' + currentAttempt
# queue a single registration request
engine.queue(target.req, username, gate=currentAttempt)
# queue 50 confirmation requests - note that this will probably sent in two separate packets
for i in range(50):
engine.queue(confirmationReq, gate=currentAttempt)
# send all the queued requests for this attempt
engine.openGate(currentAttempt)
```
* また、Burp Suiteの新しい「**Send group in parallel**」オプションを使用して、**Repeater**でも利用できます。
* **limit-overrun**の場合、グループに**同じリクエストを50回**追加するだけです。
* **connection warming**の場合、ウェブサーバーの非静的な部分にいくつかのリクエストをグループの**先頭**に**追加**することができます。
* 2つのサブステートステップで**1つのリクエストともう1つのリクエストの間の処理を遅延**させる場合、両方のリクエストの間に**追加のリクエストを追加**することができます。
* **multi-endpoint**のRCの場合、**隠れた状態に移動するリクエスト**を送信し、その後**その隠れた状態を利用するリクエストを50回**送信します。
### Raw BF
前の研究の前に、RCを引き起こすためにパケットをできるだけ速く送信しようとするいくつかのペイロードが使用されました。
* **Repeater:** 前のセクションの例を確認してください。
* **Intruder**: **リクエスト**を**Intruder**に送信し、**オプションメニュー**で**スレッド数**を**30**に設定し、ペイロードとして**Null payloads**を選択して**30**を生成します。
* **Turbo Intruder**
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
pipeline=False
)
a = ['Session=','Session=','Session=']
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**
Pythonの非同期処理(asyncio)
```python
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())
```
## **RCの方法論**
### 制限超過/TOCTOU
これは最も基本的なタイプの競合状態であり、**アクションを実行できる回数を制限する場所に現れる** **脆弱性**が存在します。たとえば、ウェブストアで同じ割引コードを複数回使用することです。[**このレポート**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43)や[**このバグ**](https://hackerone.com/reports/759247)****に非常に簡単な例があります。
この種の攻撃にはさまざまなバリエーションがあります。
* ギフトカードを複数回利用する
* 製品に複数回評価を付ける
* 口座残高を超えて現金を引き出すまたは送金する
* 単一のCAPTCHAソリューションを再利用する
* 反ブルートフォースのレート制限をバイパスする
### **隠れたサブステート**
他の最も複雑なRCは、攻撃者がアクセスすることを意図されていなかった状態を悪用できる**マシンのサブステート**を利用しますが、攻撃者がアクセスするための**小さなウィンドウ**があります。
1. **潜在的な隠れた興味深いサブステートを予測する**
最初のステップは、それに書き込むか、それからデータを読み取り、それを重要な何かに使用するすべてのエンドポイントを特定することです。たとえば、ユーザーは登録、プロファイル編集、パスワードリセットの開始、パスワードリセットの完了によって変更されるデータベーステーブルに保存される場合があります。
次の3つの重要な質問を使用して、衝突の可能性が低いエンドポイントを除外できます。各オブジェクトと関連するエンドポイントについて、次のように尋ねます。
* **状態はどのように保存されていますか?**
永続的なサーバーサイドのデータ構造に保存されているデータは、悪用に適しています。一部のエンドポイントは、パスワードリセットなど、JWTをメールで送信することによって動作するように、完全にクライアントサイドに状態を保存します。これらは安全にスキップできます。
アプリケーションは、ユーザーセッションに一部の状態を保存することがよくあります。これらは通常、サブステートに対してある程度保護されています。後で詳しく説明します。
* **編集または追加していますか?**
既存のデータを編集する操作(アカウントの主なメールアドレスを変更するなど)は、十分な衝突の可能性がありますが、既存のデータに追加するだけの操作(追加のメールアドレスを追加するなど)は、制限超過攻撃以外の脆弱性に対して脆弱ではありません。
* **操作は何にキー付けられていますか?**
ほとんどのエンドポイントは、ユーザー名、パスワードリセットトークン、ファイル名などの「キー」を使用して検索される特定のレコードで動作します。成功した攻撃には、同じキーを使用する2つの操作が必要です。たとえば、2つの考えられるパスワードリセットの実装を想像してみてください。
2. **手がかりを探る**
この時点で、潜在的に興味深いエンドポイントに対していくつかのRC攻撃を**実行**して、通常のものとは異なる結果を見つけようとします。応答の変化、または異なるメールの内容やセッションの目に見える変化など、予想される応答からの逸脱は、何かが間違っていることを示す手がかりになる可能性があります。
3. **コンセプトを証明する**
最後のステップは、**コンセプトを証明し、攻撃可能な攻撃に変える**ことです。
一括のリクエストを送信すると、初期のリクエストペアが脆弱なエンドステートをトリガーする場合がありますが、後のリクエストがそれを上書き/無効にし、最終的な状態は攻撃できないものになります。このシナリオでは、不要なリクエストをすべて削除する必要があります。ほとんどの脆弱性を悪用するには2つのリクエストが十分です。ただし、2つのリクエストにすると、攻撃はタイミングに敏感になるため、攻撃を複数回リトライするか、自動化する必要がある場合があります。
### タイムセンシティブ攻撃
場合によっては、競合状態を見つけることができないかもしれませんが、**正確なタイミングでリクエストを送信するための技術**は、他の脆弱性の存在を明らかにすることができます。
その一例として、セキュリティトークンを生成するために、**暗号化されたランダムな文字列の代わりに高解像度のタイムスタンプが使用される**場合があります。
タイムスタンプのみを使用してランダム化された**パスワードリセットトークン**を考えてみましょう。この場合、**同じトークン**を生成するようにリクエストのタイミングを合わせることで、**2つの異なるユーザーのために2つのパスワードリセットをトリガー**することができるかもしれません。
{% hint style="warning" %}
たとえば、前述の状況を確認するには、**同時に2つのパスワードリセットトークンを要求**(シングルパケット攻撃を使用)し、それらが**同じ**かどうかを確認します。
{% endhint %}
[**このラボの例**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities)を確認してください。
## 隠れたサブステートのケーススタディ
### 商品の支払いと追加
[**このラボ**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation)をチェックして、**支払い**を行い、**追加の商品**を追加する方法を確認してください。追加の商品には支払いが必要ありません。
### 他のメールの確認
アイデアは、**メールアドレスを確認し、同時に別のメールアドレスに変更**し、プラットフォームが新しいメールアドレスを確認するかどうかを確認することです。
### 2つのメールアドレスに電子メールを変更する(Cookieベース)
[**この解説**](https://portswigger.net/research/smashing-the-state-machine)によると、Gitlabはこの方法で乗っ取られる可能性がありました。なぜなら、Gitlabは**1つのメールの電子メール確認トークンを他のメールに送信**する可能性があるからです。
これについては、[**このラボ**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint)もチェックしてください。
### 隠れたデータベースの状態/確認バイパス
**2つの異なる書き込み**が使用されて**データベース**に**情報を追加**する場合、最初のデータがデータベースに書き込まれた後、**2番目のデータ
### 2FAのバイパス
以下の疑似コードは、ウェブサイトがこの攻撃のレースバリエーションに対して脆弱である可能性を示しています。
```python
session['userid'] = user.userid
if user.mfa_enabled:
session['enforce_mfa'] = True
# generate and send MFA code to user
# redirect browser to MFA code entry form
```
この場合、**単一のリクエスト内での複数のステップのシーケンス**が実際に存在することがわかります。最も重要なことは、**ユーザーが一時的に有効なログインセッションを持っているが、MFAがまだ強制されていない**というサブステートを経由することです。攻撃者は、ログインリクエストと共に、機密な認証済みエンドポイントへのリクエストを送信することで、これを悪用する可能性があります。
### OAuth2の永続性
いくつかの[**OAuthプロバイダー**](https://en.wikipedia.org/wiki/List\_of\_OAuth\_providers)があります。これらのサービスは、プロバイダーが登録したユーザーを認証し、アプリケーションにアクセスを許可することができます。そのためには、**クライアント**が**アプリケーションにアクセスを許可**する必要があります。**OAuthプロバイダー**内の一部のデータにアクセスするためです。\
したがって、ここまでは、Google/LinkedIn/GitHubなどの一般的なログインで、以下のようなページが表示されます: "_Application \ があなたの情報にアクセスすることを希望しています。許可しますか?_"
#### `authorization_code`における競合状態
**問題**は、**それを受け入れ**、自動的に**`authorization_code`**を悪意のあるアプリケーションに送信するときに発生します。その後、この**アプリケーションはOAuthサービスプロバイダー内の競合状態を悪用して、`authorization_code`から複数のAT/RT**(_認証トークン/リフレッシュトークン_)を生成します。基本的には、あなたがアプリケーションがデータにアクセスすることを許可したことを悪用して、**複数のアカウントを作成**します。その後、**アプリケーションにデータへのアクセスを許可しなくなると、1つのAT/RTのペアは削除されますが、他のものは有効のまま**です。
#### `Refresh Token`における競合状態
有効なRTを**取得した後**、それを悪用して複数のAT/RTを生成しようとすることができます。そして、ユーザーが悪意のあるアプリケーションに対してアクセス許可をキャンセルした場合でも、**複数のRTは有効のまま**です。
## WebSocketsにおける競合状態
[**WS\_RaceCondition\_PoC**](https://github.com/redrays-io/WS\_RaceCondition\_PoC)では、JavaでWebソケットメッセージを**並列**に送信して、**Webソケットでも競合状態を悪用**するPoCを見つけることができます。
## 参考文献
* [https://hackerone.com/reports/759247](https://hackerone.com/reports/759247)
* [https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html](https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html)
* [https://hackerone.com/reports/55140](https://hackerone.com/reports/55140)
* [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
* [https://portswigger.net/web-security/race-conditions](https://portswigger.net/web-security/race-conditions)
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
* **サイバーセキュリティ企業で働いていますか?** HackTricksで**会社を宣伝**したいですか?または、**PEASSの最新バージョンにアクセス**したり、HackTricksを**PDFでダウンロード**したりしたいですか?[**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)をチェックしてください!
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)を発見しましょう。独占的な[**NFT**](https://opensea.io/collection/the-peass-family)のコレクションです。
* [**公式のPEASS&HackTricksのグッズ**](https://peass.creator-spring.com)を手に入れましょう。
* [**💬**](https://emojipedia.org/speech-balloon/) [**Discordグループ**](https://discord.gg/hRep4RUj7f)または[**Telegramグループ**](https://t.me/peass)に参加するか、**Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**をフォロー**してください。
* **ハッキングのトリックを共有するには、**[**hacktricksのリポジトリ**](https://github.com/carlospolop/hacktricks) **と** [**hacktricks-cloudのリポジトリ**](https://github.com/carlospolop/hacktricks-cloud) **にPRを提出**してください。
\
[**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks)を使用して、世界で最も高度なコミュニティツールによって強化された**ワークフローを簡単に構築**し、自動化します。\
今すぐアクセスを取得してください:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}