freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

CVE-2021-26855 分析学习
FreeBuf_329663 2021-10-28 11:52:00 170281

今天“忙里偷闲”,一直在慢慢学习Exchange,把很早之前写了一半的东西补充好发出来 -0-

img

CVE-2021-26855,是一个SSRF漏洞,问题出在前后端解析Cookie时,可以成功访问后端

这个漏洞常与CVE-2021-27065一起使用,称为ProxyLogon

CVE-2021-26855分析

关于这个SSRF漏洞的触发请求大致如下

POST /ecp/3.jpg HTTP/1.1
Host: 10.0.19.20
Cookie: X-BEResource=EXCHANGE2016.pig.com:444/autodiscover/autodiscover.xml?a=~194206252

首先进入Microsoft.Exchange.FrontEndHttpProxy.dll中,命名空间为Microsoft.Exchange.HttpProxy内的ProxyModule类中的OnPostAuthorizeRequest()函数,接着此函数又会调用OnPostAuthorizeInternal()函数。

image-20211011214501352

OnPostAuthorizeInternal()函数里调用SelectHandlerForUnauthenticatedRequest()函数,此方法为未经验证的请求决定其处理Handler,当请求类型为Ecp时,并且BEResourceRequestHandler.CanHandle()函数为True时,将会创建BEResourceRequestHandler类的实例做为Handler。

image-20211011214650297

BEResourceRequestHandler类用于处理向后端进行资源型请求,直接分析CanHandle()函数:

internal static bool CanHandle(HttpRequest httpRequest)
{
	return !string.IsNullOrEmpty(BEResourceRequestHandler.GetBEResouceCookie(httpRequest)) && BEResourceRequestHandler.IsResourceRequest(httpRequest.Url.LocalPath);
}

发现需要满足两个条件可以使CanHandle返回True

  1. BEResourceRequestHandler.GetBEResouceCookie()

  2. BEResourceRequestHandler.IsResourceRequest()

首先看第一个:

private static string GetBEResouceCookie(HttpRequest **httpRequest**)
{
  string result = null;
  HttpCookie httpCookie = **httpRequest**.Cookies[Constants.BEResource];
  if (httpCookie != null)
  {
    result = httpCookie.Value;
  }
  return result;
}

//public static readonly string BEResource = "X-BEResource";

如果Cookie中存在的X-BEResource字段不为空的话,就满足。

第二个:

internal static bool IsResourceRequest(string **localPath**)
{
  return RequestPathParser.IsResourceRequest(**localPath**);
}

继续跟进RequestPathParser.IsResourceRequest()

image-20210816135145058

发现如果请求的文件是这些类型的话就满足,换句话说请求的文件为资源型就可以。

再回到OnPostAuthorizeInternal()函数,现在已经完成了Handler的分配,下一步由于BEResourceRequestHandler继承于ProxyRequestHandler因此执行((ProxyRequestHandler)httpHandler).Run(context)

image-20210816140437617

该Handler被设置为context.RemapHandlerInstance属性

然后就会调用Handler.BeginProcessRequest()函数对申请进行进一步解决,因为BEResourceRequestHandler 继承与 ProxyRequestHandler,所以最终调用了 ProxyRequestHandler.BeginProcessRequest() 函数

ProxyRequestHandler 类的作用应是将指向 FrontEnd 的Http 申请,转发给 BackEnd

BeginProcessRequest()函数内创建新线程调用ProxyRequestHandler.BeginCalculateTargetBackEnd()函数

其作用是根据 Cookie 中的 X-BEResource 字段来判断与生成指向 BackEnd 的目标url

image-20210818141338125

接着上述函数又调用了ProxyRequestHandler.InternalBeginCalculateTargetBackEnd()函数

image-20210818141555159

InternalBeginCalculateTargetBackEnd()又调用了ProxyRequestHandler.ResolveAnchorMailbox()

image-20211011220003213

ResolveAnchorMailbox()函数中,BackEndServer.FromString()函数会对X-BEResource字段内的Cookie做处理,以"~"号做为分隔,提取两段字符串分别赋值给FQDNVersion变量

image-20210816170450165image-20210816170619948

回到InternalBeginCalculateTargetBackEnd()中,又创建线程调用了OnCalculateTargetBackEndCompleted()

ThreadPool.QueueUserWorkItem(new WaitCallback(this.OnCalculateTargetBackEndCompleted), new TargetCalculationCallbackBeacon(this.AnchoredRoutingTarget));

接着调用InternalOnCalculateTargetBackEndCompleted()

image-20211011220457049

image-20211011220621415

最终到BeginProxyRequestOrRecalculate(),最后调用ProxyRequestHandler.BeginProxyRequest()

ThreadPool.QueueUserWorkItem(new WaitCallback(this.BeginProxyRequest));

其中调用了GetTargetBackEndServerUrl()

image-20211011220958841

GetTargetBackEndServerUrl()中获取了发送给后端的URL:

image-20211011221148480

1.设置HTTPS

2.Host即FQDN,xxxx.com

3.如果端口小于Server.E15MinVersion的值,端口会被设置为443

image-20211011221311037

获取完后端URL后最后赋值给uri就执行CreateServerRequest()

需要注意的是,中间代理在 BeginProxyRequest() 函数中 调用 CreateServerRequest() 来创建指向服务端的请求,而该函数会间接调用 GenerateKerberosAuthHeader() 函数来 创建Kerberos 认证头部。这也是中间代理能够访问BackEnd Server 的一个重要原因。

上述这个坑待填...

调用堆栈

Microsoft.Exchange.FrontEndHttpProxy.dll!

1.
ProxyModule.OnPostAuthorizeRequest()
	-->FbaModule.OnPostAuthorizeInternal()
		-->ProxyModule.SelectHandlerForUnauthenticatedRequest()
			-->BEResourceRequestHandler.BEResourceRequestHandler()

2.
BeginProcessRequest()
	-->BeginCalculateTargetBackEnd()
		-->InternalBeginCalculateTargetBackEnd()
				-->OnCalculateTargetBackEndCompleted()
					-->InternalOnCalculateTargetBackEndCompleted()
						-->BeginValidateBackendServerCacheOrProxyOrRecalculate()
							-->BeginProxyRequestOrRecalculate()
								-->BeginProxyRequest()
									-->CreateServerRequest()

以及更多好玩的工具、技巧欢迎关注微信公众号「黑客在思考」

# 代码审计 # Exchange # CVE-2021-26855
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 FreeBuf_329663 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
FreeBuf_329663 LV.3
这家伙太懒了,还未填写个人描述!
  • 4 文章数
  • 1 关注者
CVE-2021-31209 分析学习
2021-10-28
免杀权限维持之「计划任务」
2021-10-27
NimFileBinder:钓鱼攻击载荷捆绑利器
2021-09-28
文章目录