Getting started with php deserialization vulnerability

table of Contents

What is php serialization?

serialize() instance

Array deserialization instance

Examples of objects deserialized 

unserialize() instance 

Array serialization instance

Object serialization instance

Serialized string format analysis 

Variable type

The difference between public, private, and protected after serialization

Magic method

Common magic methods

Method call example

__sleep()

__wakeup()

__toString()

Principle of deserialization vulnerability

Reference link


What is php serialization?

The two functions used

serialize()     //函数用于序列化对象或数组,并返回一个字符串。
unserialize()   //函数用于将通过 serialize() 函数序列化后的对象或数组进行反序列化,并返回原始的对象结构。

 

serialize() instance

Array serialization instance

After serializing a set of arrays, get a string of strings


<?php
    highlight_file(__FILE__);
    $a = array('a' => 'Apple' ,'b' => 'banana' , 'c' => 'Coconut');
    $s = serialize($a);
    echo $s;
    //a:3:{s:1:"a";s:5:"Apple";s:1:"b";s:6:"banana";s:1:"c";s:7:"Coconut";} 
?>

 

Object serialization instance 

After serializing an object, get a string of strings

<?php
    highlight_file(__FILE__);
    class test_class{ //创建类
		var $test = '123'; //在类中新建一个test变量
	}
	
	$class1 = new test_class; //创建对象
	$class_str = serialize($class1);//序列化对象
	echo $class_str;//输出序列化后的字符串
//O:10:"test_class":1:{s:4:"test";s:3:"123";}
?>

unserialize() instance 

Array deserialization instance

Deserialize a serialized string in a standard format, and you will get the following array

<?php
    highlight_file(__FILE__);
    $str = 'a:3:{s:1:"a";s:5:"Apple";s:1:"b";s:6:"banana";s:1:"c";s:7:"Coconut";} ';
	$un_str=unserialize($str);	
	var_dump($un_str);	    
?>

 

Object deserialization instance

Deserialize a serialized string in a standard format to obtain a new object

<?php
    highlight_file(__FILE__);
    $str = 'O:10:"test_class":1:{s:4:"test";s:3:"123";}';
    $un_str=unserialize($str);
    var_dump($un_str);  
?> 

Serialized string format analysis 

O:10:"test_class":1:{s:4:"test";s:3:"123";}

Object type: class name length : class name: number of variables in the class : {variable: variable name length: variable name; variable type : variable content length : variable content }

 

a:3:{s:1:"a";s:5:"Apple";s:1:"b";s:6:"banana";s:1:"c";s:7:"Coconut";}

Array type: number of arrays : {variable: variable name length : variable name ; variable type : variable content length : variable content ;...}

 

  • There are two types of serialization:
    • Object type
    • Array type
  • It can be seen that in the braces, two semicolons (;) form a group, and the two semicolons represent the content of a variable.
    • {s:4:"test";s:3:"123";}

 

Variable type

Different storage types will be converted into different letters after serialization

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

The difference between public, private, and protected after serialization

  • Public (public): can be accessed within this class, external classes, and subclasses
  • Private (private): only available inside this class
  • Protected (protected): only this class or subclass or parent can access

After serializing according to the above 3 modifiers, the following results are obtained:

O:10:"test_class":3:{

s:6:"test_1";s:3:"str";

s:18:"test_classtest_3";i:123;

s:9:"*test_2";i:123;

}

 

  • public: basically no change after serialization
  • private: After serialization, the name of the class will be added to the variable name, and the length of the variable name will also increase
  • protected: After serialization, there will be an extra * before the variable name, but why does the length of the variable name become 9 bytes?
    • In fact, when the protected attribute is serialized, the format is %00*%00 member name

 

Magic method

When using PHP deserialization, it is often necessary to use the magic method in deserialization to check whether there are sensitive operations in the method.

PHP reserves all class methods starting with __ (two underscores) as magic methods.

Common magic methods

__construct()//创建对象时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__invoke() //当脚本尝试将对象调用为函数时触发
__sleep() //此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。
__wakeup() //经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。

php magic method official document 

 

 

Method call example

__sleep()

The serialize() function checks whether there is a magic method __sleep() in the class. If it exists, the method will be called first before the serialization operation is performed. This function can be used to clean up the object and return an array containing the names of all variables in the object that should be serialized. If the method does not return anything, NULL is serialized and an E_NOTICE level error is generated.

__wakeup()

unserialize() will check if there is a __wakeup() method. If it exists, the __wakeup method will be called first to prepare the resources needed by the object in advance.

__toString()

The __toString() method is used to respond when a class is treated as a string. For example echo $obj; what should be displayed. This method must return a string, otherwise a fatal error of E_RECOVERABLE_ERROR level will be issued.

Principle of deserialization vulnerability

When the parameters of deserialization unserialize() are controllable, we can construct a serialized string to modify the internal variables and even functions of the object.

Case:

<?php
error_reporting(0);
show_source(__FILE__);
class c{
	public $str = 111;
	
	function __wakeup(){
		echo $this->str;
		
	}
}

$str = $_GET['str'];
if (isset($str)){
	unserialize($str);
	}
?>

When we can control deserialization, we will be able to modify the contents of variables in the class

poc

?str=O:1:"c":1:{s:3:"str";s:3:"123";}

Of course it’s not that simple, just modify the content of the value, we can also type xss

poc

?str=O:1:"c":1:{s:3:"str";s:24:"<script>alert()</script>";}

Of course, this is just a simple case, I will explain the advanced knowledge of php deserialization next time.

 

Reference link

https://chybeta.github.io/2017/06/17/%E6%B5%85%E8%B0%88php%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/

https://xz.aliyun.com/t/3674

https://xz.aliyun.com/t/6753

https://xz.aliyun.com/t/7366

Guess you like

Origin blog.csdn.net/weixin_41924764/article/details/113093719