您当前的位置: 首页 >  ar

Z3eyOnd

暂无认证

  • 2浏览

    0关注

    117博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

phar反序列化+两道CTF例题

Z3eyOnd 发布时间:2022-02-14 19:43:41 ,浏览量:2

文章目录
    • Phar反序列化
      • 什么是phar文件
      • 常见的流包装器
      • phar文件必要的结构组成
      • 受影响的文件操作函数
      • 漏洞利用条件
      • phar生成
      • 绕过方式
    • 例题
      • SWPUCTF 2018]SimplePHP
      • [NSSCTF]prize_p1
        • PHP对象
        • 绕过异常
        • phar://反序列化
        • 处理getflag()类
        • 签名修改
    • 参考文献

Phar反序列化

phar文件本质上是一种压缩文件,会以序列化的形式存储用户自定义的meta-data。当受影响的文件操作函数调用phar文件时,会自动反序列化meta-data内的内容。(漏洞利用点)

什么是phar文件

在软件中,PHAR(PHP归档)文件是一种打包格式,通过将许多PHP代码文件和其他资源(例如图像,样式表等)捆绑到一个归档文件中来实现应用程序和库的分发

php通过用户定义和内置的“流包装器”实现复杂的文件处理功能。内置包装器可用于文件系统函数,如(fopen(),copy(),file_exists()和filesize()。 phar://就是一种内置的流包装器

常见的流包装器
file:// — 访问本地文件系统,在用文件系统函数时默认就使用该包装器
http:// — 访问 HTTP(s) 网址
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流(I/O streams)
zlib:// — 压缩流
data:// — 数据(RFC 2397)
glob:// — 查找匹配的文件路径模式
phar:// — PHP 归档
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音频流
expect:// — 处理交互式的流
phar文件必要的结构组成

stub:phar文件的标志,必须以 xxx __HALT_COMPILER();?> 结尾,否则无法识别。xxx可以为自定义内容。

manifest:phar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的meta-data,这是漏洞利用最核心的地方。

content:被压缩文件的内容

signature (可空):签名,放在末尾。

受影响的文件操作函数

img

漏洞利用条件
  1. phar可以上传到服务器端(存在文件上传)

  2. 要有可用的魔术方法作为“跳板”。

  3. 文件操作函数的参数可控,且:/phar等特殊字符没有被过滤

phar生成

得到phar文件,修改后缀为jpg,上传。

得到文件名的两种方法

方法1:

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 'alert("上传成功!");';
}

文件名是$filename = md5($_FILES["file"]["name"] . $_SERVER["REMOTE_ADDR"]) . ".jpg";

路径是url+/upload/文件名

(但是这种方法感觉不对,得不出flag,个人做的时候出现问题了)

方法2:

直接访问,URL+/upload/可以查看文件名

最后直接

file=phar://upload/文件名,就可以得到flag
[NSSCTF]prize_p1

考点:

  1. phar反序列化
  2. 绕过Error异常
  3. phar签名修改
  4. GC进制(垃圾回收系统)

wp:

打开,直接审计代码


config == 'w') {
            $data = $_POST[0];
            if (preg_match('/get|flag|post|php|filter|base64|rot13|read|data/i', $data)) {
                die("我知道你想干吗,我的建议是不要那样做。");
            }
            file_put_contents("./tmp/a.txt", $data);
        } else if ($this->config == 'r') {
            $data = $_POST[0];
            if (preg_match('/get|flag|post|php|filter|base64|rot13|read|data/i', $data)) {
                die("我知道你想干吗,我的建议是不要那样做。");
            }
            echo file_get_contents($data);
        }
    }
}
if (preg_match('/get|flag|post|php|filter|base64|rot13|read|data/i', $_GET[0])) {
    die("我知道你想干吗,我的建议是不要那样做。");
}
unserialize($_GET[0]);
throw new Error("那么就从这里开始起航吧");

分析代码,其中getflag__destruct方法触发即可得到flag,A__destruct方法触发即可写/tmp/a.txt或者任意文件读。

PHP对象

__destruct是PHP对象的一个魔术方法,称为析构函数,顾名思义这是当该对象被销毁的时候自动执行的一个函数。其中以下情况会触发__destruct

  1. 主动调用unset($obj)
  2. 主动调用$obj = NULL
  3. 程序自动结束

除此之外,PHP还拥有垃圾回收Garbage collection即我们常说的GC机制。

PHP中GC使用引用计数和回收周期自动管理内存对象,那么这时候当我们的对象变成了“垃圾”,就会被GC机制自动回收掉,回收过程中,就会调用函数的__destruct

刚才我们提到了引用计数,其实当一个对象没有任何引用的时候,则会被视为“垃圾”,即

$a = new show();

这是一个show对象,被a变量应用,所以它不是“垃圾”。如果是

new show();

$a = new show();$a = 2;

上面都是对象没有被饮用或开始有引用之后失去了引用的情况,我们可以考虑下列实例代码。

            
关注
打赏
1651657201
查看更多评论
0.0724s