跳转至

GraphQL Authorization Misconfiguration

GraphQL 授权配置错误

描述

GraphQL 授权配置错误(GraphQL Authorization Misconfiguration)是一个严重的安全漏洞,当 GraphQL API 未能在其所有操作和数据模型中一致且全面地强制实施访问控制时,就会出现此问题。 这种疏漏使未经授权的用户能够超出其预期权限访问、修改或删除信息,从而可能危及整个系统的安全。 此漏洞的主要特征包括不一致的访问控制(针对相似数据的不同查询或变异具有不同级别的授权检查)、过于宽松的架构(在没有适当限制的情况下公开敏感字段或操作)以及缺乏深度的查询限制(导致没有机制来防止资源密集型或过度嵌套的查询)。

影响

  1. 未经授权的数据访问和操作:
  2. 攻击者可以检索敏感信息,如个人用户数据、财务记录或专有业务信息。
  3. 恶意用户可能会更改或删除关键数据,从而影响系统完整性和用户信任。

  4. 潜在的权限提升:

  5. 攻击者可利用配置错误的查询或变异来获取管理员权限。
  6. 在系统内横向移动成为可能,从而允许访问其他受限区域。

  7. 破坏系统完整性:

  8. 整个数据集的可靠性和准确性受到质疑。
  9. 可能会发生违规事件,尤其是涉及 GDPR 或 CCPA 等数据保护法规时。

  10. 数据泄露:

  11. 通过精心设计的查询,大规模数据窃取变得可行。
  12. 竞争情报或用户数据库可能会在不被察觉的情况下被提取。

  13. 声誉受损:

  14. 公开披露此类漏洞可能导致失去用户信任并产生潜在的法律后果。

代码示例

  class UserType(DjangoObjectType):
    class Meta:
      model = User
      fields = ("id", "username", "email")

  class OrganizationType(DjangoObjectType):
    class Meta:
      model = Organization
      fields = ("id", "name", "users")

  class Query(graphene.ObjectType):
  all_users = graphene.List(UserType)
  organization = graphene.Field(OrganizationType, id=graphene.ID(required=True))

  def resolve_all_users(self, info):
    user = info.context.user
    if not user.is_authenticated:
      raise graphene.GraphQLError("Authentication required")
    return User.objects.all()

  def resolve_organization(self, info, id):
    try:
      org = Organization.objects.get(id=id)
    except Organization.DoesNotExist:
      raise graphene.GraphQLError("Organization not found")

    return org
在此示例中,请注意,即使 Users Query 实现了访问控制,而 Organization Query 却没有。 由于组织查询公开了嵌套的用户属性,攻击者可利用它来访问在直接查询时被拒绝的信息。

查询示例:

# 安全查询
query {
  allUsers {
    id
    username
    email
  }
}

# 漏洞查询
query {
  organization(id: "123") {
    id
    name
    users {
      id
      username
      email
    }
  }
}

建议

缓解最佳实践

  1. 实施一致的服务器端授权:
  2. 使用中间件或装饰器统一强制执行访问控制。
  3. 示例:

    @require_permission('admin')
    def resolve_sensitive_data(self, info):
        # 只有管理员可以访问此解析器
        pass
    
  4. 利用字段级权限:

  5. 在字段级别定义并强制执行访问控制。
  6. 使用 graphene-django 的示例:

    class UserType(DjangoObjectType):
        class Meta:
            model = User
            fields = ('id', 'username', 'email')
    
        @staticmethod
        def resolve_email(parent, info):
            if info.context.user.has_permission('view_email'):
                return parent.email
            return None
    
  7. 将自定义标量用于敏感数据:

  8. 实施具有内置授权检查的自定义标量类型。

  9. 禁用或限制内省:

  10. 在生产环境中,禁用内省或将其仅限制为经过身份验证和授权的用户。

  11. 定期进行安全审计和扫描:

  12. 对 GraphQL 架构、解析器和访问控制机制进行全面审查。

通过解决这些根本原因并实施强大的授权机制,开发人员可以显著降低 GraphQL 授权配置错误的风险,并创建更安全的 GraphQL API。

链接

标准

  • CCPA:
    • CCPA_1798_150
  • CWE_TOP_25:
    • CWE_862
  • OWASP_ASVS_L3:
    • V1_2_4
    • V4_1_3
    • V13_4_1
    • V13_4_2
  • SOC2_CONTROLS:
    • CC_6_3