做婚恋网站投入多少钱,网站建设div设置圆角,免费的seo,wordpress安装水煮鱼目录
php序列化和反序列化简介
序列化
反序列化
类中定义的属性
序列化实例
反序列化实例
反序列化漏洞
序列化返回的字符串格式
魔术方法和反序列化利用
绕过wakeup
靶场实战
修复方法 php序列化和反序列化简介
序列化
将对象状态转换为可保持或可传输的格式的…目录
php序列化和反序列化简介
序列化
反序列化
类中定义的属性
序列化实例
反序列化实例
反序列化漏洞
序列化返回的字符串格式
魔术方法和反序列化利用
绕过wakeup
靶场实战
修复方法 php序列化和反序列化简介
序列化
将对象状态转换为可保持或可传输的格式的过程。
简单的理解将 PHP 中 对象、类、数组、变量、匿名函数等转化为字符串方便保存到数据库或者文件中。
反序列化
反序列化就是再将这个状态信息拿出来使用。将字符串重新再转化为对象或者其他的状态信息
简单来说将这个状态信息转换成原来的对象或者其他原来的格式。
PHP序列化把对象转化为二进制的字符串使用serialize()函数 PHP反序列化把对象转化的二进制字符串再转化为对象使用unserialize()函数
类中定义的属性
public属性被序列化的时候属性值会变成 属性名
protected属性被序列化的时候属性值会变成 \x00*\x00属性名
private属性被序列化的时候属性值会变成 \x00类名\x00属性名
其中\x00表示空字符但是还是占用一个字符位置空格
序列化实例
序列化只序列属性不序列方法
当在 php 中创建了一个对象后可以通过 serialize() 把这个对象转变成一个字符串保存对象的值方便之后的传递与使用。
?php
// 定义一个简单的类
class Person {public $nameAlice;public $age25;
}
// 创建一个Person对象
$person new Person();
// 序列化对象
$serialized_object serialize($person);
// 输出序列化后的字符串
echo $serialized_object
?
输出结果
O:6:Person:2:{s:4:name;s:5:Alice;s:3:age;s:2:25;}
反序列化实例
与 serialize() 对应的 unserialize() 可以从已存储的表示中创建 PHP 的值可以从序列化后的结果中恢复对象 object
?php
// 定义一个简单的类
class Person {public $name;public $age;
}
// 定义要反序列化字符串
$object O:6:Person:2:{s:4:name;s:5:Alice;s:3:age;s:2:25;};
// 反序列化字符串为对象
$unserialized_object unserialize($object);
// 输出反序列化后的对象信息
echo Name: . $unserialized_object-name . \n;
echo Age: . $unserialized_object-age . \n;
?
输出结果
Name: Alice Age: 25
反序列化漏洞
本质上 serialize() 和 unserialize() 在 PHP 内部实现上是没有漏洞的漏洞的主要产生是由于应用程序在处理对象、魔术函数以及序列化相关问题的时候导致的。
当传给 unserialize() 的参数可控时那么用户就可以注入精心构造的payload 。当进行反序列化的时候就有可能会触发对象中的一些魔术方法造成意想不到的危害。
序列化返回的字符串格式
O:length:class name:n:{field name 1field value 1...field name nfield value n} O:表示序列化的是对象 length:表示序列化的类名称长度 class name表示序列化的类的名称 n:表示被序列化的对象的属性个数 field name 1属性名 field value 1属性值 $number 34;
$str uusama;
$bool true;
$null NULL;
$arr array(a 1, b 2);
$cc new CC(uu, true);
var_dump(serialize($number));
var_dump(serialize($str));
var_dump(serialize($bool));
var_dump(serialize($null));
var_dump(serialize($arr));
var_dump(serialize($cc));
输出结果
string(5) i:34;
string(13) s:6:uusama;
string(4) b:1;
string(2) N;
string(30) a:2:{s:1:a;i:1;s:1:b;i:2;}
string(52) O:2:CC:2:{s:4:data;s:2:uu;s:8: CC pass;b:1;}
序列化对于不同类型得到的字符串格式为 String : s:size:value; Integer : i:value; Boolean : b:value;(保存1或0) Null : N; Array : a:size: Object : O:strlen(object name):object name:object size:
魔术方法和反序列化利用
php 中有一类特殊的方法叫“ Magic function” 魔术方法 这里我们着重关注一下几个
__construct()当一个对象创建时被调用,但在 unserialize()时是不会自动调用的。构造函数
__destruct()当一个对象销毁时被调用
__toString()当一个对象被当作一个字符串使用
__sleep() 在对象在被序列化之前运行
__wakeup将在序列化之后立即被调用
从序列化到反序列化这几个函数的执行过程是
__construct() -__sleep() - __wakeup() - __toString() - __destruct()
绕过wakeup
CVE-2016-7124当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行(让n大于原有的对象属性个数)
官方给出的影响版本 PHP5 5.6.25 PHP7 7.0.10
靶场实战 payload:
O:1:S:1:{s:4:test;s:29:scriptalert(xss)/script;} 分析代码 __construct()在序列化的时候会自动调用反序列化时不会自动调用。
这里着重分析一下if语句
if(!$unser unserialize($s)){$html.p大兄弟,来点劲爆点儿的!/p;
}else{$html.p{$unser-test}/p;
}
它的作用如下 unserialize($s): 这个函数尝试将一个序列化的字符串 ($s) 转换回PHP的值比如数组、对象等。如果 $s 不是一个序列化的字符串或在反序列化过程中出现错误unserialize() 函数会返回 false。 $unser: 这部分使用了错误控制运算符 ()。它会抑制 unserialize() 可能抛出的任何错误。如果 unserialize() 失败返回 false那么 $unser 也会是 false。 若反序列化失败或者说$s不是一个序列化后的值unserialize($s)返回false给unser,用来一直错误输出!false为真执行语句$html.p大兄弟,来点劲爆点儿的!/p;若反序列化成功unserialize($s)返回true给unser!true为假执行else后面的语句$html.p{$unser-test}/p;
因为是直接嵌入html页面中没有经过过滤所以可以输入前端代码造成xss攻击。
修复方法 验证输入: 在接收用户输入并执行反序列化之前验证输入的合法性和预期格式。可以使用正则表达式或其他方法检查输入是否符合预期的序列化字符串格式。 过滤输出: 在输出反序列化后的对象属性时确保适当地转义和过滤用户提供的内容以防止恶意代码执行。可以使用 PHP 的 htmlspecialchars() 函数来转义输出确保任何 HTML 标签都被安全地显示。 限制反序列化的对象类型: 如果可能的话尽量避免反序列化不受信任的数据尤其是复杂的对象结构。可以使用简单的数据结构或者明确指定允许的类名。