source : https://tutorialboy24.blogspot.com/2022/06/the-various-utilization-methods-of-php.html
Serialization & Deserialization
To facilitate data storage, php usually converts data such as arrays into serialized form for storage, so what is serialization? Serialization is actually converting data into a reversible data structure. Naturally, the reverse process is called deserialization.
There is a vivid example on the Internet, which will make us deeply remember that the purpose of serialization is to facilitate the transmission and storage of data. In PHP, serialization and deserialization are generally used for caching, such as session caching, cookies, etc .
Now we all buy tables on Taobao. How do transport such irregular things from one city to another? At this time, we usually dismantle them into boards, put them in boxes, and then send them by express. Going out, this process is similar to our serialization process (converting data into a form that can be stored or transmitted). When the buyer receives the goods, they need to assemble these boards into a table by themselves. This process is like a reverse sequence process (transformed into the original data object).
Serialize() & Unserialize()
PHP uses two functions to serialize and deserialize data: serialize() formats the object into an ordered string unserialize() restores the string to the original object.
Php Deserialization
PHP deserialization is a necessary basis for code auditing, and this knowledge point is a standing knowledge point for ctf competitions. Because PHP objects need to express more content, there will be a basic format for basic type expression, which is roughly divided into six types .
boolean (bool) | b:value-->Example: b:0 |
---|---|
Integer type (int) | i:value-->Example: i:1 |
String type (str) | s:/length:"value"-->Example: s:4:"aaaa" |
Array type (array) | a:/length:{key:value pairs};-->Example: a:1:{i:1:/s:1:"a"} |
object | O:< class_name_length > |
NULL type | N |
a - array
b - boolean
d - double
i - integer
o - common object
r - reference
s - string
C - custom object
O - class
N - null
R - pointer reference
U - unicode string
Example
<?php class message{
public $from='d';
public $msg='m';
public $to='1';
public $token='user';
}
$msg= serialize(new message);
print_r($msg);
Output
O:7:"message":4:{s:4:"from";s:1:"d";s:3:"msg";s:1:"m";s:2:"to";s:1:"1";s:5:"token";s:4:"user";}
At the same time, it should be noted that the serialized content only has member variables and no member functions, as shown in the following example:
<?php
class test{
public $a;
public $b;
function __construct(){$this->a = "xiaoshizi";$this->b="laoshizi";}
function happy(){return $this->a;}
}
$a = new test();
echo serialize($a);
?>
Output
O:4:"test":2:{s:1:"a";s:9:"xiaoshizi";s:1:"b";s:8:"laoshizi";}
From the output results, we can see that the construct() and happy() functions, including the classes in the functions, will not be output.
If the variable is protected, it will be added before the variable name x00*x00 , and private will be added before the variable name x00 class name x00 . Such as the following cases:
<?php
class test{
protected $a;
private $b;
function __construct(){$this->a = "xiaoshizi";$this->b="laoshizi";}
function happy(){return $this->a;}
}
$a = new test();
echo serialize($a);
echo urlencode(serialize($a));
?>
The output will cause the loss of the invisible character x00, so the storage is more recommended in the form of base64 encoding:
O:4:"test":2:{s:4:" * a";s:9:"xiaoshizi";s:7:" test b";s:8:"laoshizi";}
Deserialization Vulnerabilities and Magic Methods
There is often no suitable utilization chain in the actual digging process, which requires the use of native classes that come with PHP itself. Here are some magic methods that deserialization exploits.
__wakeup() // While executing unserialize(), this function will be called first
__sleep() // When serialize() excuted,this function will be called first
__destruct() // Trigger when the object is destroyed
__call() // Triggered when an inaccesible method is called in the object context
__callStatic() // Triggered when an inaccesible method is called in a static context
__get() // This method is called for reading data from inaccesible properties or if the key doesn't exist
__set() // Use to write data to inaccesible properties
__isset() // Triggered by calling isset() or empty() on an inaccesible property
__unset() // Triggered when unset() is used on a inaccesible property
__toString() // Triggered when the class is used as a string
__invoke() // Triggered when trying to call an object as a function
__construct() // Triggered when the object is created
Deserialization Exploit (Bypass)
Php7.1+ deserialization is not sensitive to class attributes. We said earlier that if the variable is protected, the serialization result will add x00*x00 to the variable name
However, in certain versions above 7.1, it is not sensitive to class attributes. For example, the following example will still output abc even if there is no x00*x00.
<?php
class test{
protected $a;
public function __construct(){
$this->a = 'abc';
}
public function __destruct(){
echo $this->a;
}
}
unserialize('O:4:"test":1:{s:1:"a";s:3:"abc";}');
?>
Example question: [Net Ding Cup 2020 Qinglong Group] AreUSerialz (BUUCTF)