hacktricks/pentesting-web/race-condition.md

327 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# レースコンディション
<figure><img src="../.gitbook/assets/image (3) (1).png" alt=""><figcaption></figcaption></figure>
\
[**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" %}
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* **サイバーセキュリティ企業で働いていますか?** 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)のコレクションです。
* [**公式のPEASSHackTricks 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)**をフォロー**してください。
* **ハッキングのトリックを共有するには、**[**hacktricks repo**](https://github.com/carlospolop/hacktricks) **および** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **にPRを提出**してください。
</details>
## RCの悪用
RCの悪用の主な問題は、リクエストが非常に短い時間差通常> 1msで並行して処理される必要があることです。次のセクションでは、これを可能にするためのさまざまな解決策が提案されています。
<figure><img src="../.gitbook/assets/image (5) (1).png" alt=""><figcaption></figcaption></figure>
### シングルパケット攻撃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のリクエストがサーバーに同時に到着することができます。
<figure><img src="../.gitbook/assets/image (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
**ターゲットアーキテクチャに適応する**
多くのアプリケーションはフロントエンドサーバーの背後にあり、これらは一部のリクエストを既存の接続を介してバックエンドに転送し、他のリクエストに対しては新しい接続を作成する場合があります。
そのため、アプリケーションの動作による一貫性のないリクエストタイミングをロックメカニズムなどのアプリケーションの動作に帰することは重要ではありません。また、フロントエンドのリクエストルーティングは通常、接続ごとに行われるため、攻撃を実行する前にサーバーサイドの接続ウォーミングを実行することで、リクエストのタイミングをスムーズにすることができる場合があります(これは、実際の攻撃を開始する前にいくつかのリクエストを送信するだけです)。
#### セッションベースのロックメカニズム <a href="#session-based-locking-mechanisms" id="session-based-locking-mechanisms"></a>
一部のフレームワークでは、**リクエストロック**としての形式のデータ破損を防ぐ試みが行われています。たとえば、**PHPのネイティブセッションハンドラ**モジュールは、**1つのセッションあたり1つのリクエストのみ**を処理します。
このような動作を見つけることは非常に重要です。なぜなら、すべてのリクエストが順次処理されていることに気付かないと、簡単に悪用できる脆弱性をマスクする可能性があるからです。すべてのリクエストが順次処理されていることに気付いた場合は、それぞれのリクエストを異なるセッショントークンを使用して送信してみてください。
#### **レート制限またはリソース制限の乱用**
接続のウォーミングが効果がない場合、この問題に対するさまざまな解決策があります。
Turbo Intruderを使用すると、クライアント側で短い遅延を導入することができます。ただし、これには実際の攻撃リクエストを複数のTCPパケットに分割する必要があるため、シングルパケット攻撃技術を使用することはできません。その結果、高ジッターターゲットでは、どのような遅延を設定しても攻撃が確実に機能しない可能性があります。
<figure><img src="../.gitbook/assets/image (2) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
代わりに、一般的なセキュリティ機能を乱用することで、この問題を解決することができる場合があります。
Webサーバーは、リクエストがあまりにも速く送信された場合に処理を遅延させることがよくあります。ダミーの大量のリクエストを送信してレート制限またはリソース制限を意図的にトリガーすることで、適切なサーバーサイドの遅延を引き起こすことができるかもしれません。これにより、遅延実行が必要な場合でも、シングルパケット攻撃が実行可能になります。
<figure><img src="../.gitbook/assets/image (3) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
{% 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`**のように変更し、`csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s`のように選択します。次に、ドロップダウンから**`examples/race-single-packer-attack.py`**を選択します:
<figure><img src="../.gitbook/assets/image (4) (1) (1).png" alt=""><figcaption></figcaption></figure>
**異なる値を送信する**場合は、クリップボードからワードリストを使用するこのコードに変更できます:
```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回**送信します。
<figure><img src="../.gitbook/assets/image (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
### 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_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**
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 Methodology**
### Limit-overrun / TOCTOU
これは最も基本的な競合状態のタイプであり、**アクションの実行回数を制限する場所に現れる脆弱性**が存在します。たとえば、ウェブストアで同じ割引コードを複数回使用することです。[**このレポート**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43)や[**このバグ**](https://hackerone.com/reports/759247)****に非常に簡単な例があります。
この種の攻撃には、次のような多くのバリエーションがあります。
- ギフトカードを複数回利用する
- 製品に複数回評価を付ける
- 口座残高を超えて現金を引き出すまたは送金する
- 単一のCAPTCHAソリューションを再利用する
- 反復試行防止の制限をバイパスする
### **Hidden substates**
他の最も複雑なRCは、攻撃者がアクセスすることを意図されていなかった状態を悪用できる可能性のあるマシン状態の**サブステート**を利用しますが、攻撃者がアクセスするための**小さなウィンドウ**があります。
1. **潜在的な隠れた興味深いサブステートを予測する**
最初のステップは、それに書き込むか、それからデータを読み取り、それを重要な何かに使用するすべてのエンドポイントを特定することです。たとえば、ユーザーは登録、プロファイル編集、パスワードリセットの開始、パスワードリセットの完了によって変更されるデータベーステーブルに保存される場合があります。
次の3つの重要な質問を使用して、衝突の可能性が低いエンドポイントを除外できます。各オブジェクトと関連するエンドポイントについて、次のように尋ねます。
- **状態はどのように保存されていますか?**
永続的なサーバーサイドのデータ構造に保存されているデータは、悪用に適しています。一部のエンドポイントは、パスワードリセットなど、JWTをメールで送信することによって動作するように、完全にクライアントサイドに状態を保存します。これらは安全にスキップできます。
アプリケーションは、ユーザーセッションに一部の状態を保存することがよくあります。これらは通常、サブステートに対してある程度保護されています。後で詳しく説明します。
- **編集または追加ですか?**
既存のデータを編集する操作(アカウントの主なメールアドレスの変更など)は、十分な衝突の可能性がありますが、既存のデータに追加するだけの操作(追加のメールアドレスの追加など)は、制限超過攻撃以外の脆弱性に対して脆弱ではありません。
- **操作は何にキー付けられていますか?**
ほとんどのエンドポイントは、ユーザ名、パスワードリセットトークン、ファイル名などの「キー」を使用して特定のレコードで操作します。成功した攻撃には、同じキーを使用する2つの操作が必要です。たとえば、2つの考えられるパスワードリセットの実装を想像してみてください。
<figure><img src="../.gitbook/assets/image (2) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
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)を確認してください。
## Hidden substates case studies
### 商品の支払いと追加
[**このラボ**](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つの異なる書き込み**が使用されて**データベース**に**情報を追加**する場合、最初のデータがデータベースに書き込まれた後のわずかな時間だけ、**最初のデータだけが
```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 \<InsertCoolName> があなたの情報にアクセスすることを希望しています。許可しますか_"
#### `authorization_code`における競合状態
**問題**は、**それを受け入れ**、自動的に**`authorization_code`**を悪意のあるアプリケーションに送信するときに発生します。その後、この**アプリケーションはOAuthサービスプロバイダー内の競合状態を悪用して、`authorization_code`から複数のAT/RT**_認証トークン/リフレッシュトークン_を生成します。基本的には、あなたがアプリケーションがデータにアクセスすることを許可したことを悪用して、**複数のアカウントを作成**します。その後、**アプリケーションにデータへのアクセスを許可しなくなると、1組のAT/RTは削除されますが、他のものは有効のまま**です。
#### `Refresh Token`における競合状態
有効なRTを**取得した後**、それを悪用して複数のAT/RTを生成しようとすることができます。そして、ユーザーが悪意のあるアプリケーションに対してアクセス許可をキャンセルした場合でも、**複数のRTは有効のまま**です。
## 参考文献
* [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)
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* **サイバーセキュリティ企業で働いていますか?** 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)のコレクションです。
* [**公式のPEASSHackTricksのグッズ**](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 repo**](https://github.com/carlospolop/hacktricks) **と** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **にPRを提出**してください。
</details>
<figure><img src="../.gitbook/assets/image (3) (1).png" alt=""><figcaption></figcaption></figure>
\
[**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" %}