网络安全之反序列化漏洞-爱代码爱编程
一·PHP类与对象
类Class
一个共享相同结构和行为的对象的集合
<?php
class MyClass{
var $var1;
var $var2 ="constant string";
function myfunc ($arg1,$arg2){
[......]
}
[....]
}
?>
类的实例
$baidu = new Site;
$kitty = new Cat;
$benz = new Car;
二.Magic函数
函数作用
函数 | 作用 |
__construct | 当一个对象创建时被调用 |
__destruct | 当一个对象销毁时被调用 |
__toString | 当一个对象被当做一个字符串使用 |
__sleep | 在对象被反序列化之前运行 |
__wakeup | 在对象被反序列化之后被调用 |
__serialize | 对对象调用serialize()方法,PHP 7.4.0起 |
__unserialize | 对对象调用unserialize()方法,PHP 7.4.0起 |
函数 | 作用 |
__call() | 在对象上下文调用不可访问的方法时触发 |
__callStatic | 在静态上下文中调用不可访问的方法时触发 |
__get() | 用于从不可访问的属性读取数据 |
__set() | 用于将数据写入不可访问的属性 |
__isset() | 在不可访问的属性上调用isset()或者empty()触发 |
__unset() | 在不可访问的属性上使用unset()时触发 |
__invoke() | 当脚步尝试将对象调为函数时触发 |
案例
<?php
/**
*Class MyClss
*Magic函数演示
*/
calss Myclass{
public $var = "hello word\n";
public function echoString(){
echo $this->var;
}
//对象创建的时候调用
public function __construct(){
echo "__construct\n";
}
//对象销毁的时候调用
public function __destruct(){
echo "__destruct\n";
}
//对象被当成字符串的时候调用
public function __toString(){
return "__toString\n";
}
}
//创建一个新的对象,__construct被调用
$obj = new MyClass();
//调用该类的方法
$obj->echoString();
//以字符形式输出,__toString方法被调用
echo $obj;
//php脚本要结束时,__destruct会被调用
?>
三.PHP序列化与反序列化
序列化与反序列化
<?php
/**
*Class SerialType
*不同类型的序列化演示
*/
class SerialType{
public $data;
private $pass;
const CONTRY = 'CHINA';
public function __construct($data,$pass)
{
$this->data = $data;
$this->pass = $pass;
}
}
$number = 32;
$str = 'hello';
$bool = true;
$NULL = NULL;
$arr = array('a' => 1,'bbbb' => 9);
$obj = new SerialType(data: 'somestr',pass: 'true');
var_dump(serialize($number));
var_dump(serialize($str));
var_dump(serialize($bool));
var_dump(serialize($arr));
var_dump(serialize($obj));
var_dump(value:CONTRY);
?>
其他序列化的格式
json字符串 json_encode
<?php
/**
*Class Jsonclass
*JSON和XML的序列化演示
*/
class JsonClass{
public $word = "hello word";
public $prop = array('name' => 'darkroom', 'age' => 31, 'motto' => 'Apple keep doctor');
}
$obj = new JsonClass();
//转化对象为JSON字符串
$s = json_encode($obj);
//转换对象为XML
$x = wddx_serialize_value($obj );
echo $s;
echo "\n";
echo $x;
?>
xml字符串 wddx_serialize_value
二进制格式
字节数组
序列化中不需要序列化的字段
<?php
class User{
const SITE = 'darkroom';
public $username;
public $nickname;
private $password;
public function __construct($username, $nickname, $password){
$this->username = $username;
$this->nickname = $nickname;
$this->password = $password;
}
//重载序列化调用非法
public function __sleep(){
//返回需要序列化的变量名,过滤掉password变量
return array('username', 'nickname');
}
}
$user = new User(username:'hackerdarkroom', nickname:'darkroom', password:'123456');
var_dump(serialize($user));
?>
反序列化演示
<?php
/**
*Class UnSerializeTest
*反序列化的演示
*/
class UnSerializeTest{
public $var = "hello darkroom\n";
public function echoString(){
echo $this->var;
}
public function __consturct(){
echo "__consturct\n";
}
public function __destruct(){
echo "__destruct\n";
}
public function __serialize(){
echo "__serialize\n";
}
public function __wakup(){
echo "__wakup\n";
}
}
//创建一个新的类
//$obj1 = new UnSerializeTest();
//调用该类的
//$obj1->echoString();
//输出序列化以后的字符
//echo "序列化以后的结果:\n";
//echo serialize($obj1);
//反序列化
//"0"表示对象,“15”表示对象长度为15,"UnSerializeTest"为对象名,“1”表示有一个参数
//“{}”里面是参数的key和value,"s"表示string对象,“11”表示长度,“var”则为key
//!注意,var内容和长度可以修改
//$obj2 = unserialize('0:15"UnSerializeTest":1:{s:3:"var";s:12:"hello darkroom";}');
//调用对象的方法
echo "反序列化以后执行的结果: \n";
var_dump($obj2);
$obj2->echoString();
?>
注意:
1.如果传递的字符串不可以序列化,则返回FALSE
2。如果对象没有预定义,反序列化得到的对象是_PHP_Incomplete_Class
作用
1.传输对象
2.用作缓存(Cookie,Session)
反序列化与Magic函数
__wakup
__unserialize
如果类中同时定义了__unserialize()和__wakup()两个魔法函数,则只有__unserialize()方法会生效,__wakup()方法会被忽略