授权备忘录¶
简介¶
授权可定义为“验证特定实体请求的动作或服务是否被批准的过程”(NIST)。授权与认证不同,认证是验证实体身份的过程。在设计和开发软件解决方案时,务必牢记这些区别。一个已通过认证(可能通过提供用户名和密码)的用户通常无权访问系统通过技术手段可能提供的所有资源并执行所有操作。例如,一个 Web 应用程序可能既有普通用户,也有管理员,管理员能够执行普通用户即使已通过认证也无权执行的操作。此外,访问资源并不总是需要认证;未经认证的用户可能被授权访问某些公共资源,例如图像或登录页面,甚至整个 Web 应用程序。
本备忘录的目标是帮助开发人员实现健壮、符合应用程序业务上下文、可维护且可扩展的授权逻辑。本备忘录中提供的指导应适用于开发生命周期的所有阶段,并足够灵活以满足多样化开发环境的需求。
与授权逻辑相关的缺陷是 Web 应用程序的一个显著问题。“访问控制失效”在 OWASP 2021 十大安全风险中被列为最令人担忧的 Web 安全漏洞,并被 MITRE 的 CWE 项目断言具有“高”的利用可能性。此外,根据 Veracode 软件安全状况报告第 10 卷,访问控制是 OWASP 十大风险中更常涉及漏洞利用和安全事件的风险之一,尽管它是所审查风险中发生率最低的之一。
利用授权缺陷可能造成的潜在影响在形式和严重性上都高度可变。攻击者可能能够读取、创建、修改或删除本应受保护的资源(从而危及其机密性、完整性或/和可用性);然而,此类行为的实际影响必然与受损资源的关键性和敏感性相关联。因此,成功利用授权缺陷的业务成本可以从非常低到极高。
完全未经认证的外部人员和已认证(但不一定授权)的用户都可能利用授权弱点。尽管非恶意实体由于诚实的错误或粗心大意可能导致授权绕过,但通常需要恶意意图才能完全实现访问控制威胁。横向权限提升(即能够访问另一个用户的资源)是一种特别常见的弱点,认证用户可能能够利用。与授权控制相关的故障可能允许恶意内部人员和外部人员查看、修改或删除各种形式的敏感资源(数据库记录、静态文件、个人身份信息 (PII) 等),或执行他们不应拥有特权的操作,例如创建新账户或发起昂贵的订单。此外,如果与访问控制相关的日志记录未正确设置,此类授权违规行为可能未被发现,或者至少无法归因于特定个人或团体。
建议¶
强制执行最小权限原则¶
作为一种安全概念,最小权限原则指仅向用户分配完成其工作所需的最低权限。尽管这在系统管理中最为常见,但该原则对软件开发人员也同样重要。最小权限原则必须横向和纵向应用。例如,尽管会计师和销售代表在组织层次结构中可能处于同一级别,但他们都需要访问不同的资源来执行其工作。会计师可能不应被授予访问客户数据库的权限,而销售代表也不应能够访问薪资数据。同样,销售部门负责人可能需要比其下属更多的特权访问权限。
未能强制执行应用程序中的最小权限原则可能会危及敏感资源的机密性。缓解策略主要在架构和设计阶段应用(参见 CWE-272);然而,该原则必须贯穿整个软件开发生命周期 (SDLC)。
考虑以下几点和最佳实践:
- 在设计阶段,确保定义信任边界。列举将访问系统的用户类型、公开的资源以及可能对这些资源执行的操作(如读取、写入、更新等)。对于用户类型和资源的每个组合,确定用户(基于角色和/或其他属性)必须能够对该资源执行哪些操作(如果有)。对于 ABAC 系统,确保考虑所有属性类别。例如,销售代表可能需要在工作时间内从内部网络访问客户数据库,但不能在午夜从家中访问。
- 创建测试以验证设计阶段映射的权限是否被正确强制执行。
- 应用程序部署后,定期审查系统中的权限,以防“权限蔓延”;也就是说,确保当前环境中用户的权限不超过设计阶段定义的权限(加减任何正式批准的更改)。
- 请记住,授予用户额外权限比收回他们以前享有的权限更容易。在 SDLC 早期仔细规划和实施最小权限原则有助于降低稍后需要撤销被认为过于宽泛的权限的风险。
默认拒绝¶
即使没有明确匹配任何访问控制规则,当实体请求访问特定资源时,应用程序也不能保持中立。应用程序必须始终做出决定,无论是隐式还是显式,以拒绝或允许所请求的访问。与访问控制相关的逻辑错误和其他错误可能会发生,尤其是在访问要求复杂时;因此,不应完全依赖明确定义的规则来匹配所有可能的请求。为了安全目的,应用程序应配置为默认拒绝访问。
考虑以下几点和最佳实践:
- 在初始开发期间以及应用程序暴露新功能或资源时,都应采用“默认拒绝”的心态。应该能够明确证明为什么向特定用户或组授予了特定权限,而不是假设访问是默认立场。
- 尽管某些框架或库本身可能采用默认拒绝策略,但应优先选择显式配置,而不是依赖框架或库的默认设置。第三方代码的逻辑和默认设置可能会随着时间而演变,而开发人员可能无法完全了解或理解这些更改对特定项目的影响。
在每个请求上验证权限¶
无论请求是由 AJAX 脚本、服务器端还是任何其他来源发起,都应在每个请求上正确验证权限。用于执行此类检查的技术应允许全局、应用程序范围的配置,而不是需要单独应用于每个方法或类。请记住,攻击者只需要找到一种进入方式。即使只“漏掉”一个访问控制检查,资源的机密性和/或完整性也可能受到威胁。仅在大多数请求上正确验证权限是不够的。可以帮助开发人员执行此类一致权限检查的特定技术包括:
彻底审查所选工具和技术的授权逻辑,必要时实施自定义逻辑¶
如今的开发人员可以使用大量的库、平台和框架,这些使他们能够以最小的努力将健壮、复杂的逻辑集成到应用程序中。然而,这些框架和库不应被视为解决所有开发问题的速效药;开发人员有责任负责任地、明智地使用这些框架。与正确访问控制相关的框架/库选择的两个普遍关注点是开发人员的错误配置/缺乏配置以及组件本身的漏洞(有关这些主题的通用指导,请参阅 A6 和 A9)。
即使在一个开发安全的应用程序中,第三方组件中的漏洞也可能允许攻击者绕过正常的授权控制。此类问题不应仅限于未经证实或维护不善的项目,而是会影响即使是最健壮和最流行的库和框架。编写复杂、安全的软件是困难的。即使是最有能力的开发人员,在开发高质量库和框架时也会犯错误。假设您集成到应用程序中的任何第三方组件都可能存在或将出现授权漏洞。重要的考虑因素包括:
- 创建、维护并遵循检测和响应易受攻击组件的流程。
- 将 Dependency Check 等工具集成到 SDLC 中,并考虑订阅供应商、NVD 或其他相关来源的数据订阅。
- 实施纵深防御。不要依赖任何单一框架、库、技术或控制来单独强制执行正确的访问控制。
错误配置(或完全缺乏配置)是开发人员构建的组件导致授权失效的另一个主要方面。这些组件通常旨在成为相对通用的工具,以吸引广泛的受众。除了最简单的用例,这些框架和库必须进行定制或补充额外的逻辑,以满足特定应用程序或环境的独特要求。当涉及安全要求(包括授权)时,这一考虑尤为重要。授权的显著配置考虑因素包括:
- 花时间彻底了解您构建授权逻辑所依赖的任何技术。分析该技术的功能,并理解**组件提供的授权逻辑可能不足以满足您应用程序的特定安全要求**。依赖预构建的逻辑可能很方便,但这并不意味着它就足够了。理解自定义授权逻辑很可能对于满足应用程序的安全要求是必要的。
- 不要让任何库、平台或框架的功能来指导您的授权要求。相反,应首先确定授权要求,然后根据这些要求分析第三方组件。
- 不要依赖默认配置。
- 测试配置。不要仅仅假设对第三方组件进行的任何配置都能在您的特定环境中完全按预期工作。文档可能被误解、模糊、过时或干脆不准确。
优先使用基于属性和关系的访问控制而非 RBAC¶
在软件工程中,广泛使用了两种基本形式的访问控制:基于角色的访问控制 (RBAC) 和基于属性的访问控制 (ABAC)。还有一种较新的模型已获得普及:基于关系的访问控制 (ReBAC)。这些模型之间的选择对整个 SDLC 具有重大影响,应尽早做出决定。
-
RBAC 是一种访问控制模型,其中访问权限根据分配给用户的角色授予或拒绝。权限不直接分配给实体;相反,权限与角色关联,实体继承分配给其的任何角色的权限。通常,角色和用户之间的关系可以是多对多的,并且角色可能具有层次结构性质。
-
ABAC 可以定义为一种访问控制模型,其中“主体对对象执行操作的请求是根据主体分配的属性、对象分配的属性、环境条件以及一组以这些属性和条件形式指定的策略来授予或拒绝的”(NIST SP 800-162,第 7 页)。根据 NIST SP 800-162 的定义,属性只是可以表示为名称-值对并分配给主体、对象或环境的特征。职位、一天中的时间、项目名称、MAC 地址和创建日期仅仅是可能属性的一小部分示例,它们突出了 ABAC 实现的灵活性。
-
ReBAC 是一种基于资源之间关系授予访问权限的访问控制模型。例如,只允许创建帖子的用户编辑它。这在社交网络应用程序(如 Twitter 或 Facebook)中尤其必要,用户希望限制对其数据(推文或帖子)的访问,仅限他们选择的人(朋友、家人、关注者)。
尽管 RBAC 历史悠久,至今仍在软件开发人员中流行,但对于应用程序开发而言,通常应优先选择 ABAC 和 ReBAC。它们相对于 RBAC 的优势包括:
-
支持细粒度、复杂的布尔逻辑。在 RBAC 中,访问决策基于角色的存在或不存在;也就是说,请求实体考虑的主要特征是分配给它的角色。这种简单的逻辑在支持对象级或横向访问控制决策以及需要多因素的决策方面表现不佳。
- ABAC 大大扩展了可以考虑的特征的数量和类型。在 ABAC 中,“角色”或职务功能当然可以是分配给主体的属性之一,但它不需要孤立地考虑(如果此特征与所请求的特定访问不相关,则根本不需要考虑)。此外,ABAC 可以结合环境和其他动态属性,例如一天中的时间、使用的设备类型和地理位置。拒绝在正常工作时间之外访问敏感资源,或者如果用户最近没有完成强制性培训则拒绝访问,这些只是 ABAC 可以满足 RBAC 难以满足的访问控制要求的几个例子。因此,ABAC 在解决最小权限原则方面比 RBAC 更有效。
- ReBAC,由于它支持在直接对象和直接用户之间分配关系(而不仅仅是角色),因此允许细粒度权限。一些系统还支持代数运算符,如 AND 和 NOT,以表达诸如“如果此用户与对象具有关系 X 但没有关系 Y,则授予访问权限”之类的策略。
-
健壮性。在大型项目或存在大量角色时,很容易遗漏或不正确地执行角色检查(OWASP C7:强制访问控制)。这可能导致访问权限过多或过少。在 RBAC 实现中,如果不存在角色层次结构,并且必须链式执行多个角色检查才能达到预期效果(即
if(user.hasAnyRole("SUPERUSER", "ADMIN", "ACCT_MANAGER"))
),则尤其如此。 - 速度。在 RBAC 中,当系统定义过多角色时,可能会发生“角色爆炸”。如果用户通过 HTTP 头部等有大小限制的方式发送其凭据和角色,可能没有足够的空间包含用户的所有角色。解决此问题的一个可行方法是仅发送用户 ID,然后应用程序检索用户的角色,但这会增加每个请求的延迟。
- 支持多租户和跨组织请求。RBAC 不太适合需要不同组织或客户访问同一组受保护资源的用例。使用 RBAC 满足此类要求将需要非常繁琐的方法,例如在多租户环境中为每个客户配置规则集,或要求为跨组织请求预先配置身份(OWASP C7;NIST SP 800-162)。相比之下,只要属性定义一致,ABAC 实现允许访问控制决策“在相同或不同的基础设施中执行和管理,同时保持适当的安全级别”(NIST SP 800-162,第 6 页)。
- 易于管理。尽管 RBAC 的初始设置通常比 ABAC 简单,但随着系统规模和复杂性的增长,这种短期优势很快就会消失。最初,几个简单的角色,如用户和管理员,可能足以满足某些应用程序的需求,但这在生产应用程序中不太可能长期成立。随着角色数量的增加,测试和审计(建立代码库和逻辑信任的关键流程)都变得更加困难(OWASP C7)。相比之下,ABAC 和 ReBAC 表达能力更强,结合了更能反映实际情况的属性和布尔逻辑,在访问控制需求发生变化时更易于更新,并鼓励策略管理与身份执行和供应的分离(NIST SP 800-162;另请参阅 XACML-V3.0,该标准强调了这些优势)
确保查找 ID 即使被猜测也无法访问或无法被篡改¶
应用程序通常会暴露用于定位和引用对象的内部对象标识符(例如数据库中的账户号码或主键)。此 ID 可能会作为查询参数、路径变量、“隐藏”表单字段或其他位置暴露。例如:
https://mybank.com/accountTransactions?acct_id=901
基于此 URL,可以合理地假设应用程序将返回交易列表,并且返回的交易将仅限于特定账户——由 `acct_id` 参数指示的账户。但如果用户将 `acct_id` 参数的值更改为另一个值(例如 `523`)会发生什么?用户是否能够查看与另一个账户相关的交易,即使该账户不属于他?如果不能,失败是简单地因为账户“523”不存在/未找到,还是因为访问控制检查失败?尽管此示例可能过于简化,但它说明了应用程序开发中一个非常常见的安全缺陷——CWE 639:通过用户控制的密钥绕过授权。当被利用时,此弱点可能导致授权绕过、横向权限提升,以及较不常见的纵向权限提升(参见 CWE-639)。这种类型的漏洞也代表了不安全直接对象引用 (IDOR) 的一种形式。以下段落将描述该弱点及可能的缓解措施。
在上述示例中,查找 ID 不仅暴露给用户且易于篡改,而且似乎是一个相当可预测的、可能是顺序的值。虽然可以使用各种技术来掩盖或随机化这些 ID 以使其难以猜测,但这种方法本身通常不足够。用户不应仅仅因为能够猜测和操纵查询参数或其他地方的对象标识符,就能够访问他们没有权限的资源。与其依赖某种形式的模糊安全,不如将重点放在控制对底层对象和/或标识符本身的访问。此弱点的推荐缓解措施包括:
- 尽可能避免向用户暴露标识符。例如,应仅基于当前已认证用户的身份和属性(例如通过安全实现的 JSON Web Token (JWT) 或服务器端会话中包含的信息)来检索某些对象,例如账户详细信息。
- 使用 OWASP ESAPI 等工具实现用户/会话特定的间接引用(参见 OWASP 2013 十大风险 - A4 不安全直接对象引用)
- 对**每次**请求访问**特定**对象或功能时执行访问控制检查。仅仅因为用户有权访问特定类型的对象,并不意味着他们有权访问该特定类型的所有对象。
对静态资源强制执行授权检查¶
确保静态资源安全的重要性常常被忽视,或者至少被其他安全问题所掩盖。尽管确保数据库和类似数据存储的安全往往理所当然地受到安全意识团队的极大关注,但静态资源也必须得到适当的保护。尽管未受保护的静态资源对于各种形式的网站和 Web 应用程序来说无疑是一个问题,但近年来,云存储服务(如 Amazon S3 存储桶)中安全性差的资源日益突出。在保护静态资源时,请考虑以下事项:
- 确保将静态资源纳入访问控制策略。对静态资源所需的保护类型必然是高度上下文相关的。某些静态资源可能完全可以公开访问,而另一些则应仅在存在一组高度受限的用户和环境属性时才可访问。因此,理解所考虑特定资源中暴露的数据类型至关重要。考虑是否应建立正式的数据分类方案并将其纳入应用程序的访问控制逻辑(有关数据分类的概述,请参阅此处)。
- 确保用于存储静态资源的任何基于云的服务都使用供应商提供的配置选项和工具进行保护。查阅云提供商的文档(有关具体实现细节,请参阅 AWS、Google Cloud 和 Azure 的指导)。
- 如果可能,使用与保护其他应用程序资源和功能相同的访问控制逻辑和机制来保护静态资源。
验证授权检查在正确的位置执行¶
开发人员绝不能依赖客户端访问控制检查。虽然此类检查可能被允许用于改善用户体验,但它们绝不应成为授予或拒绝资源访问权限的决定性因素;客户端逻辑通常很容易被绕过。访问控制检查必须在服务器端、网关或使用无服务器函数执行(参见 OWASP ASVS 4.0.3,V1.4.1 和 V4.1.1)
授权检查失败时安全退出¶
访问控制检查失败在安全的应用程序中是正常现象;因此,开发人员必须为这些失败做好计划并安全地处理它们。对这些失败处理不当可能导致应用程序处于不可预测的状态(CWE-280:权限不足或特权不足处理不当)。具体建议包括:
- 确保处理所有异常和失败的访问控制检查,无论它们看起来多么不可能发生(OWASP 十大主动控制 C10:处理所有错误和异常)。这并不意味着应用程序应始终尝试“纠正”失败的检查;通常,一个简单的消息或 HTTP 状态码就足够了。
- 集中处理失败的访问控制检查的逻辑。
- 验证异常和授权失败的处理。确保此类失败,无论多么不可能,都不会使软件处于可能导致授权绕行的不稳定状态。
- 确保敏感信息(如系统日志或调试输出)不会在错误消息中暴露。错误配置的错误消息可能会增加应用程序的攻击面。(CWE-209:生成包含敏感信息的错误消息)
实施适当的日志记录¶
日志记录是应用程序安全中最重要的检测性控制之一;在 OWASP 2021 十大安全风险中,日志记录和监控不足被认为是其中最关键的安全风险。适当的日志不仅可以检测恶意活动,而且在事件发生后的调查中是无价的资源,可用于故障排除访问控制和其他安全相关问题,并对安全审计有用。尽管在初始设计和需求阶段容易被忽视,但日志记录是整体应用程序安全的重要组成部分,必须融入 SDLC 的所有阶段。日志记录的建议包括:
- 使用一致、定义明确的格式进行日志记录,以便于分析。根据 OWASP 十大主动控制 C9,Apache 日志服务是为多种语言和平台提供支持的一个项目示例
- 仔细确定要记录的信息量。这应根据特定的应用程序环境和要求来确定。日志记录过多或过少都可能被视为安全弱点(参见 CWE-778 和 CWE-779)。日志记录过少可能导致恶意活动未被发现,并大大降低事件后分析的有效性。日志记录过多不仅会占用资源并导致过多的误报,还可能导致敏感数据被不必要地记录。
- 确保系统间的时钟和时区同步。在事件响应期间和之后,准确性对于拼凑攻击序列至关重要。
- 考虑将应用程序日志集成到集中式日志服务器或 SIEM 中。
为授权逻辑创建单元和集成测试用例¶
单元测试和集成测试对于验证应用程序是否按预期执行以及在更改后保持一致至关重要。访问控制逻辑中的缺陷可能很微妙,尤其是在需求复杂时;然而,即使访问控制中一个小小的逻辑或配置错误也可能导致严重的后果。尽管不能替代专门的安全测试或渗透测试(有关此主题在访问控制方面的优秀指南,请参阅 OWASP WSTG 4.5),但对访问控制逻辑进行自动化单元测试和集成测试可以帮助减少进入生产环境的安全缺陷数量。这些测试擅长捕获安全问题的“唾手可得的成果”,但对于更复杂的攻击向量则不然(OWASP SAMM:安全测试)。
单元测试和集成测试应旨在纳入本文档中探讨的许多概念。例如,是否默认拒绝访问?即使在异常条件下,当访问控制检查失败时,应用程序是否安全终止?ABAC 策略是否得到正确执行?虽然简单的单元测试和集成测试永远不能取代熟练黑客进行的手动测试,但它们是快速检测和纠正安全问题的重要工具,所需资源远少于手动测试。
参考资料¶
ABAC¶
-
XACML-V3.0 强调这些优势的标准