所有文章 > API安全 > 细粒度授权修复关键API安全风险 - Auth0
细粒度授权修复关键API安全风险 - Auth0

细粒度授权修复关键API安全风险 - Auth0

什么是OWASP API安全十大风险?

OWASP社区的主要目标之一是让开发者和技术人员意识到其应用程序和系统面临的安全风险。为此,社区发布了一些文档来强调最常见的安全问题。

其中,《OWASP十大安全风险》是最受欢迎的文档,主要关注Web开发领域。此外,还有一个专门针对API的文档:《API安全十大风险》。

在2019年和2023年的文档版本中,都将对象级授权失效(Broken Object Level Authorization,简称BOLA)列为最关键的安全风险。令人惊讶的是,尽管已经过去了四年,这一问题仍然在全球范围内影响着API的安全性。那么,有没有办法缓解甚至消除这个漏洞呢?

答案是肯定的:通过设计适当的授权系统,可以有效防止这一漏洞对API的影响。但在找到解决方案之前,我们需要先了解什么是对象级授权失效。


什么是对象级授权失效?

授权是确定用户可以访问哪些内容的过程。这种访问控制可以根据具体应用的业务规则以多种方式实现。

在API环境中,每个对受保护端点的请求都需要被分析,以确定客户端是否有权访问和执行请求的操作。通常,这种检查在代码层面完成,主要是验证客户端是否有权限访问API端点暴露的资源(对象)。

需要保护的资源

在某些场景中,需要保护的资源是API端点本身。例如,/profile端点隐式返回当前用户的个人资料数据。API通常通过会话存储或请求中携带的访问令牌来识别当前用户。

而在其他场景中,需要保护的是请求的具体资源。例如,/profile/42端点返回ID为42的用户个人资料数据。在这种情况下,仅仅比较当前用户ID和请求的用户ID可能是不够的。例如,管理员可能需要访问所有用户的个人资料数据。这时,授权检查应该验证当前用户是否有权访问请求的对象。

如果在使用对象ID的端点中进行不准确的权限检查,API可能会暴露在BOLA攻击的风险之下。攻击者可以通过操纵对象ID来访问他们无权访问的对象。


BOLA漏洞实例

为了更好地理解对象级授权失效漏洞的危害,我们来看一个实际的例子。

假设你的银行提供了一个账户管理应用程序。作为开发者,你观察到应用程序通过调用https://thebankwebsite.com/accounts/9876543端点来获取你的账户(账号9876543)数据。

你想起有位朋友也在同一家银行开户,并且你曾给他转过账。通过聊天记录,你找到了他的账号1029387。于是,你使用curl或其他HTTP客户端,将端点URL修改为https://thebankwebsite.com/accounts/1029387,并重放HTTP请求到银行服务器。

令人惊讶的是,你竟然成功获取到了朋友的账户数据!这表明银行的API存在BOLA漏洞,其授权检查在对象访问层面失效了。

示例代码分析

以下是该银行API可能的实现方式:

const express = require('express');
const app = express();
const { auth, requiredScopes } = require('express-oauth2-jwt-bearer');

// 验证访问令牌的有效性
const validateAccessToken = auth({
  audience: '...yourApiIdentifier...',
  issuerBaseURL: https://...yourDomain.../,
});

// 检查访问令牌是否包含读取权限
const checkReadPermissions = requiredScopes('read:account');

app.get('/accounts/:accountNumber', validateAccessToken, checkReadPermissions, function(req, res) {
  res.json(getAccountData(req.params.accountNumber));
});

这段Node.js代码展示了如何处理/accounts/:accountNumber端点的GET请求。尽管该端点受两个中间件保护:

  • validateAccessToken:确保客户端提供有效的访问令牌;
  • checkReadPermissions:确保访问令牌包含必要的read:account权限范围;

但这些检查并不足以实现对账户对象的精确访问控制,因此无法阻止用户访问其他账户的数据。


如何预防BOLA漏洞?

避免使用可预测的对象标识符

一种常见的建议是避免在端点URL中使用容易识别的对象标识符,例如银行账号。可以使用GUID(全局唯一标识符)代替银行账号,因为GUID是随机生成的值,难以被猜测。

然而,这种方法只能降低BOLA攻击的风险,并不能从根本上解决问题。如果攻击者能够找到对象ID与GUID之间的关联,这种保护机制就会失效。

核心问题:授权机制

真正的问题在于授权机制。API的访问控制不应仅限于控制对端点的访问,还需要验证只有授权用户才能访问端点暴露的对象。

例如,在银行账户的场景中,可以通过以下方式检查当前用户是否是账户的所有者:

app.get('/accounts/:accountNumber', validateAccessToken, checkReadPermissions, function(req, res) {
  const userId = req.auth.payload.sub;
  const account = getAccountData(req.params.accountNumber);

  if (account.userId == userId) {
    res.json(account);
  } else {
    res.status(403).json("Permission denied.");
  }
});

虽然这种方法可以解决单一账户的授权问题,但对于更复杂的场景(如多人共有账户或银行员工访问权限)可能会显得力不从心。


什么是细粒度授权?

为了应对复杂的授权需求,可以使用细粒度授权(Fine-Grained Authorization, FGA)。FGA通过分析各种属性和关系描述的上下文,来更精确地控制对资源的访问。

常见的FGA模型

  • 基于属性的访问控制(ABAC):通过评估用户角色、资源类型、请求操作等属性来做出授权决策。
  • 基于策略的访问控制(PBAC):基于策略逻辑进行授权,与ABAC类似,但更注重逻辑规则。
  • 基于关系的访问控制(ReBAC):专注于用户与资源之间的关系,适用于复杂的授权场景。

Auth0 FGA与OpenFGA

  • Auth0 FGA:一个集中管理授权逻辑和数据的服务,支持定义授权模型、存储授权数据并在应用中进行授权决策。
  • OpenFGA:Auth0 FGA的开源实现,允许开发者在本地安装并集成到应用中。

FGA如何解决BOLA漏洞?

Auth0 FGA和OpenFGA通过集中管理授权逻辑,帮助开发者修复API中的对象级授权失效漏洞,同时保持代码清晰。

实现步骤

  1. 定义授权模型:描述系统中的对象类型及其关系。
  2. 存储授权数据:根据授权模型填充实际数据。
  3. 在API中添加授权检查:通过SDK将授权检查集成到API中。

以下是银行账户场景的授权模型示例:

model schema 1.1
type user
type branch
  relations
    define employee: [user]
type account
  relations
    define branch: [branch]
    define owner: [user]
    define can_view: owner or employee from branch

通过FGA引擎,API可以根据授权模型和数据动态验证用户权限,从而避免BOLA漏洞。


总结

本文详细介绍了对象级授权失效(BOLA)的概念及其危害,并通过实际案例分析了漏洞的成因。我们讨论了如何通过细粒度授权(FGA)解决这一问题,并展示了Auth0 FGA和OpenFGA的强大功能。

通过定义授权模型、存储授权数据以及在API中集成授权检查,开发者可以有效防止BOLA漏洞,同时保持代码的简洁和可维护性。

原文链接: https://auth0.com/blog/how-fine-grained-authorization-solves-critical-api-security-risk/
#你可能也喜欢这些API文章!

我们有何不同?

API服务商零注册

多API并行试用

数据驱动选型,提升决策效率

查看全部API→
🔥

热门场景实测,选对API

#AI文本生成大模型API

对比大模型API的内容创意新颖性、情感共鸣力、商业转化潜力

25个渠道
一键对比试用API 限时免费

#AI深度推理大模型API

对比大模型API的逻辑推理准确性、分析深度、可视化建议合理性

10个渠道
一键对比试用API 限时免费