Exchange安全漏洞分析:ProxyOracle攻击链详解

news/2025/10/8 21:39:56/文章来源:https://www.cnblogs.com/qife122/p/19130152

Orange:MS Exchange新攻击面第二部分 - ProxyOracle!

作者:Orange Tsai(@orange_8361)

嗨,这是新MS Exchange攻击面的第二部分。由于本文涉及前一篇文章中的几个架构介绍和攻击面概念,您可以在以下位置找到第一篇:

MS Exchange新攻击面第一部分 - ProxyLogon!

这次,我们将介绍ProxyOracle。与ProxyLogon相比,ProxyOracle是一种采用不同方法的有趣漏洞利用。通过简单地引导用户访问恶意链接,ProxyOracle允许攻击者完全以明文格式恢复用户的密码。ProxyOracle包含两个漏洞:

CVE-2021-31195 - 反射型跨站脚本
CVE-2021-31196 - Exchange Cookie解析中的填充Oracle攻击

ProxyOracle的位置

那么ProxyOracle在哪里?基于我们之前介绍的CAS架构,CAS的前端首先将用户身份序列化为字符串,并将其放入X-CommonAccessToken的标头中。该标头将合并到客户端的HTTP请求中,随后发送到后端。一旦后端收到,它会将标头反序列化为前端中的原始用户身份。

我们现在知道了前端和后端如何同步用户身份。接下来要解释的是前端如何知道您的身份并处理您的凭据。Outlook Web Access (OWA)使用一个花哨的界面来处理整个登录机制,称为基于表单的身份验证 (FBA)。FBA是一个特殊的IIS模块,它继承自ProxyModule,并负责在进入代理逻辑之前执行凭据和Cookie之间的转换。

FBA机制

HTTP是一种无状态协议。为了保持您的登录状态,FBA将用户名和密码保存在Cookie中。每次您访问OWA时,Exchange将解析Cookie,检索凭据并尝试使用该凭据登录。如果登录成功,Exchange会将您的用户身份序列化为字符串,将其放入X-CommonAccessToken的标头中,并将其转发到后端。

HttpProxy\FbaModule.csprotected override void OnBeginRequestInternal(HttpApplication httpApplication) {httpApplication.Context.Items["AuthType"] = "FBA";if (!this.HandleFbaAuthFormPost(httpApplication)) {try {this.ParseCadataCookies(httpApplication);} catch (MissingSslCertificateException) {NameValueCollection nameValueCollection = new NameValueCollection();nameValueCollection.Add("CafeError", ErrorFE.FEErrorCodes.SSLCertificateProblem.ToString());throw new HttpException(302, AspNetHelper.GetCafeErrorPageRedirectUrl(httpApplication.Context, nameValueCollection));}}base.OnBeginRequestInternal(httpApplication);
}

所有Cookie都被加密,以确保即使攻击者能够劫持HTTP请求,他/她也无法以明文格式获取您的凭据。FBA利用5个特殊的Cookie来完成整个加解密过程:

  • cadata - 加密的用户名和密码
  • cadataTTL - 生存时间戳
  • cadataKey - 加密的KEY
  • cadataIV - 加密的IV
  • cadataSig - 防止篡改的签名

加密逻辑首先生成两个16字节的随机字符串作为当前会话的IV和KEY。用户名和密码随后使用Base64编码,通过AES算法加密,并在Cookie中发送回客户端。同时,IV和KEY也会发送给用户。为了防止客户端直接通过已知的IV和KEY解密凭据,Exchange在发送出去之前会再次使用其SSL证书私钥通过RSA算法加密IV和KEY!

以下是加密逻辑的伪代码:

@key = GetServerSSLCert().GetPrivateKey()
cadataSig = RSA(@key).Encrypt("Fba Rocks!")
cadataIV  = RSA(@key).Encrypt(GetRandomBytes(16))
cadataKey = RSA(@key).Encrypt(GetRandomBytes(16))@timestamp = GetCurrentTimestamp()
cadataTTL  = AES_CBC(cadataKey, cadataIV).Encrypt(@timestamp)@blob  = "Basic " + ToBase64String(UserName + ":" + Password)
cadata = AES_CBC(cadataKey, cadataIV).Encrypt(@blob)

Exchange采用CBC作为其填充模式。如果您熟悉密码学,您可能想知道这里的CBC模式是否容易受到填充Oracle攻击?没错!事实上,在2021年,像Exchange这样重要的软件中仍然存在填充Oracle攻击!

CVE-2021-31196 - 填充Oracle

当FBA出现问题时,Exchange会附加一个错误代码并将HTTP请求重定向回原始登录页面。那么Oracle在哪里?在Cookie解密中,Exchange使用异常来捕获填充错误,并且由于异常,程序立即返回,因此错误代码号为0,表示None

Location: /OWA/logon.aspx?url=…&reason=0

与填充错误相反,如果解密成功,Exchange将继续认证过程,并尝试使用损坏的用户名和密码登录。此时,结果必然是失败,错误代码号为2,表示InvalidCredentials

Location: /OWA/logon.aspx?url=…&reason=2

图表如下:
[此处应有图表]

有了这个差异,我们现在有了一个Oracle来识别解密过程是否成功。

HttpProxy\FbaModule.csprivate void ParseCadataCookies(HttpApplication httpApplication)
{HttpContext context = httpApplication.Context;HttpRequest request = context.Request;HttpResponse response = context.Response;string text = request.Cookies["cadata"].Value;    string text2 = request.Cookies["cadataKey"].Value;    string text3 = request.Cookies["cadataIV"].Value;    string text4 = request.Cookies["cadataSig"].Value;    string text5 = request.Cookies["cadataTTL"].Value;// ...RSACryptoServiceProvider rsacryptoServiceProvider = (x509Certificate.PrivateKey as RSACryptoServiceProvider);byte[] array = null;byte[] array2 = null;byte[] rgb2 = Convert.FromBase64String(text2);byte[] rgb3 = Convert.FromBase64String(text3);array = rsacryptoServiceProvider.Decrypt(rgb2, true);array2 = rsacryptoServiceProvider.Decrypt(rgb3, true);// ...using (AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider()) {aesCryptoServiceProvider.Key = array;aesCryptoServiceProvider.IV = array2;using (ICryptoTransform cryptoTransform2 = aesCryptoServiceProvider.CreateDecryptor()) {byte[] bytes2 = null;try {byte[] array5 = Convert.FromBase64String(text);bytes2 = cryptoTransform2.TransformFinalBlock(array5, 0, array5.Length);} catch (CryptographicException ex8) {if (ExTraceGlobals.VerboseTracer.IsTraceEnabled(1)) {ExTraceGlobals.VerboseTracer.TraceDebug<CryptographicException>((long)this.GetHashCode(), "[FbaModule::ParseCadataCookies] Received CryptographicException {0} transforming auth", ex8);}httpApplication.Response.AppendToLog("&CryptoError=PossibleSSLCertrolloverMismatch");return;} catch (FormatException ex9) {if (ExTraceGlobals.VerboseTracer.IsTraceEnabled(1)) {ExTraceGlobals.VerboseTracer.TraceDebug<FormatException>((long)this.GetHashCode(), "[FbaModule::ParseCadataCookies] Received FormatException {0} decoding caData auth", ex9);}httpApplication.Response.AppendToLog("&DecodeError=InvalidCaDataAuthCookie");return;}string @string = Encoding.Unicode.GetString(bytes2);request.Headers["Authorization"] = @string;}}
}

需要注意的是,由于IV是使用SSL证书私钥加密的,我们无法通过XOR恢复密文的第一个块。但这不会给我们带来任何问题,因为C#在内部将字符串处理为UTF-16,所以密文的前12个字节必须是B\x00a\x00s\x00i\x00c\x00 \x00。再加上应用了一次Base64编码,我们只会在用户名字段中丢失前1.5个字节。

(16−6×2) ÷ 2 × (3/4) = 1.5

漏洞利用

到目前为止,我们有一个填充Oracle,允许我们解密任何用户的Cookie。但是,我们如何获取客户端Cookie呢?在这里,我们发现了另一个漏洞将它们链接在一起。

XSS窃取客户端Cookie

我们在CAS前端(是的,又是CAS)中发现了一个XSS(CVE-2021-31195)来链接在一起,这个XSS的根本原因相对简单:Exchange在打印数据之前忘记清理数据,因此我们可以使用\从JSON格式中转义并注入任意JavaScript代码。

https://exchange/owa/auth/frowny.aspx
?app=people
&et=ServerError
&esrc=MasterPage
&te=\
&refurl=}}};alert(document.domain)//

但这里又出现了另一个问题:所有敏感Cookie都受HttpOnly标志保护,这使我们无法通过JavaScript访问Cookie。我们该怎么办?

绕过HttpOnly

由于我们可以在浏览器上执行任意JavaScript,为什么不直接插入我们在ProxyLogon中使用的SSRF Cookie呢?一旦我们添加了这个Cookie并将后端目标值分配为我们的恶意服务器,Exchange将成为受害者和我们之间的代理。然后,我们可以接管所有客户端的HTTP静态资源并获取受保护的HttpOnly Cookie!

通过将漏洞链接在一起,我们有了一个优雅的漏洞利用,只需向用户发送恶意链接即可窃取任何用户的Cookie。值得注意的是,这里的XSS仅帮助我们窃取Cookie,这意味着所有解密过程都不需要任何认证和用户交互。即使用户关闭浏览器,也不会影响我们的填充Oracle攻击!

以下是演示我们如何恢复受害者密码的演示视频:
[此处应有演示视频]
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)

公众号二维码

公众号二维码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/931970.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

北京建站公司哪家好都选万维科技电脑维护网站模板

题目链接 2865. 美丽塔 I - 力扣&#xff08;LeetCode&#xff09; 解题思路 根据题意可以知道&#xff0c;假设数组的长度为n,对于山状数组heights定义如下&#xff1a; 假设heights[i]为数组中的最大值&#xff0c;则i左边的值均小于等于heights[i]&#xff0c;i右边的值…

将word档案转为kindle可识别的azw3材料的方法

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

牛客 周赛111 20251008

牛客 周赛111 20251009 https://ac.nowcoder.com/acm/contest/117763 A: 题目大意: void solve(){int a, b, c;cin >> a >> b >> c;if (b != a + 1 || c != b + 1) cout << "No";…

本人于2025上半学期编码需要遵守的规范(参考腾讯内部编码规范)

编码的规范可以使代码更加具有易维护性以及编码安全性等等 程序的板式 缩进使用 4 个空格,禁止混用 Tab 键。 行宽限制 80 字符,长表达式在低优先级操作符处换行,操作符置于新行首。 大括号{}独占一行并与代码对齐,…

常州语言网站建设龙岩网站开发

hw_breakpoint 是由处理器提供专门断点寄存器来保存一个地址&#xff0c;是需要处理器支持的。处理器在执行过程中会不断去匹配&#xff0c;当匹配上后则会产生中断。 内核自带了硬件断点的样例linux-3.16\samples\hw_breakpoint\data_breakpoint.c static void sample_hbp_h…

tp做的网站封装成app定制网站建设公司有哪些

抖音短视频规则一、抖音的定义1、抖音是个去中心化的平台&#xff0c;根本没有什么权重&#xff0c;主要是看你账号的活跃度&#xff0c;互动关系&#xff0c;和行为习惯标签&#xff0c;抖音后台技术有去重机制&#xff0c;机器会自动判断你的视频重复率。重复率达到一定的比例…

图片素材网站免费大推荐网站正在备案

我想在recyclerview中显示一些JSON对象&#xff0c;并且希望它们在日期之后排序&#xff0c;我该如何实现&#xff1f;下面是下载从JSON URL的数据的方法&#xff1a;Android Studio Studio回收列表中的JSON对象public void downloadFromSkistar(){try{URL url new URL("…

泰安网站建设怎么样网上做兼职做网站

转载公众号 | 计算机科学编辑部征稿“知识图谱赋能的知识工程&#xff1a;理论、技术与系统”专题知识图谱&#xff08;Knowledge Graph&#xff09;方法与技术是人工智能在知识工程领域发展的最新前沿。知识图谱正在“感知智能”迈向“认知智能”的过程中扮演着重要角色。近年…

中山企业网站优化杭州手机网站建设

问题一&#xff1a; 什么是软件架构风格&#xff1f; 软件架构风格指特定软件系统组织方式的惯用模式。组织方式描述了系统的组成构件和这些构件的组织方式。惯用模式反映了众多系统所共有的结构和语义。 集成开发环境与用户的交互方式 &#xff08;实际上询问在交互方面&am…

10.8 CSP-JS 模拟赛 T5. xor

思路 考虑转化成组合数学 一个数最终会被异或多少次, 等价于在给出的网格图中, 有多少种路径走到这个位置 显然是一个 \(\displaystyle {a \choose b}\) 的组合数形式 又有 \[{a \choose b} \bmod 2 = [a \,\&\, b…

做网站实例中国农村建设网站首页

文章目录 概述方法 1: 使用 Spark SQL 语句方法 2: 使用 DataFrame API方法 3: 使用 Hadoop 文件系统 API方法 4: 使用 Delta Lake使用注意事项常见相关问题及处理结论 概述 Apache Spark 是一个强大的分布式数据处理引擎&#xff0c;支持多种数据处理模式。在处理大型数据集时…

防抖 解释

防抖: 核心就是当一个现象停止一段时间后, 才执行动作. 而不是每次都执行.主意timer的配置

山西做网站浦东教育网站官网

一、 DR模式的特点 直接路由&#xff1a; 在LVS_DR模式下&#xff0c;负载均衡器不修改数据包的IP地址&#xff0c;只修改目的MAC地址。这使得数据包可以直接路由到后端实际服务器上&#xff0c;而不需要返回到负载均衡器。 高性能&#xff1a; 由于数据包在传输过程中不需要回…

从零到一搭建:vue3+vite7+antfu+stylelint+githooks,全流程配置,附带源码,集成css变量使用,下载即用

@目录0 基础环境0.1 node版本0.2 包管理器0.3 vscode插件1 创建项目——vue官网方式1.1 创建命令1.2 初始化git2 语法检查:antfu组合eslint和prettier2.1 安装命令2.2 安装依赖2.3 在package.json中添加脚本2.4 修改e…

云梦网如何做网站广东万高建设网站

在程序操作过程中偶尔会出现如标题所示的错误&#xff0c;开始一直不知道怎么回事&#xff0c;后来仔细调试了下&#xff0c;发现是在浏览器可以点击“前进/后退”按钮时&#xff0c;同时按住shift鼠标滚轮滚动会出现这个Bug。 上网查找了下&#xff0c;有些浏览器Shift鼠标滚轮…

网站添加百度搜索哈尔滨优化seo外包公司

文章目录 概要一、Es二、kibana三、dcoker compose管理四、参考 概要 在工作过程中&#xff0c;经常需要测试环境搭建Es环境&#xff0c;本文基于Es V8.12.2来演示如何快速搭建单节点Es和kibana。 服务器默认已按装docker 一、Es 1&#xff1a;拉取镜像 docker pull elast…

晶台光耦在手机PD快充上的应用 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

bat批处理脚本文件-获取当前时间的几种方法

前言全局说明获取当前时间的几种方法一、说明 1.1 环境: Windows 7 旗舰版二、方法一 2.1 源码 @echo off@REM 获取当前时间 https://www.cnblogs.com/wutou/p/19130116 SET year=%date:~0,4% SET month=%date:~5,2% S…

二分图最大权完美匹配 KM算法

#include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; #define LL long long #define N 510 #define INF 1e12 int n,m; int match[N];//右点匹配了…

做一张简单的app网站多钱黔东南建设厅官方网站

对于初学者来说&#xff0c;java中的"\t"和空格总是让人迷惑&#xff0c;其实很简单&#xff0c;通过一个例子就能很快明白&#xff01;比如说打印九九乘法表&#xff01;先来看用空格的效果&#xff01;1 package cn.edu.nwpu.java;23 public class MultiplicationT…