所有文章 > API安全 > 修复API中损坏的访问控制的指南
修复API中损坏的访问控制的指南

修复API中损坏的访问控制的指南

API 无处不在,其数量也比以往任何时候都要多。Programmable Web 网站曾记录了 2010 年代初期公共 API 的指数级增长,达到了超过 20,000 个,尚未包括许多企业内部使用的 API。最近,Gartner 报告称,到 2022 年,API 管理市场将增长 17%,收入达到 33 亿美元,成为应用基础设施和中间件市场增长第四快的部分。而根据 Cloudflare 2024 年的 API 安全与管理报告,目前超过一半的互联网流量是由 API 请求构成的。

世界银行(尽管并非科技组织)估计,公共数据的使用对全球 GDP 的增值贡献介于 0.4% 至 1.4% 之间。例如,丹麦的开放地址数据集在 2005 至 2009 年间带来了 6200 万欧元的直接经济效益,是 200 万欧元(约合 1500 万丹麦克朗)数据投资成本的数倍。这些发现对 API 经济至关重要,因为开放数据是 API 驱动的数据共享模式。

API 显著增长的原因有多方面。首先,API 促进了更简洁的应用程序开发架构。其次,开放银行、金融、保险、医疗保健等跨行业举措正在推动对更多 API 的需求。最后,随着生活方方面面的数字化,全球对更多 API 的需求也在不断增加。

因此,API 的普及是个好消息。开发面向更广泛受众的应用程序变得更为容易,上市时间大幅缩短。公司可以迅速响应客户需求,并加速创新。

然而,每一种新工具和范例的引入,也伴随着新的安全威胁。最常见的威胁之一就是访问控制的破坏。无怪乎,在 OWASP 十大威胁列表中,排名第一的威胁是 A01:2021 —— 访问控制损坏,而在 OWASP 十大 API 安全风险中,排名第一的是 API1:2023 —— 对象级授权损坏。接下来,让我们深入探讨这一挑战,并寻求解决方案。

什么是 OWASP 以及 OWASP 前十名?

开放全球应用程序安全项目(OWASP)是一个全球性的在线社区,致力于提供与物联网、系统软件和 Web 应用程序安全相关的免费文章、方法、文档、工具和技术资源。OWASP Top 10 是一份面向开发人员的安全意识标准文档,旨在代表 Web 应用程序中最关键的安全风险,并广泛获得业内共识。

更具体地说,OWASP API 安全项目的目标是通过识别不安全 API 中潜在的风险,并提供相应的缓解措施,帮助软件开发人员和安全评估人员提升安全性。为此,OWASP API 安全项目创建并维护了十大 API 安全风险文档,并提供了关于创建和评估 API 的最佳实践指导。

与授权相关的 API 威胁

损坏的对象级授权(BOLA)并非 API 面临的唯一威胁,还包括以下风险:

  • API3:2023 —— 损坏的对象属性级别授权
  • API5:2023 —— 功能级别授权被破坏
  • API6:2023 —— 无限制访问敏感业务流程
  • API7:2023 —— 服务器端请求伪造

修复?保护层、身份验证和授权的组合

为了有效解决 API 安全问题,需要通过多个组件的组合来提供保护:

  • API 网关、防火墙或代理
  • 身份验证层,可以嵌入网关中或作为独立的身份提供者
  • 授权层,可以嵌入网关中或作为独立的授权服务

第一步是部署 API。假设我们有一个开放的银行 API,并将其暴露出来。此时,它是“裸露的”,完全暴露在外界。当前的保护措施仅集成在应用程序中,或者依赖底层框架(例如 Java Spring)。因此,API 面临诸如 DoS 攻击、有效负载中毒和其他内容级攻击等威胁。

接下来,我们来介绍一下 API 网关,例如 Broadcom Layer7 API Gateway。网关提供了一种可扩展、高性能的方式,通过 API 将跨云、容器或本地环境的任意组合连接到最关键的数据和应用程序。

不受保护的API:

在API前边插入API网关

为了有效保护 API,应在 API 前面插入 API 网关。API 网关能解决 API 面临的核心安全挑战,并能够处理基本的身份验证和某些级别的授权。随着 IETF 在 OAuth 方面取得的进展,以及一套成熟的 OAuth 工具(例如授权服务器),身份验证问题也能得到更加完善的解决方案。

将基于标准的身份验证应用于 API

在身份验证方面,有几个标准可以提供帮助。其中,最流行和现代的标准是 OAuth 2.0 和基于身份验证的配置文件 OpenID Connect。OAuth 2.0 支持用户身份验证、委派、模拟等多种用例。OAuth 提供了不同的身份验证流程,每个流程都针对特定的用例进行定制:

  • 授权码流程
  • 客户端凭证流程
  • 客户端启动的反向通道身份验证流程(CIBA)
  • 混合流
  • JWT 承载流程
  • 设备流程

在涉及 API 的情况下,API 客户端(可能是应用程序的后端)需要发送用户的令牌(无论是透明的访问令牌还是可能是 JWT 令牌)。该令牌来自授权服务器,是最终用户完成身份验证过程后的结果(例如 OAuth 2.0 中的授权码流)。身份验证的处理方式有多种。例如,使用的令牌可以是用户的实际令牌(访问令牌、JWT 令牌,甚至 ID 令牌),或者 API 调用可以使用系统到系统的令牌(例如客户端凭证)。具体方式将取决于架构团队的决策。

配置授权层时,确保了解如何访问最终用户的身份信息,以便授权层能够利用这些信息进行授权。

需要注意的是,身份验证流程在 OAuth 2.0 中有时被称为 RS/AS 模式(资源服务器/授权服务器模式)。该模式允许通过使用范围和声明来进行某种程度的粗粒度授权。IETF 内部正在开展进一步的工作,以推出一种名为交易令牌的新型令牌,这将有助于进一步增强授权功能。

完成身份验证步骤后,我们就知道了正在进行操作的主体——即最终用户的身份。这个步骤的结果是,接下来至关重要的一步——授权。

将基于标准的授权应用于 API

现在我们已经知道了用户的身份,接下来需要确认的是他们可以执行哪些操作。这就是授权步骤的目标。

幸运的是,OASIS XACML 和 NIST 发布了一种架构,现在已成为外部化和细粒度授权的标准模式。这个架构的主要组成部分包括:

  • 策略执行点(PEP):PEP 拦截客户端与目标系统(如 API、应用程序或数据库)之间的调用,创建授权请求(是/否问题),并将其发送到 PDP。当 PDP 做出决策后,PEP 会执行该决策。API 网关通常在这个环节发挥作用。
  • 策略决策点(PDP):PDP 是决策的核心。它根据从 PEP 收到的请求,按照配置的策略进行评估,可能还会从策略信息点(PIP)中检索所需的元数据,并生成允许或拒绝的决策。PDP 还可以返回一些声明(例如,要求 MFA)。
  • 策略管理点(PAP):PAP 是控制平面,主要负责编写和管理策略,并将其发送到 PDP。PAP 本身不参与运行时的决策过程。
  • 策略信息点(PIP):PIP 是一个抽象接口,PDP 可以通过它连接到第三方存储库(如 LDAP、REST、SCIM、SQL、Graph 等),以检索用户、资源和应用程序的元数据,例如用户的批准限制或银行账户余额。

那么,回到本文的核心问题,如何修复与 OWASP API 威胁相关的访问控制问题呢?我们可以通过以下步骤来缓解与访问控制损坏相关的特定风险:

  • API1:2023 – 对象级授权被破坏
  • API3:2023 – 损坏的对象属性级别授权
  • API5:2023 – 功能级别授权被破坏
  • API6:2023 – 无限制访问敏感业务流程
  • API7:2023 – 服务器端请求伪造

一旦您建立了 P*P 架构并且了解了请求者的身份,修复就相对简单了:编写策略并将其部署到 PDP。编写策略的语言有多种选择,例如 OPA 的 Rego、Oso 或 ALFA。下面是使用 ALFA 编写并部署到 PDP 的一个示例。

示例:开放银行 API 的 ALFA 策略

假设我们的 API 暴露了以下端点。请注意,这只是一个简单的示例,实际情况中不要直接使用此设计:

  • /accounts
  • GET /accounts:列出用户的账户。
  • GET /accounts/{accountId}:列出指定 accountId 的特定账户。
  • POST /accounts:创建新账户。
  • /accounts/{accountId}/transactions
  • GET /accounts/{accountId}/transactions:列出指定账户的最近交易。
  • GET /accounts/{accountId}/transactions/{txId}:列出指定交易的详细信息。
  • POST /accounts/{accountId}/transactions/:创建从指定账户到目标账户的转账。

针对每个端点和方法,我们可以定义具体的授权策略。例如,以下是开放银行用例中的 ALFA 策略代码:

namespace openbanking{
policyset main{
apply firstApplicable
/**
* 控制对银行账户的访问
**/
policyset accounts{
target clause object=="account"
apply firstApplicable
/**
* 确定谁可以查看账户
**/
policy viewAccount{
target clause action=="view"
apply firstApplicable
/**
* 任何用户都可以查看他们拥有的账户
*/
rule owner{
permit
condition account.owner == user.username
}
/**
* 分行职员可以查看同一分行客户的账户
*/
rule branch{
target clause user.role == "teller"
permit
condition user.branch == account.branch
}
}
}
}
}

一旦我们编写了策略,就可以开始编写示例授权请求。以下是 XACML/JSON 格式的授权请求示例:

{
"Request": {
"ReturnPolicyIdList": true,
"AccessSubject": {
"Attribute": [
{
"AttributeId": "openbanking.user.username",
"Value": "Alice"
}
]
},
"Resource": {
"Attribute": [
{
"AttributeId": "openbanking.object",
"Value": "account"
},
{
"AttributeId": "openbanking.account.accountId",
"Value": "AL47 2121 1009 0000 0002 3569 87411"
}
]
},
"Action": {
"Attribute": [
{
"AttributeId": "openbanking.action",
"Value": "view"
}
]
}
}
}

请注意,此请求不包含元数据,例如账户所有权或分行信息。这些信息将通过 PIP 获取并由 PDP 计算。

关于 AuthZEN 的说明

截至 2023 年 6 月,一些从业者和供应商在 OpenID 基金会的领导下聚集,推动创建一种新的 PEP-PDP 标准,以提高不同框架之间的互操作性。这个新标准现被称为 AuthZEN,并且在本文撰写时,已经处于实施者草案阶段,已有 12 个实现符合该标准。具体示例可以参见此 Postman 集合。

进出时授权

在上面的示例中,我们检查用户是否可以查看整个银行账户信息。可能我们希望授权用户查看账户的部分内容,例如账户 ID、余额或交易列表。为此,我们可以在内部 API 向网关返回调用时,在出站通道上应用授权检查。网关可以拦截流量并触发一系列新的授权检查。这些检查可以以批处理模式进行。例如,可以提出这样的查询:“Alice 是否可以查看账户 #123 的 ID、余额和交易列表?”查询返回的结果可能是“允许”、“拒绝”或“拒绝”等。

结论

恭喜!外部化和基于策略的授权能够有效解决 OWASP 前十名中的安全风险。例如,针对 API1:2023 – 对象级授权损坏(BOLA),上述 ALFA 策略能够直接解决这一问题,因为它在授予访问权限之前会验证用户是否为账户的所有者。随着时间推移,策略可以不断丰富和加强,而无需重新部署应用程序或 API。

为了实现这一愿景,您可以将 Layer7 API 网关与 Axiomatics 的细粒度授权服务结合使用,身份验证部分则可以委托给 Curity 的 Identity Server。如果您想看到实际效果,我们非常乐意为您展示。

原文链接:A Guide to Fixing Broken Access Control in Your APIs

#你可能也喜欢这些API文章!