英雄背景无分隔线
准则

身份验证和授权

身份验证 (AuthN) 和授权 (AuthZ) 的主题极其重要,因为其中任何一个都容易受到攻击的漏洞频繁出现。由于它们似乎经常出现,这通常意味着它们是什么甚至是导致它们的原因存在一定的不确定性。

提醒一下,每个学期都涵盖以下内容:

  • 身份验证:谁是用户?
  • 授权:用户应该有权访问什么?

我们将在下面单独研究它们。

身份验证(识别和身份验证失败)

身份验证不当可能涵盖各种漏洞,例如:

  • 特定页面/端点上没有身份验证
  • 缺乏针对暴力攻击的保护(凭证填充)
  • 不安全的帐户/密码恢复流程
  • 不安全的身份验证令牌生成、验证、到期、传输或存储
  • 用户已使用 2FA 进行身份验证的验证不正确或缺失(如果适用)

清单上的第一项(缺少身份验证)是迄今为止在野外观察到的最常见的问题。很多时候,开发人员必须明确注释/配置页面或端点所需的身份验证级别,而这一步很容易被忽略。

确保系统出现故障是一种很好的做法 关闭,而不是无法打开。因此,与其在每个端点上注明它们需要经过身份验证的用户会话的信息,不如默认值是 所有 路由需要经过身份验证的用户会话,除非它已被特别覆盖。这样做可以大大减少出错的余地。

授权(访问控制失效)

授权问题可能以多种不同的方式出现,这些方式很常见:

  • 不安全的直接对象引用 (IDOR)
  • 缺少功能级别访问控制(缺少 AuthZ)
  • 权限提升(水平或垂直)

不安全的直接对象引用

对象往往具有唯一标识符 (ID),用作引用它们的密钥。当用户发送查看订单、账户或类似内容的请求时,它通常包含此 ID。当应用程序无法验证用户(或没有用户)是否应该能够访问该特定对象时,就会出现 “不安全的直接对象引用”。

缺少功能级别访问控制

另一个非常常见的漏洞是缺乏对页面或端点(而不是对象)的授权检查。

根据所使用的框架,开发人员通常必须检查处理程序中的授权,或者对端点进行注释并指定调用端点所需的要求。

不幸的是,这些额外的步骤也很容易被忘记,这通常可以解释一些授权漏洞最终是如何发生的。

建议

默认为关闭而不是打开

对于身份验证和授权,默认为关闭而不是开放的原则很重要。

根据您的语言/框架,最好确保所有进入应用程序的路由的默认值都需要经过身份验证的会话并具有尽可能高的角色或权限。这样做会迫使开发人员超越对路线的要求。

cs

//确保默认行为是对请求进行身份验证,并检查它们是否是管理员
[身份验证]
[授权(“管理员”)]
公共类 SecureController:控制器
{

}

公共类 myController:安全控制器
{

//覆盖继承的 Authorize 属性以允许任何用户访问该页面
[授权(“用户”)]
公共页面 showUserProfile () {
        
}

//只能由管理员用户访问
公共页面 showAdminPage () {

}

//覆盖 Authenticate 和 Authorize 属性以允许我
[允许匿名]
公共页面 showLoginPage () {
       
}

}

在服务中强制执行授权检查

访问数据时,确保所有数据访问都以统一的方式执行相关的访问和授权检查极为重要。这通常是通过使用域名服务来实现的。

更多示例

下面,我们收集了一系列简短的示例,可以很好地说明安全和不安全的身份验证和授权之间的区别。

C#-不安全

缺少身份验证

公共类管理员控制器:控制器
{

//不安全:在显示管理员页面之前不检查用户是否已登录
公共页面 showAdminPage () {

}

}

缺少授权

[身份验证]
公共类管理员控制器:控制器
{

//不安全:在显示管理员页面公共页面 showAdminPage () 之前不检查用户的授权 sowAdminPage () {

}

}

C#-安全

[身份验证]
[授权(“管理员”)]
公共类管理员控制器:控制器
{

//安全:两者都检查用户是否已登录,并具有管理员角色
公共页面 showAdminPage () {

}

}