Web渗透—PHP反序列化????????课程学习分享(课程非本人制作,仅提供学习分享)
靶场下载地址:GitHub - mcc0624/php_ser_Class: php反序列化靶场课程,基于课程制作的靶场
序列化(Serialization)是将对象的状态信息(属性)转换为可以存储或传输的形式的过程。
对象 —(序列化)—>?字符串
将对象或数组转化为可以存储/传输的字符串
所有格式第一位都是数据类型的英文字母简写(字符串中 s: 后跟的是字符串的长度)。
<?php
$a = null; ??????????????????????//空字符
$b = 666; ????????? ? ? ? ? ? ? ?//整形
$c = 66.6; ???????? ? ? ? ? ? ? ?//浮点型
$d = true;? ? ? ? ? ? ? ? ? ? ?? //Boolean型
$e = false;
$f = 'benben';? ? ? ? ? ? ? ? ? //字符串
echo serialize($a)."\n";
echo serialize($b)."\n";
echo serialize($c)."\n";
echo serialize($d)."\n";
echo serialize($e)."\n";
echo serialize($f);
?>
输出结果:
N; ???????????????????????????-> 空字符
i:666;? ? ? ? ? ? ? ? ? ? ? ? -> 整形
d:66.6;? ? ? ? ? ? ? ? ? ? ? ?-> 浮点型
b:1; ?????????????????????????-> Boolean型
b:0;
s:6:"benben";?????????????????-> 字符串
数组的序列化
<?php
$a = array('benben','dazhuang','laoliu');
echo $a[0]."\n";
echo serialize($a);
?>
输出结果:
benben
a:3:{i:0;s:6:"benben";i:1;s:8:"dazhuang";i:2;s:6:"laoliu";}
a?array:3?参数数量:{i:0?编号;s:6:"benben";i:1;s:8:"dazhuang";i:2;s:6:"laoliu";}
不能序列话 '类' ,可以序列化 '对象'
<?php
class test{
public $pub = 'benben';
function jineng(){
echo $this->pub;
}
}
$a = new test();
echo serialize($a);???????? //只序列化成员变量,不序列化成员函数
?>
输出结果:
O:4:"test":1:{s:3:"pub";s:6:"benben";}
Oobject:4类名长度:"test"类名:1变量数量:{s:3变量名字长度:"pub"变量名字;s:6值的长度:"benben"变量值;}
私有修饰符
private私有属性序列化是在变量前加”%00类名%00”
<?php
class?test{
private?$pub='benben';
function?jineng(){
echo?$this->pub;
}
}
$a?=?new?test();
echo?serialize($a); ????????//echo urlencode(serialize($a));(可使用url编码来反序列化)
?>? ? ? ? ? ? ? ? ? ? ? ? ? //00隔开,’pub’是’test’的私有属性
输出结果:
O:4:"test":1:{s:9:"testpub";s:6:"benben";}
O:4:"test":1:{s:9变量名字长度:"testpub"%00类名%00变量名(%00占一位);s:6:"benben";}
保护修饰符
protedted受保护属性序列化时在变量名前加”%00*%00”
<?php
class?test{
????protected?$pub='benben';
????function?jineng(){
????????echo?$this->pub;
????}
}
$a?=?new?test();
echo?serialize($a); ????????//echo urlencode(serialize($a))(可使用url编码来对反序列化编码)
?>
输出结果:
O:4:"test":1:{s:6:"*pub";s:6:"benben";}
O:4:"test":1:{s:6变量名字长度:"*pub"%00*%00变量名(%00和*都只占一位);s:6:"benben";}
成员属性调用对象(在对象里调用对象)
<?php
class?test{
var?$pub='benben';
function?jineng(){
echo?$this->pub;
}
}
class?test2{
var?$ben;
function?__construct(){
$this->ben=new?test();
}
}
$a?=?new?test2();
echo?serialize($a);
?>
输出结果:
O:5:"test2":1:{s:3:"ben";O:4:"test":1:{s:3:"pub";s:6:"benben";}}
<?php
class test{
var $pub='benben';
function jineng(){
echo $this->pub;
}
}
class test2{
var $ben;
}
$b = new test();
$a = new test2();
$a->ben = $b;
echo serialize($a);
?>
输出结果:
O:5:"test2":1:{s:3:"ben";O:4:"test":1:{s:3:"pub";s:6:"benben";}}
实例化后的对象 $a 的成员变量 'ben'?调用实例化后的对象 $b
1)反序列化之后的内容为一个对象;
2)反序列化生成的对象里的值,由反序列化里的值提供;与原有类预定义的值无关;
3)反序列化不触发类的成员方法;需要调用方法后才能触发;
将序列化后的参数还原成实例化的对象。
对象? —(序列化)—>? 字符串
对象? <—(反序列化)—? 字符串
实例演示
<?php
class?test?{
public??$a?=?'benben';
protected??$b?=?666;
private??$c?=?false;
public?function?displayVar()?{
echo?$this->a;
}
}
$d?=?new?test(); ???????????????????????//将test类实例化为对象$d
$d?=?serialize($d);? ? ? ? ? ? ? ? ? ???//将$d序列化为字符串,并重新赋值给$d
echo?$d."\n"; ??????????????????????????//输出$d(已经进行了序列化)
echo?urlencode($d)."\n";? ? ? ? ? ? ????//输出进行url编码后的$d
$a?=?urlencode($d);? ? ? ? ? ? ? ? ? ? ?//将url编码后的$d赋值给$a
$b?=?unserialize(urldecode($a)); ???????//将url解码并反序列化后的$a赋值给$b
var_dump($b);? ? ? ? ? ? ? ? ? ? ? ? ? ?//查看$b内的值
?>
输出结果:
O:4:"test":3:{s:1:"a";s:6:"benben";s:4:" * b";i:666;s:7:" test c";b:0;}
O%3A4%3A%22test%22%3A3%3A%7Bs%3A1%3A%22a%22%3Bs%3A6%3A%22benben%22%3Bs%3A4%3A%22%00%2A%00b%22%3Bi%3A666%3Bs%3A7%3A%22%00test%00c%22%3Bb%3A0%3B%7D
object(test)#1 (3) {
? ["a"]=>
? string(6) "benben"
? ["b":protected]=>
? int(666)
? ["c":"test":private]=>
? bool(false)
}