目录
一·PHP类与对象
类Class
一个共享相同结构和行为的对象的集合
类的实例
二.Magic函数
函数作用
案例
三.PHP序列化与反序列化
序列化与反序列化
其他序列化的格式
序列化中不需要序列化的字段
反序列化演示
注意:
作用
反序列化与Magic函数
四。反序列化的发生
场景演示
反序列化漏洞发生的条件
常见的利用函数
$baidu = new Site;
$kitty = new Cat;
$benz = new Car;
函数 | 作用 |
__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() | 当脚步尝试将对象调为函数时触发 |
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会被调用
?>
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
'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
二进制格式
字节数组
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));
?>
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)
__wakup
__unserialize
如果类中同时定义了__unserialize()和__wakup()两个魔法函数,则只有__unserialize()方法会生效,__wakup()方法会被忽略
';
file_put_contents($this->filename,$text,flags:FILE_APPEND);
}
//destrcuctor 删除日志文件
public function __destruct(){
echo '__destruct deletes'.$this->filename.'file.
';
unlink(filename:dirname(path:__FILE__).'/'.$this->filename);
}
}
?>
name.'is'.$this->age.'year old.
';
}
}
//通过GET请求参数传入字符
//此处可以反序列化任意对象
$usr = unserialize($_GET['param']);
?>
filename = 'index.php';
//序列化
echo serialize($obj);
?>
1.unserialize函数的参数可控,比如通过GET请求传参(漏洞触发点)
2。脚本中定义了有Magic方法,方法里面有向PHP文件做读写数据或者执行命令的操作,比如__destruct(),unlink()
3.读写的内容需要有对象中的成员变量的值,比如filename
类别 | 函数 |
命令执行 | exec() passthru() popen() system() ........ |
文件操作 | file_put_contents() file_get_contents() unlink() ........ |