我熟悉逻辑,如果您希望使用用户名和密码对某人进行身份验证,则无论是否找不到用户名,或者密码错误,都应该返回相同的错误。这个想法是,如果你单独返回"用户未找到"和"用户找到了,但密码错误"错误,攻击者可以尝试所有用户名并找出哪些用户名有效,然后将字典攻击集中在这些用户名上。
使用REST服务,我有一个只有某些用户才能访问的资源,我们可以将其称为/foo/{id}
。所以有各种各样的情况:
如果用户尝试访问/foo/4
并且他们有权访问,他们显然会获得200响应和资源。
用户尝试访问/foo/3
并且它不存在。 (我不知道如果它确实存在,他们是否可以访问它。因为它不存在。想想Facebook上不存在的照片,只有照片存在所有权信息。)
用户尝试访问/foo/4
,但它存在但无法访问。
所以我的问题是,在案例2和3中返回什么返回码?据我所知,有两种选择:
案例2返回404,案例3返回403.但这意味着攻击者可以找出存在哪些对象,类似于第一个示例中的密码示例。
毕竟,从用户的角度来看,所有示例都返回404,他们无法访问的资源不会存在"如果他们列出的话他们有权访问该资源的所有资源都不在列表中。
返回403以获取所有示例。
答案 0 :(得分:4)
这里的标准是什么?
希望“隐藏”当前存在的禁止目标资源的原始服务器可以使用状态代码404(未找到)进行响应。
有趣的是,在HTTP/1.0中,这已被扭转
如果服务器不希望将此信息提供给客户端,则可以使用状态代码403(禁止)。
你应该知道403和404有different default caching behavior。
在查看错误响应时,请注意恶意用户无法从返回的状态代码中收集有关系统的任何潜在敏感信息。例如:一个API搜索,它接受一个租户ID参数并返回一个没有结果的HTTP 404响应,如果租户ID不存在则返回一个HTTP 500响应。攻击者可能会利用此信息来确定租户ID是否有效。一种解决方案是捕获当提供的租户ID不存在时抛出的异常,并返回带有错误响应的HTTP 404状态代码。
请注意,状态代码不是可以被利用的响应的唯一部分;如果你要完成对齐状态代码的工作,你还应该确保消息体和标题也没有给出任何东西,the timing of the response没有给出显示,等等。
答案 1 :(得分:0)
在我们的项目中,我们继续选择第一项:
404
- 如果物理上缺少资源
403
- 如果用户无权访问
使用不透明的标识符解决了id-guessing的问题,例如GUIDs
:
/foo/08490cee-c5a1-4ea5-a00e-1a488fd58044
无法使用的标识符是任何公共API的常见建议,因为否则攻击者可以简单地添加或减去ID号,甚至可以学习他们不应该知道的事情,例如已经创建了多少个实体对象。还记得 - 数据库主键可能仍然是整数。
除此之外,我不确定这里会有任何标准。您可以继续使用适合您业务领域的三种方法中的任何一种。
答案 2 :(得分:0)
如果资源拥有所有者或多个所有者,这可能有所帮助:
如果资源确实存在,但不允许用户看到它,那么在内部就会想到它就像资源确实存在一样 - 但不适合你!"因此我就是这样。返回404。
如您所说,请注意返回403,因为它可能会暴露内部元数据。