Akamai 收购 Fermyon,将 WebAssembly 函数即服务 (FaaS) 与其全球分布式平台相结合。 阅读新闻
Dark background with blue code overlay
博客
RSS

Akamai EAA 冒充漏洞 - 深度剖析

Akamai Wave Blue

寫於

Akamai

June 01, 2021

Akamai Wave Blue

寫於

Akamai

在这篇文章中,我们将介绍 CVE-2021-28091 的技术细节,该漏洞影响了 Akamai 的 Enterprise Application Access (EAA) 平台。文中介绍了我们对该漏洞执行的调查、补救和披露过程。有关该漏洞的概述、对 Akamai 的影响、对 EAA 客户的影响以及需要采取的行动,请参见我们的伴读报告

概述

在本节中,我们将向您介绍该漏洞的历史以及对该漏洞的剖析。如果需要,读者可以暂时跳过本节,直接进入“需要采取的行动”一节,并在他们需要进行任何评估或未来进行审查时再使用此概述作为参考。

在 Akamai 于 2016 年通过收购 Soha Systems 获得 EAA 技术之前,该平台引入了一项关键功能,使得该平台的客户可以根据第三方身份提供商提供的身份信息做出访问控制和身份验证决策。EAA 平台为第三方身份集成提供了多种方法。在本报告中提到了一种值得注意的方法,即支持安全断言标记语言 (SAML) v2.0 身份验证协议。

SAML 是一个广泛使用的开放标准。SAML 让身份提供商 (IdP) 通过加密签名和返回来向服务提供商 (SP) 做出断言,在此过程中,客户端在规定的时间内向 SP 呈现来自 IdP 的断言对象。(有关更多信息,请参见下文的“背景”一节。)

向 EAA 添加第三方 IdP 支持时,开发人员选择了开源库 Lasso 以在平台内实施 SAML 支持。根据 Akamai 对代码(其中,Lasso 作为 SP 会验证提供给它的 SAML 响应)的评估,我们认为,在初始集成时,实施第三方 IdP 功能的开发人员根据库附带的测试案例,以合理的方式进行了实施。进一步的调查表明,用于测试 Akamai 实施的功能的测试套件不够严格,无法识别这个冒充漏洞或身份验证过程中的类似弱点。作为回应,我们扩展了适用于新版产品的测试套件,在其中包括了所有组合(有效和无效的签名响应和/或断言,以及未签名的断言和响应),从而解决了这一不足之处。这些新测试是未来标准 QA 流程的一部分。

在本报告的以下章节,我们详细说明了构成整个漏洞的各项弱点和促成因素。我们之所以进行这种详细讲解,目的是为了帮助其他人了解 Akamai 采取的措施,使他们能够在自己的环境中避免类似的情况。

系统测试和评估

单元测试、集成测试和回归测试是任何软件开发生命周期 (SDLC) 中的重要环节。虽然实施的子组件具备所有这些与之相关的测试方法,但我们已经清楚地了解,这些测试不够严格。此外,此事件还表明存在疏忽,也就是说,我们将一些第三方库纳入到了项目中,因为我们错误地认为,依赖项的 SDLC 本身足够严格,并且可以发现特定于域的漏洞,比如类似的库中的漏洞。

每个组件及其每个依赖项必须具备严格的 SDLC,但是,组件开发和质量保证 (QA) 计划中的测试往往不够充分。为了对这种测试进行补充,可以采用对抗性评估,比如渗透测试或第三方代码审查。就 EAA 而言,在该产品的生命周期中,已经对 EAA 平台进行了多次外部安全和漏洞评估,通常是由客户执行。尽管如此,引发本次回应的报告是客户首次向 Akamai 报告这一漏洞。Akamai 已经对 EAA 平台的其他部分及其客户端应用程序进行了针对性评估,但该特定组件尚未接受过这种程度的审查。

避免过早披露

在此事件响应过程的早期,Akamai 开始编写了一份概括性的客户通知,以指导客户开始执行配套文章中的“需要采取的行动”一节中建议的调查。在对该文档进行发布前审查时,没有获知该漏洞的 Akamai 员工收到了一份面向客户的消息副本。在提供此消息后的一小时内,我们的审查人员确定了受影响的协议 (SAML)、受影响的软件包 (Lasso),并根据 Lasso 项目维护者最近的一些活动,猜测出了漏洞的内容。这一发现使我们立即暂停了部分通知计划,以遵守负责任的披露原则。 

在与我们的审查人员进一步交谈后,事件团队得以了解他们发现这些信息的过程。审查人员报告了一个关键发现,即 IdP 在错误情况发生时返回的错误消息。在该漏洞的修复方案发布之前,当 SAML 失败时,系统会返回一个错误页面,该页面会向最终用户显示 Lasso 错误,如下图所示。转发错误(特别是对于身份验证这样的关键安全流程)不符合最佳做法的理念,这就是为什么从这个版本开始,最终用户将看不到此错误。 

漏洞

在 Akamai 工程师发现 Lasso 库的弱点后,我们对 Lasso 代码库进行了针对性审查。在向该库的维护者提供报告之前,工程团队能够在不使用我们的应用程序专属代码的情况下再现该漏洞。要获取维护者应用的补丁,请访问此处

在与 Lasso 维护者协调之后,Akamai 保留了 CVE ID CVE-2021-28091。公布的 CVE ID 的相关 CVSS 得分是 8.2。同样在与 Lasso 维护者协调下,Akamai 向 CERT/CC 报告了此问题,后者负责协调披露过程。

背景

为了充分了解此问题,需要有效理解 SAML 身份验证过程。为了便于理解此主题,请参见《The Beer Drinker's Guide to SAML》 ,发布者为 DUO。

一切的核心在于攻击者可以利用的弱点。为了进一步详细说明此问题,我们首先介绍一下在库的修补版本中如何解读 SAML 响应。然后讨论在哪些情况下可以利用此弱点来冒充其他用户。

在用户向 SAML IdP 进行身份验证后,IdP 通过 SP 和 IdP 管理员预先协商的方法将 SAML 响应返回给 SP。 通常使用客户端作为中介来实现此目的。 SP 通过此 SAML 响应来验证客户端是否获得授权。 

SAML 断言是一个 XML 文档,它大致采用以下形式:

  <samlp:Response>

 <saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer>

 <saml:Assertion>

   <saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer>

   <ds:Signature>

    ... Assertion Signature ...

   </ds:Signature>

   <saml:AttributeStatement>

     <saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">

       <saml:AttributeValue xsi:type="xs:string">test</saml:AttributeValue>

     </saml:Attribute>

     <saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">

       <saml:AttributeValue xsi:type="xs:string">users</saml:AttributeValue>

     </saml:Attribute>

   </saml:AttributeStatement>

 </saml:Assertion>

</samlp:Response>

在本报告中,上述 XML 文档已经简化,但结构是相同的。外部“父”文档是 SAML 响应,包括关于请求的元数据和断言文档。断言(也称为“SAML 断言”)是由 IdP 提供给 SP 的数据,用于身份验证过程。在一个 SAML 响应中可能存在多个断言。在上面的示例中, ds:Signature 括号中的内容是对父对象中的内容执行的加密签名,在这种情况下,该内容就是断言。同样的签名对象也可以应用于整个响应对象。签名的目的是让 SP 验证断言或响应中包含的数据是否合法,以及是否由 IdP 提供。对于断言,签名只适用于断言中包含的所有数据,比如用户名、电子邮件地址或组成员身份指示。在响应级别应用的签名适用于响应的全部内容和其中的所有断言。

对 SAML 响应中的各种签名执行的验证委托给 SP 处理,通常在配置 IdP 以与应用程序通信时配置此验证。在我们对此问题的回应中,我们认为,SAML 响应的默认验证条件应该如下所示。

  • 当整个 SAML 响应具备有效签名时,响应中的所有断言必须具有正确的签名,或者不包含任何签名。如果发现任何无效的签名,验证必定会失败。这种方法依赖于 IdP 对整个消息正文(有签名)具有权威性。
  • 当 SAML 响应没有签名时,响应中的所有断言必须具有正确的签名,否则验证必定失败。
  • 当 SAML 响应具有无效的签名时,验证必定失败。

Akamai 提议的 Lasso 补丁实施了上述处理条件。

在此问题开始时提供给 Akamai 的报告显示,研究人员在一个 SAML 响应中提交了两个 SAML 断言,第一个具有有效签名,而第二个没有签名。Lasso 的默认配置具有以下默认验证条件。

  • 如果响应中的第一个 SAML 断言具有有效签名,则验证通过,而不考虑整个 SAML 响应签名是否有效。
  • 如果第一个 SAML 断言具有无效签名,则验证失败。
  • 如果 SAML 响应具有有效签名,并且没有断言具有签名,则验证通过。
  • 否则,验证将失败。

 更复杂的是,当库认为响应有效时,从 SAML 响应中检索断言的函数将返回响应对象中的最后一个断言,而不考虑它是否具有有效签名。举例来说,假设一个攻击者从 IdP 获得了一个有效的 SAML 响应(具有单个断言),如上所示,并添加了以下内容作为第二个断言:

  <saml:Assertion>
 <saml:AttributeStatement>
   <saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
     <saml:AttributeValue xsi:type="xs:string">superuser</saml:AttributeValue>
   </saml:Attribute>
   <saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
     <saml:AttributeValue xsi:type="xs:string">admins</saml:AttributeValue>
   </saml:Attribute>
 </saml:AttributeStatement>
</saml:Assertion>

如果提供的用户对于企业有效,但具有更多权限,他们会将合并的 SAML 响应提交给 SP:

  <samlp:Response>
 <saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer>
 <saml:Assertion>
   <ds:Signature>
    ... Assertion Signature ...
   </ds:Signature>
   <saml:AttributeStatement>
     <saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
       <saml:AttributeValue xsi:type="xs:string">test</saml:AttributeValue>
     </saml:Attribute>
     <saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
       <saml:AttributeValue xsi:type="xs:string">users</saml:AttributeValue>
     </saml:Attribute>
   </saml:AttributeStatement>
 </saml:Assertion>
 <saml:Assertion>
   <saml:AttributeStatement>
     <saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
       <saml:AttributeValue xsi:type="xs:string">superuser</saml:AttributeValue>
     </saml:Attribute>
     <saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
       <saml:AttributeValue xsi:type="xs:string">admins</saml:AttributeValue>
     </saml:Attribute>
   </saml:AttributeStatement>
 </saml:Assertion>
</samlp:Response>

当 Lasso 试图验证这个 SAML 响应时,结果将是:该响应是有效的。当发起调用的应用程序从上述响应中检索断言时,将返回具有超级用户的用户 ID (uid) 的断言,此断言可能被认为是一个有效的断言。除了上面的示例以外,如果 SAML 响应本身具有有效的签名,这种冒充方法也是可行的。EAA 对 SAML 响应执行的处理就属于这种情况。 

发生漏洞利用的条件

为了使 SAML 响应在提交给 SP 之前遭到修改,必须出现以下条件之一:

  • 合法客户端(由有效的授权用户控制,并通过该客户端来重定向 SAML 响应)必须注入额外的断言文档,以作为 SAML 响应的一部分,从而更改 SAML 响应。例如,这可能是通过客户端系统上的恶意浏览器扩展程序或其他恶意软件,有时被称为“浏览器中间人攻击”。
  • 攻击者必须获得 SAML 响应的有效副本,该副本之所以仍然有效,要么是因为在断言过期前仍有剩余时间,要么是因为在某些应用程序中,断言还没有呈现给 SP。例如,一个中间方可以通过代理来拦截并修改 SAML 响应,这通常被称为“中间人攻击”。
  • 一个未经授权的客户端要么知道、要么能够猜到授权用户的登录信息。收集登录信息的方法很多,包括网络钓鱼、密码泄露、猜测或暴力破解攻击

上述每一种情况都可能导致用户的会话遭到入侵,如果 SAML 实施存在上述缺陷,SP 就容易遭受冒充攻击。

该漏洞的历史

这个相同的漏洞(名为 XML 签名包装)已经被报告了一次一次

对 Lasso 存储库的审查表明,该库的漏洞早在 2005 年 11 月就已纳入了代码库,远远早于我们纳入该库的时间,也早于之前公布的漏洞发布到其他平台的时间。

我们在调查过程中还注意到,Lasso 库的维护者在向 Akamai 发送问题通知后不久就 承诺 参与该项目。与报告人的讨论表明,这次提交与他们的报告完全没有关系,只是巧合而已。

2021 年 2 月 24 日提出的修复方案部分解决了该漏洞的影响,但经过进一步审查,我们认为这不是一个完整的修复方案,这就是为什么最终向维护者提议了我们的补丁。

了解 Akamai 的事件响应

Akamai 遵循正式的事件响应流程。工程/系统开发、网络运营和客户支持人员之间相互合作,定期处理事件。一般来说,事件越严重,参与处理的人员就越多,事件的优先级也就越高,超过了计划内的运营和工作。在所有事件中,Akamai 的目标是: 

  • 限制问题的影响, 
  • 确保我们的系统持续、安全运行,
  • 确保我们的事件响应者提供持续、安全的支持,
  • 让客户满意,保障他们的数据安全,
  • 遵守各种法律和法规,
  • 确保我们能够从允许事件发生的任何危险情形中学到经验教训并实现改进。

如上所述,我们在接到这个漏洞的通知后,立刻启动了我们的事件响应流程。该流程使 Akamai 能够调整技术资源,与内部利益相关者和管理层进行沟通,与外部利益相关者进行沟通,并及时有效地协调与该事件相关的所有活动。

修补与部署过程

开发该漏洞的修复方案并在 EAA 网络上部署补丁的过程与计划内升级所遵循的正常流程非常相似,只是变更要小得多,且时间更短。

在事件响应的初始阶段,我们准备了一个修复时间表草案,并考虑到了一些关键决策。该时间表如下所示:在修复方案准备就绪后,按照标准 QA 流程,QA 流程预计需要 3 天,而部署阶段将耗费 48 小时。在部署阶段之后,我们计划以博客文章和客户通知的形式来沟通此问题。这些时间表本来可以进一步缩短,但由于没有证据表明存在活跃的漏洞利用,我们优先考虑了我们的网络稳定性,并确保我们的客户在整个过程中保持稳定。

在对问题进行初步分类后,工程团队通过两条途径进行修复,两者使用了不同的工程和 QA 资源。 

一个团队调查了问题并开发了一个部分修复方案,该方案解决了报告的问题,并对 SAML 响应的处理要求进行了限制。我们认为,这种方案会正常呈现带有断言的 SAML 响应。这种方法可能导致 IdP 发出的一些响应遭到拒绝,即使它们是有效和安全的。这种方法也可以选择为各个客户禁用更严格的检查,以便在与少数 IdP 发生意外交互的情况下,使其他客户群得到保护。

另一个团队采取了与第一个团队类似的方法,但他们开发的不是可配置的部分修复方案,而是我们所认为的完整修复方案。他们的方法经过了仔细审查,以确保所有格式良好和正确签署的 SAML 响应将被接受,从而减少复杂性,使得客户可以更轻松地完成降级。

我们采用了这种双管齐下的策略,这是因为,当一条途径受阻或遇到 QA 难题时,这种策略使得我们仍然可以部署一种修复方案。美国东部时间 2 月 24 日晚些时候,我们预计,在事件开始三天后,部分修复方案将准备好进行 QA,而完整修复方案的开发预计还需要多耗费一个星期。工作一直持续到 25 号,工程团队的进度报告显示,完整修复方案进展顺利,预计最终开发速度会更快、测试复杂性会更低。

最终,完整修复方案移交给 QA 团队的时间比部分修复方案提前了大约一天。在第一个方案移交给 QA 团队后,我们向所有 EAA 客户发布补丁通知,告知了预期的部署时间范围。

此状态在整个 QA 过程中保持不变。在维护时间窗口前不久,完整修复方案得到了 QA 团队的签核,这为部署扫清了道路。

部署过程从一个负载很低的入网点 (POP) 开始, 我们在这个入网点上运行了一个扩展的回归套件,并仔细监测了流量,以确定对客户造成的潜在中断。我们升级了另一个负载很小的 POP,缩短了测试过程,并进行了一段时间的监测。3 月 2 日凌晨,我们升级了为 Akamai 内部 EAA 部署提供服务的 POP,以便通过近 8000 名最终用户执行更多负载测试。我们发现,到那时为止的任何部署都没有问题,然后,其余 POP 在维护时间窗口的剩余 36 小时内进行了升级,最终在维护时间窗口结束前完成了部署过程。 

在升级过程中,大多数与 EAA 应用程序进行交互的用户可能看到一个或多个与重新执行身份验证有关的交互。 这些交互通常包括一次临时会话中断,并会重定向到他们的 IdP 以输入他们的凭据,然后方可恢复正常工作。EAA 客户端的用户也可能观察到这种行为。在部署过程中,EAA 客户会集中完成重新执行身份验证的操作。在每个 POP 上执行代码升级后,EAA 保留的会话缓存将被清除,这将在 5 分钟内对所有请求触发重新执行身份验证的过程。重新执行身份验证后,我们发现,对最终用户没有进一步的影响。

管理事件团队

在开发、验证用于解决此类重大问题的修复方案并向我们的网络安全部署该修复方案时,需要重视一件事:仔细关心处理问题的团队。Akamai 的事件管理流程和配套的培训包含相应的指南,说明了如何降低对事件进行响应的技术和管理团队的倦怠感。该指南包括对事件团队的以下事项进行核实:

  • 吃饭(按时)
  • 睡觉(最好能睡足整“夜”)
  • 承担个人义务
  • 保持健康(新冠疫苗、锻炼)

虽然对手头的事件进行补救至关重要,但我们发现,通过在整个过程中保持团队关怀,有助于让受影响的产品和/或系统最终变得更加安全,与此同时,也能减少可以避免的错误,以及减少通常与高压型事件响应过程有关的、可能会对客户造成影响的事件。

Akamai 事件管理流程的另一个关键特征在于一项原则:我们一起携手努力,我们现在和将来都不会责怪任何人。事件团队共同解决问题,无论是什么样的问题,我们都要以最好的方式来解决,我们注重的是首先减少影响,然后想办法防止它再次发生。Akamai 专注于寻找导致事件发生的假设,从这些不完整的假设中学习,并进行适当修改,以降低该事件或类似事件再次发生的几率。

需要采取的行动

依靠 Lasso 执行 SAML 身份验证的系统所有者应尽快完成修补。可能需要采取其他行动来调查对经过身份验证的系统造成的影响。有关可能需要采取的行动的更多信息,请参见本文的配套文章中的“需要采取的行动”一节。

时间表

时间戳(全部为 UTC) 活动
2230 - 2021 年 2 月 23 日 向 Akamai 的信息安全小组发送了外部漏洞报告
1222 - 2021 年 2 月 24 日 Akamai 信息安全小组解密了该报告并开始调查该问题
1242 - 2021 年 2 月 24 日 响应人员启动了 Akamai 事件管理流程,召集必要的各方调查并修复问题。
2000 - 2021 年 2 月 24 日 问题被工程团队成功再现。
0132 - 2021 年 2 月 27 日 向 Akamai Control Center 发布了补丁通知
1500 - 2021 年 3 月 1 日 与 Lasso 的维护者首次联络
0100 - 2021 年 3 月 2 日 开始部署修复方案
1126 - 2021 年 3 月 2 日 Akamai 的生产服务进行了升级,以对升级进行严格测试
2134 - 2021 年 3 月 2 日 研究人员确认,他们的漏洞无法在修补过的系统上出现。
2336 - 2021 年 3 月 4 日 修复方案部署完成
1646 - 2021 年 3 月 8 日 保留 CVE ID CVE-2021-28091
1747 - 2021 年 3 月 8 日

与 CERT/CC 首次联络以报告该漏洞。

1200 - 2021 年 6 月 1 日 禁止发布完成


Akamai Wave Blue

寫於

Akamai

June 01, 2021

Akamai Wave Blue

寫於

Akamai