php Opcache插件进行RCE

php opcache缓存进行RCE

前言

关于opcache我是在去年三四月份从B站上的nepnep战队的一个分享会上看到的,当时觉得很难,就记录了一下操作,记住了这个词,然后就没出现过了

再次见到就是Boogipop大佬的文章,不过也没看,一直到现在复现DASCTF X 0psu3的一个题目用到了,就来看一遍,相当于是重新学一遍了

复现一遍Boogipop大佬文章,我这里详细给出了环境搭建的命令(当然若是大佬可以直接看原文)

环境搭建

docker pull php:7.1-apache
//docker pull php:8.2-apache

docker run -d -p 9000:80 --name opcache7 php:7.1-apache

apt-get update
apt install vim
vim phpinfo.php    //写phpinfo

//安装opcache插件
docker-php-ext-configure opcache --enable-opcache && docker-php-ext-install opcache

vim /usr/local/etc/php/php.ini-production

//找到opcache部分添加下面三行句子
[opcache]
opcache.enable=1
opcache.file_cache="/tmp"
opcache.file_cache_only=1

//docker的php是没有php.ini配置文件的,修改了php.ini-production后复制并重命名为php.ini即可
cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini


//修改了php.ini要重启服务
service apache2 reload

image-20240117181811688

看到这一行就说明配置成功了

看一下docker中的文件

image-20240117145457621

当Opcache第一次缓存文件时, /tmp/system_id/var/www/html/phpinfo.php.bin

php7 Opcache

首先说一下Opcache rce的原理,Opache是php中一个生成缓存文件的拓展,当我们访问一个php文件时,他会产生一个缓存文件,下次访问该php文件时,就是直接根据缓存文件回显页面了。

那很明显伪造文件替换即可

image-20240117145457621

缓存文件夹是1116d566fdc53f79abce6c01e3a0308d这个是今天的重点,我们怎么去算这个system_id呢?

在之前的笔记中,我记录它为文件上传 LFI + phpinfo,是可以根据phpinfo的信息计算出来system_id

在PHP环境下已经有前人给出我们计算脚本
https://github.com/GoSecure/php7-opcache-override

php7.3版本好像太高算不对,于是Boogipop大佬降低了版本为7.1

image-20240117145519755

我们怎么利用呢?当我们存在任意文件写入或者覆盖时,我们可以通过覆盖.php.bin文件达到RCE的目的

我们把缓存文件下载下来分析一下

image-20240117145739241

可以看到最开头是OPACHE+systemid,因此假如我们获取到了SYSTEMID,我们就可以伪造一份缓存文件了,但是还需要注意一点

image-20240117183119719

我们这里的opcache拓展开启了timestamp,也就是时间戳验证,那么假如我们创建的文件时间戳不对的话,我们也无法覆盖成功的QWQ,那么就需要题目有一个获取时间的地方,假如可以下载任意文件或者直接获取时间戳,那么我们可以用010editor直接修改。

干到这里时我实在是受不了原来那版010了,又耗费精力找新的破解版,耗了不少时间,服了

image-20240117183402563

0040h开始,即第五行开始的8个字节(图中蓝色部分)即是时间戳

这里我们再启动一个容器就行,与原来一样的配置(只是在phpinfo.php文件中写入一句话木马),这样就省下计算system_id这一步了

同样会生成一个phpinfo.php.bin文件,弄下来修改为前一个的system_id(已省略)和时间戳

image-20240117162146324

然后把这个修改过的文件替换掉环境中的文件即可

我是把原来的直接删掉,然后通过base64写入文件

image-20240117175735733

然后访问phpinfo.php就会变得空白,说明一句话木马写入成功

image-20240117175701476

这样就成功getshell了,需要注意一下生成恶意bin文件的php版本需要大致吻合,不能差太多。

php8 opcache

在PHP8之后,opcache生成system_id的方法有些许改变,所以之前的脚本是跑不出来了

image-20240117180130700

image-20240117180147678

可以看到算出的system_id不同

image-20240117184508737

image-20240117184527792

Boogipop大佬并没有说出规律是什么

经过我的尝试,规律很简单,就是修改API前的版本号

我这里是8.2.14

image-20240117184659142

再加上框框中的内容

image-20240117185550804

所以得出计算代码

<?php
var_dump(md5("8.2.14API420220829,NTSBIN_4888(size_t)8\002"));

image-20240117180524000

image-20240117180147678

后面的步骤是一样的,就不试了

春秋杯2023-php_again

给出Boogipop大佬文章中的例题,

考点就是opache8的缓存文件利用:

<?php

$action = $_GET['action'];
if (empty($action)) {
    highlight_file(__FILE__);
    die();
}
switch ($action) {
    case 0_0:
        phpinfo();
        break;
    case 0o0_111:
        exec('zip -r /tmp/www.zip *');
        readfile('/tmp/www.zip');
        break;
    case 0b0_111:
        var_dump(scandir('/var/www/html/'));
        break;
    case 0x0_555:
        file_put_contents('/tmp/tmp.zip',base64_decode($_POST['data']));
        break;
    case 777_777:
        exec('cd /tmp && unzip -o tmp.zip');
        break;
}

首先是一个软链接读文件,然后是unzip解压覆盖文件,满足了所有条件后就可以按照上述步骤进行处理,getshell了

这感觉好难啊

DASCTF X 0psu3 十一月挑战赛 single_php

就给个代码,看文章复现吧

DASCTF X 0psu3 Web Writeup - Boogiepop Doesn’t Laugh (boogipop.com)

好像都是解压覆盖这种

<?php

error_reporting(0);

highlight_file(__FILE__);
$allowed_ip = "127.0.0.1";
if ($_SERVER['REMOTE_ADDR'] !== $allowed_ip) {
    die("S* has the kanojo but you don't");
}

 $finfo = finfo_open(FILEINFO_MIME_TYPE);
 if (finfo_file($finfo, $_FILES["file"]["tmp_name"]) === 'application/x-tar'){
 exec('cd /tmp && tar -xvf ' . $_FILES["file"]["tmp_name"]);
 }
<?php
error_reporting(0);
class siroha{
public $koi;

public function __destruct(){
$this->koi['zhanjiangdiyishenqing']();
}
}
$kanozyo = $_GET['LuckyE'](__FILE__);
var_dump($kanozyo);
$suki = unserialize($_POST['suki']);

reference

PHP8 OPCACHE缓存文件导致RCE - Boogiepop Doesn’t Laugh (boogipop.com)


php Opcache插件进行RCE
https://zer0peach.github.io/2024/01/17/php-Opcache插件进行RCE/
作者
Zer0peach
发布于
2024年1月17日
许可协议