在访问控制层之前先具有验证层是否可以


24

我正在创建一个API组合式Web应用程序,在此应用程序中,我们有不同的层,各自在工作。

第一层是验证用户输入的验证层,如果通过验证,则将其移至第二层(即访问控制层),否则返回错误消息

第二层是访问控制,它检查用户是否具有执行其想要执行的任务的权限,如果用户具有权限,则将请求移至下一层,否则返回错误消息

第三层是控制器层,我们具有应用逻辑

我的问题是在访问控制之前可以具有验证层吗?如果用户尝试执行用户没有权限的任务并且我们正在发回验证错误消息怎么办?用户将向端点发送请求并与验证层进行对话,并且仅在通过验证之后,他才会看到消息You can't access this!

我觉得很奇怪,所以这样还好吗?或者在基础设施方面我还有其他选择吗?


10
还值得一提的是,验证通常必须联系数据库以完成其工作或文件存储。如果在检查访问控制冲突之前执行此操作,则实际上可以使攻击者通过在该特定URL上抛出大量流量来DDoS数据库或文件系统。
格雷格·伯格哈特

就我而言,访问控制中间件也是如此,它检查资源并查看用户是否可以访问资源的类型,如果可以访问,我允许访问,否则不允许访问
Muhammad

确实如此。在DDoS期间,该层仍将打入您的数据存储。首先运行该层,您将不会对数据存储进行验证和访问控制-您将对其进行访问控制。它减小了海啸的大小,但并没有阻止海啸袭击海滩。它使您或您的服务器团队有机会在整个系统陷入瘫痪之前对攻击做出响应。
格雷格·伯格哈特

5
从实际的角度来看,访问控制应该始终在验证之前进行-如果用户首先无法访问请求,您将如何验证用户请求的正确性?
Zibbobz

@Zibbobz验证很简单,例如检查用户是否发送了正确的模式,例如应为integer的参数为integer或其他值
Muhammad

Answers:


57

这取决于是否知道不允许您执行某项任务的某些输入的有效性是否存在安全漏洞。如果是这样,您确实应该反过来做。

对未授权用户的唯一安全响应是“拒绝访问”。如果有时响应是“错误请求”,而有时是“拒绝访问”,则说明您正在向未经授权的用户发送信息。

例如,您可以检查是否存在命名文件存在的“删除文件”任务。没有权限的人可以通过尝试删除某事物并比较它们收到的错误来辨别某事物是否存在。特别确定的攻击者可以枚举所有文档名称(一定长度以下),以查看存在的名称。


7
绝对是+1。如果您的数据可以通过任何方式个人识别或敏感,那么安全隐患比可用性隐患要严重得多。
凯莉安·佛斯

4
@caleth实际上,它不会让您知道系统中是否存在某个文档,此类信息仅在您到达控制器层时给出。验证只检查架构,它不会访问数据库-只有访问控制和更深的层才可以访问数据库。同样,访问控制层仅在资源存在或不存在时向您显示相同的内容。唯一有问题的是我正在考虑的方案是否可以确定
Muhammad

@Caleth您能否详细说明您的最后评论?考虑到OP的评论,我看不到这种情况。在任何情况下,如果该模式已公开记录,则似乎唯一发送回的信息是非特权信息。
Rotem '18

11
@Rotem基本上不可能预先确定攻击者可以利用哪些信息。仅仅因为您还没有找到一种学习不该学习的方法的方法,并不意味着就没有这种方法。作为一个极端的例子,可能不存在任何漏洞,现在,但在未来有人可能添加一个检查到验证层不会泄露信息,因为他们不知道这是不受保护的。
卡米尔·德拉科里

4
@KamilDrakari并不是一个极端的例子,这是一个完全合理的例子。换句话说,如果您在访问控制之前进行验证,则开发人员每当要添加验证步骤时,都必须决定该验证是否公开任何敏感内容。每个开发人员正确调用该电话的机会似乎很小。
mfrankli

24

好吧,验证有多种类型:

  1. 廉价的基本健全性检查,可以验证请求是否显然没有格式错误。

    这通常是至少部分重复的客户端,以避免徒劳的往返。

    无论如何,应该在访问控制之前完成它,以使事情变得更容易且更不易出错,因为它不会冒任何信息泄漏的风险。

  2. 验证更昂贵,仍然不依赖于任何受保护的应用程序数据。

    如果有这样的额外验证,则可能是在访问控制之后才避免泄漏数据,而是阻止DOS攻击。
    有时,仅执行请求就可以以减少的成本或无成本的方式隐式地执行某些验证,因此此处可能将其省略。

    如果第一步的所有验证都重复了,那么也应该重复此客户端的某些部分。

  3. 其他验证取决于受保护的应用程序数据。

    在访问控制之前执行此操作显然会导致信息泄漏。因此,首先要进行访问控制。


3
最好在到达API之前,在基础结构中的策略执行点执行访问控制。首先是基本的静态验证集(例如:OpenAPI),然后是更深入的业务验证。甚至某些静态验证都可能会对您的应用程序ReDOS攻击的可用性产生影响。
felickz

@felickz:是的,DOS攻击是将验证推迟到授权之后的有效理由。这是一种平衡行为。无论如何,我将第一点分开以适当考虑这一点。
Deduplicator

在访问控制之前进行昂贵的验证还会因时序攻击而冒着信息泄漏的风险。如果系统根据资源花费的时间短或更长时间,则攻击者可以推断出所请求资源的各个方面。
Lie Ryan

@LieRyan:这就是所有可能在访问控制之前进行的验证完全不依赖于受保护的应用程序数据的原因。
Deduplicator

13

访问控制之前必须进行一些验证。假设SO的API有一个端点“编辑答案”,那么用户是否可以编辑特定的答案取决于答案(在一定信誉以下,用户只能编辑自己的答案)。因此,格式正确的“答案ID”参数必须在访问控制层生效之前进行验证;答案也可能存在。

正如Caleth和Greg所提到的,OTOH在访问控制之前进行了更广泛的验证,这是潜在的安全风险。

所以硬规则是

  1. 您不得通过验证泄露用户不应该发现的任何信息。
  2. 您必须先验证数据,然后访问控制才能在访问控制需要的范围内使用它。

遵循这两个规则可能意味着您必须在访问控制之前和之后进行一些验证。


3
这是现实的答案。如果其简单,直接的输入数据结构验证有效,则必须毫无限制地将其放在首位。它甚至可以保护访问控制层免受专门设计的输入/数据包的侵害。确实需要进行安全信息泄漏或猜测的验证,必须放在访问检查之后。
SD

假设答案是公开的。我敢说很多API甚至都不会向您显示没有身份验证的数据。
TomTom

6

验证输入后,除了可能收到“拒绝访问”之外,还可能感到沮丧;还请记住,除非非常简单,否则Validation层始终可以需要Controller的信息。牢记这一点,我认为将Validation定位在Access Control之后,更靠近Controller更为有意义。


2

这取决于验证层的含义-如果仅是检查请求的语法,那是安全的,无论如何您都必须做。如果您的“验证”使用了非特权用户无法访问的任何信息,则它不再安全。

在尝试进行访问控制之前,您绝对应该具有健全性检查器,但您应注意与所有维护人员(当前和将来)非常清楚地交流该部分一定不能使用特权信息;验证后,应在单独的验证步骤中进行任何此类检查。

作为健全性检查程序的健全性检查,它实际上不应该对代码的任何部分都具有任何代码依赖关系,而且应将其分离到自己的程序包中,该程序包应公开发布而不会出现任何问题(可能的法律问题除外)。 。如果您不能这样做,那么您的“验证层”做得太多(或者您的代码库很混乱)。


1

不,这不行。

如果验证层中有错误,则可能会绕过安全层。

将安全性视为业务需求的一部分是一个常见的错误。“只有具有销售角色的用户才能看到季度数字”似乎是一项业务规则。

但是,如果您想确保安全,则必须阅读以下规则:“只有销售角色的用户才能在此端点上运行代码”。确保服务器始终返回“访问被拒绝”您在服务器上编写的任何类型的代码或文件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.