[网鼎杯 2020 半决赛]faka

[网鼎杯 2020 半决赛]faka

关键代码

    public function upload()
    {
        $file = $this->request->file('file');
        $ext = strtolower(pathinfo($file->getInfo('name'), 4));
        $md5 = str_split($this->request->post('md5'), 16);
        $filename = join('/', $md5) . ".{$ext}";
        if (strtolower($ext) == 'php' || !in_array($ext, explode(',', strtolower(sysconf('storage_local_exts'))))) {
            return json(['code' => 'ERROR', 'msg' => '文件上传类型受限']);
        }
        // 文件上传Token验证
        if ($this->request->post('token') !== md5($filename . session_id())) {
            return json(['code' => 'ERROR', 'msg' => '文件上传验证失败']);
        }
        // 文件上传处理
        if (($info = $file->move('static' . DS . 'upload' . DS . $md5[0], $md5[1], true))) {
            if (($site_url = FileService::getFileUrl($filename, 'local'))) {
                return json(['data' => ['site_url' => $site_url], 'code' => 'SUCCESS', 'msg' => '文件上传成功']);
            }
        }
        return json(['code' => 'ERROR', 'msg' => '文件上传失败']);
    }

    /**
     * 文件状态检查
     */
    public function upstate()
    {
        $post = $this->request->post();
        $filename = join('/', str_split($post['md5'], 16)) . '.' . pathinfo($post['filename'], 4);
        // 检查文件是否已上传
        if (($site_url = FileService::getFileUrl($filename))) {
            $this->result(['site_url' => $site_url], 'IS_FOUND');
        }
        // 需要上传文件,生成上传配置参数
        $config = ['uptype' => $post['uptype'], 'file_url' => $filename];
        switch (strtolower($post['uptype'])) {
            case 'qiniu':
                $config['server'] = FileService::getUploadQiniuUrl(true);
                $config['token'] = $this->_getQiniuToken($filename);
                break;
            case 'local':
                $config['server'] = FileService::getUploadLocalUrl();
                $config['token'] = md5($filename . session_id());
                break;
            case 'oss':
                $time = time() + 3600;
                $policyText = [
                    'expiration' => date('Y-m-d', $time) . 'T' . date('H:i:s', $time) . '.000Z',
                    'conditions' => [['content-length-range', 0, 1048576000]],
                ];
                $config['policy'] = base64_encode(json_encode($policyText));
                $config['server'] = FileService::getUploadOssUrl();
                $config['site_url'] = FileService::getBaseUriOss() . $filename;
                $config['signature'] = base64_encode(hash_hmac('sha1', $config['policy'], sysconf('storage_oss_secret'), true));
                $config['OSSAccessKeyId'] = sysconf('storage_oss_keyid');
        }
        $this->result($config, 'NOT_FOUND');
    }

解题步骤:

下载源码,在sql文件可以找到admin密码的md5值。去在线网站爆破即可得到密码admincccbbb123。然后代码审计。可以看上面的关键代码,来自plugs.php,用来进行文件上传。根据抓包,我们知道先执行upstate,再执行upload。可以看到,文件名可控,只要控制传入的md5即可。进入local的case里面,返回了token。然后到upload,这里的文件名也是可控的,同样控制md5即可。所以第一个if可以上传图片后缀的马进行绕过,第二个验证的话,这个filename和前一个包的filename要相同,即可绕过token验证。而upstate里面的filename和我们上传的md5有关,所以控制两个包的md5相同即可。进入到最后一个if,move函数我没进行本地调试,看了下,就是文件名遇到.直接返回,就是如果传入1.php.png的文件名,直接返回1.php。所以就可以直接上传木马了,直接开搞:



虽然会说文件上传失败,但是先执行的move函数,其实是已经成功上传了。上传的目录可以用一张正常的图片进行测试,然后文件名是以.php结尾的
然后直接蚁剑连接就可以拿到flag。
还有另一种文件下载的方法,直接任意文件读取即可,由于flag在/flag.txt里面,所以读就行。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇