一、序列化和反序列化介绍
1、序列化
将复杂的数据结构(object) 转换为适合与传输和保存的字节类型(byte)。(存储)
2、反序列化
将字节类型转换为复杂数据结构(object) 。(程序使用)
二、序列化
<?php
class Site{
public $name = 'ctf';
public function get_name()
{
echo $name;
echo md5('admin');
}
}
$a = new Site();
$b = serialize($a);
echo $b;
?>
三、反序列化
<?php
class Site{
public $name = 'ctf';
public function get_name()
{
echo md5('admin');
}
}
$a = new Site();
$b = serialize($a);
$obj = unserialize($b);
$obj->get_name();
?>
四、CTF反序列化案列
unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源
<?php
$data = file_get_contents("php://input");
class Site{
public $name = 'ctf';
public function __wakeup()
{
echo "flag:".md5('123456');
}
}
$obj = unserialize($data);
?>
五、不安全反序列化实验
<?php
class User{
public $name = 'ctf';
public $isAdmin = false;
}
$user = unserialize($_POST['flag']);
if($user->isAdmin === true){
echo "flag:".md5('admin888');
}else{
echo "no flag";
}
?>
六、对象中的属性修饰符
在php代码中,定义 User
类,并且设置属性具有 protected
和 private
属性
<?php
class User{
protected $name = 'ctf' ;
private $isAdmin = true ;
}
$user = new User();
echo serialize($user);
?>
1、protected修饰的属性在序列化之后,修改为 \x00*\x00 属性名。 //图片上的方块换成16进制为\X00
2、private修饰的属性在序列化之后,修改为\x00 类名 \x00 属性名
七、序列化字符串中的 + 号
<?php
@error_reporting(1);
include 'flag.php';
class ctf{
public $flag ;
function __toString(){
if(isset($this->flag)){
$filename = "./{$flag}";
if(file_get_contents($filename)){
return file_get_contents($filename);
}
}
}
}
if(isset($_GET['data'])){ //判断是否传递参数
$data = $_GET['data']; //将参数赋值给data
preg_match('/[oc]:\d+:/i',$data,$matches); //进行正则匹配,将匹配的结果存储到matches中
if(count($matches)){ //长度是否大于0
die('no flag');
}else{
$c = unserialize($data); //反序列化传递进来的值(此时会调用魔术方法)
echo $c;
}
}else{
highlight_file('./2.php');
}
?>
绕过正则匹配,使用+号。 url编码为 %2b
八、魔术方法
__construct:构造方法
__destruct:析构方法:
__wakeup:执行unserialize() 时,会先调用这个函数
__toString:类被当作字符串时回应的方法
<?php
class User{
function __construct()
{
echo "__construct<br/>";
}
function __destruct()
{
echo "__construct<br/>";
}
function __wakeup()
{
echo "__wakeup<br/>";
}
function __toString()
{
echo "__construct<br/>";
return '';
}
}
$u = new User();
$s = serialize($u);
echo $s."<br/>";
$o = unserialize($s);
echo $o;
?>
九、PHP序列化漏洞案例
<?php
class Test{
public $cmd = "whoami";
function __wakeup(){
system($this->cmd);
}
}
$obj = unserialize($_GET['cmd']);
?>