[CyberSecurityLearning 69] deserialization vulnerability

catalogue

Deserialization

Why serialize

Serialization and deserialization in PHP

*Simple example

*Serialize Demo

*Where are the loopholes?

@Create a class, an object, and serialize and deserialize it

@Deserialization injection

*Why

 

Deserialization

Why serialize

class
obj object

Baidu Encyclopedia's definition of serialization is the process of converting the state information of an object into a form (string) that can be stored or transmitted. During serialization, the object writes its current state to the temporary or persistent storage area (store it in the database. The preferred database is Redis, or a key value pair database of type Redis. It can be understood that the Redis database is a large array accessed through key value pairs, and the relational database is a large Excel table). Later, you can recreate the object by reading or deserializing its state from the store.

To put it simply, serialization is to turn an object into a string that can be transmitted (convenient for transmission), and deserialization is the process of converting a string into an object (if the string client is controllable, we can let the web application deserialize any object. What's more, we will trigger some executable PHP code, such as phpinfo, in the process of deserialization), Processes can communicate across platforms and safely in a specific format.

<?php
class Stu{
	public $name;
	public $sex;
	public $agel;
	public $score;
}
$stu1= new Stu();//Created an object new
$stu1->name="ZQX";
$stu1->sex=true;
$stu1->age=16;
$stu1->score=60;

$stu2= new Stu();
$stu2->name="HMM";
$stu2->sex=false;
$stu2->age=16;
$stu2->score=90;

echo $stu1->name."'s score = ".$stu1->score;  //ZQX's score = 60 find the object name first and then its attribute 
echo $stu2->name."'s score = ".$stu2->score;
echo "<hr />";
var_dump($stu1);
//The object stu1, an abstract data structure, is transformed into a string and stored in a file on the hard disk. This process is called serialization
//Advantages of serialization: we can pause a user's state, take out the string from the hard disk when the user activates, deserialize it into an object, and then store it in memory for him to work.
?>

Serialization and deserialization in PHP

PHP deserialization vulnerability, also known as PHP object injection, is a common vulnerability. Although this type of vulnerability is difficult to exploit, once successfully exploited, it will cause very threatening consequences. The root cause of the vulnerability is that the programmer does not detect the deserialization string entered by the user, resulting in the deserialization process can be maliciously controlled, resulting in a series of uncontrollable consequences such as code execution and getshell. Deserialization vulnerability is not unique to PHP, but also exists in Java, Python and other languages, but its principle is basically the same.

Serialization and deserialization in PHP are basically expanded around two functions: serialize() and unserialize().
 

*Simple example

We can understand the serialization and deserialization process by using the encoding and decoding of json format data (json format is a formatted string, that is, the data in json format has its own certain format). Although json data has nothing to do with deserialization vulnerabilities, this example helps us understand.

Test code:

<?php
$stu=array('name'=>'Waffle','age'=>20,'SEX'=>true,'score'=>96.6);
echo $stu;  //echo cannot output an array
echo "<hr />";
$stu_json=json_encode($stu);//But if we convert the number $stu to json format_ encode
//Array is an abstract array. After being encoded in json format, it will become a string. After becoming a string, it can be output with echo
echo $stu_json;
?>

We define an array, which is an abstract data structure. In order to facilitate cross platform transmission, it can be json encoded. Data in json format is in the form of key value pairs.

Array{"name":"Waffle","age":20,"SEX":true,"score":96.6}

<?php
class Stu{
	public $name;
	public $sex;
	public $agel;
	public $score;
}
$stu1= new Stu();//Created an object new
$stu1->name="ZQX";
$stu1->sex=true;
$stu1->age=16;
$stu1->score=60;

$stu2= new Stu();
$stu2->name="HMM";
$stu2->sex=false;
$stu2->age=16;
$stu2->score=90;

echo $stu1->name."'s score = ".$stu1->score;  //ZQX's score = 60 find the object name first and then its attribute 
echo $stu2->name."'s score = ".$stu2->score;
echo "<hr />";
//var_dump($stu1);
//The object stu1, an abstract data structure, is transformed into a string and stored in a file on the hard disk. This process is called serialization
//Advantages of serialization: we can pause a user's state, take out the string from the hard disk when the user activates, deserialize it into an object, and then store it in memory for him to work.
//echo $stu1;// (x) It cannot be output as a string. Next, we need to convert stu1
echo serialize($stu1);//The serialize function will serialize our object and serialize it into a string
//O:3:"Stu":5:{s:4:"name";s:3:"ZQX";s:3:"sex";b:1;s:4:"agel";N;s:5:"score";i:60;s:3:"age";i:16;}
//O stands for object, 3 is the length of the class name, and 5 indicates that there are four attributes in our class. Each sentence ends with a semicolon, s stands for string type, and b stands for bool type
?>

*Serialize Demo

Serialization converts an abstract to a string.

We can write a Demo to illustrate the serialization process. First, create a class with the following code

<?php
class Stu{
public $name;
public $sex;
public $age;
public $score;
}
?>

The class name is Stu and there are four variables.

Next, we create an object and assign values to variables in the object. The code is as follows

<?php 
include "classStu.php";
$stu1 = new Stu();
$stu1->name = "Waffle";
$stu1->sex = true;
$stu1->age = 18;
$stu1->score = 89.9;
echo serialize($stu1);
?>

Finally, we use the serialize() function to serialize the $stu1 object into a string. Such a string is easy to transmit and store. as follows

O:3:"Stu":4 / / O stands for Object object; 3. The Object name has three characters; There are four variables in the Object

    {s:4:"name";s:3:"GGG";

    s:3:"sex";b:1;

    s:3:"age";i:18;

    s:5:"score";d:89.900000000000006;}
 

Similarly, we can also use the deserialize () function to deserialize the string into an object. Since the string contains double quotation marks, we can use the delimiter. The code is as follows

<?php
 
include "classStu.php";
 
$stu1 =<<<HTML
O:3:"Stu":4:{s:4:"name";s:3:"GGG";s:3:"sex";b:1;s:3:"age";i:18;s:5:"score";d:89.900000000000006;}
HTML;
 
$stu1=unserialize($stu1);
 
var_dump($stu1);
 
?>

Running this script, we can see the deserialized object

    object(Stu)#1 (4) { ["name"]=> string(3) "GGG" ["sex"]=> bool(true) ["age"]=> int(18) ["score"]=> float(89.9) }

*Where are the loopholes?

@Create a class, an object, and serialize and deserialize it

<?php
 
class Test{
    public $str='Waffle';
    function __destruct(){
        //echo "This is function __contruct()";
        @eval($this->str);
    }
}
 
$test = new Test();
echo serialize($test);//serialize means serialization / / O:4:"Test":1:{s:3:"str";s:6:"Waffle";} There are only attributes and no methods 
echo "<hr />";
//$t=serialize($test);
//var_dump(unserialize($t)); //object(Test)#2 (1) { ["str"]=> string(6) "Waffle" } 
var_dump(unserialize($_GET['obj'])); //Deserialize it  
 
?>

@Deserialization injection

Construct serialized characters

.../class/loudong.php?obj=O:4:"Test":1:{s:3:"str";s:10:"phpinfo();";}

You will find that the phpinfo() function has been executed

It can be found from the above code that the deserialization vulnerability of PHP needs to cooperate with other vulnerabilities, such as code execution SQLi, etc

 

*Why

Why does the injected string [phpinfo()] run as a PHP statement? Observe the code and find a function in the class__ destruct() and the eval statement called by this function executes the $this - > STR variable. Why__ If destruct () is not called, the statement in the function is executed?
You can test with the following code__ destruct() function

<?php
 
class Test{
 
public $str='GGG';
 
function __destruct(){
 
echo "This is function __destruct()";
 
//@eval($this->str);
 
}
 
}
 
$test = new Test();
 
echo serialize($test);
 
echo "<hr />";
 
var_dump(unserialize($_GET['obj']));
 
?>

We will find that when destroying instantiated classes (that is, objects)__ The destruct() function is called and outputs a string

 

With__ The first method is the magic method in PHP and the magic method in class, which will be called automatically under specific circumstances. The main methods of magic are as follows

__construct()

Called automatically when an object is created

__destruct()

Called automatically when an object is destroyed

__call()

When an invocation method is invoked in an object, call() will be called

__callStatic()

Call when an invocable method is invoked in a static context

__get()

When reading the value of an inaccessible property__ get() will be called

__set()

When assigning a value to an inaccessible property__ set() will be called

__isset()

When isset() or empty() is called on an inaccessible property__ Isset() will be called

__unset()

When unset() is called on an inaccessible property__ Unset() will be called

__sleep()

The serialize() function checks whether a magic method exists in the class__ sleep(), if any, will be called first and then serialized

__wakeup()

unserialize() checks to see if there is one__ wakeup() method, if any, will be called first__ The wakeup method prepares the resources required by the object in advance

__toString()

__ The toString () method is used to respond when a class is treated as a string

__invoke()

When you try to call an object by calling a function__ The invoke() method is called automatically

__set_state()

Calling var from PHP 5.1.0_ When export() exports a class, this static method will be called

__clone()

When the copy is complete, if defined__ Clone method, the__ The clone() method is called and can be used to modify the value of the property.

__debugInfo()This method is called by var_dump() anobject to get the properties that should be shown .If the method isn't on an object ,then all public ,protec''ted and private propertieswill be shown.

Reference link:
http://www.freebuf.com/articles/web/167721.html
https://baike.baidu.com/item/%E5%BA%8F%E5%88%97%E5%8C%96/2890184?fr=aladdin
https://www.cnblogs.com/magic-zero/p/7737274.html
https://mp.weixin.qq.com/s?__biz=MzAxNDY2MTQ2OQ==&mid=2650942666&idx=1&sn=5c84d6d69463a0a430e01dfa68c2d3ab&chksm=80796ef8b70ee7ee8ba5d88feb8d794bee19a55b6e17dff45fcee6ba6ee726fb4e2e029d50bd&scene=0#rd
 

Added by chordsoflife on Fri, 04 Mar 2022 12:58:48 +0200