跳到主要内容

4. 安全注意事项 (Security Considerations)

4.1 使用 Basic 认证对客户端进行认证

Basic 认证方案并不是一种安全的用户认证方法, 它也完全不能保护实体内容, 因为这些内容会通过物理网络以明文形式传输.HTTP 并不阻止使用额外的认证方案和加密机制来提升安全性, 也不阻止为 Basic 认证增加增强措施, 例如使用一次性口令的方案.

Basic 认证最严重的缺陷在于, 它实际上会在物理网络上传输用户密码的明文形式.摘要认证 (Digest Authentication) 正是试图解决这一问题.

由于 Basic 认证涉及密码的明文传输, 因此它 SHOULD NOT 在没有增强措施的情况下用于保护敏感或有价值的信息.

Basic 认证的一个常见用途是身份识别, 即要求用户提供用户名和密码作为识别手段, 例如为了在服务器上收集准确的使用统计信息.以这种方式使用时, 如果对受保护文档的非法访问并不是主要顾虑, 人们很容易以为它没有风险.只有在服务器同时向用户发放用户名和密码, 尤其是不允许用户自行选择密码时, 这种看法才成立.问题在于, 缺乏安全意识的用户经常复用同一个密码, 以避免维护多个密码的麻烦.

如果服务器允许用户自行选择密码, 那么威胁就不仅是对该服务器上文档的未授权访问, 还包括对用户在其他系统上用同一密码保护的任何资源的未授权访问.此外, 服务器密码数据库中的许多密码, 也可能正是这些用户在其他站点使用的密码.因此, 如果这类信息没有被安全地维护, 该系统的拥有者或管理员就可能使系统的所有用户暴露在其他所有相关站点被未授权访问的风险之下.

Basic 认证同样容易受到伪造服务器的欺骗攻击.如果用户被诱导相信自己正在连接到一个包含受 Basic 认证保护信息的主机, 而实际上却连接到了恶意服务器或网关, 那么攻击者就可以请求密码、将其保存以备后用, 然后伪装成错误.使用 Digest 认证时, 这种攻击则无法实现.服务器实现者 SHOULD 防范通过网关或 CGI 脚本进行此类伪造的可能性.尤其是, 接受连接的服务器行为应当完全处于服务器自身的控制之下, 而不是由网关或 CGI 脚本控制.否则, 该网关可能利用持久连接机制, 在伪装成原始服务器且客户端无法察觉的情况下, 与客户端执行多次事务.

4.2 使用 Digest 认证对客户端进行认证

与基于公钥的机制相比, Digest 认证并不能提供强认证机制.

不过, 它明显强于例如 CRAM-MD5 这样的机制, 后者曾被提议用于 LDAP [10]、POP 和 IMAP (见 RFC 2195 [9]).Digest 认证的目标, 就是替代弱得多且危险得多的 Basic 机制.

除了保护实际密码之外, Digest 认证并不提供机密性保护.请求和响应中的其他所有内容, 对窃听者来说都是可见的.

Digest 认证对双向消息完整性的保护也很有限.如果使用 qop=auth-int 机制, 那么用于计算 WWW-AuthenticateAuthorization 首部字段中 response 指令值的那些消息部分 (见上文第 3.2 节) 会受到保护.大多数首部字段及其值仍可能在中间人攻击中被修改.

Digest 认证无法满足许多安全 HTTP 事务的需求.对于这些需求, TLS 或 SHTTP 是更合适的协议.特别是, 对于任何需要机密性保护的事务, 都不能使用 Digest 认证.尽管如此, Digest 认证对于许多功能来说仍然是有用且合适的.任何当前仍在使用 Basic 认证的服务, 都应在条件允许时尽快切换到 Digest 认证.

4.3 受限使用的 Nonce 值

Digest 方案使用服务器指定的 nonce 作为生成 request-digest 值的种子 (如上文第 3.2.2.1 节所述).正如第 3.2.1 节中的 nonce 示例所展示的那样, 服务器可以自由构造 nonce, 使其只能由特定客户端、针对特定资源、在有限时间内、在有限使用次数内, 或在其他限制条件下使用.这样做会增强其对例如重放攻击的防护能力 (见 4.5 节).不过应当注意, 所选择的 nonce 生成与校验方法也会带来性能和资源方面的影响.例如, 服务器可以通过记录每个最近发出的 nonce 是否已经被返回, 并在每个响应的 Authentication-Info 首部字段中发送 next-nonce 指令, 从而让每个 nonce 值只能使用一次.这甚至可以防御立即发生的重放攻击, 但校验 nonce 值的成本很高, 并且流水线请求一旦无法完成认证, 代价可能更高 (这大概会导致 stale nonce 指示).类似地, 把某个请求特有元素, 例如资源的 Etag 值, 纳入 nonce, 会将该 nonce 的使用限制到该资源的特定版本, 同时也会破坏流水线.因此, 对于具有副作用的方法, 这样做也许是有用的; 但对于没有副作用的方法, 它可能带来不可接受的性能影响.

4.4 Digest 与 Basic 认证的比较

Digest 与 Basic 都算不上强认证机制, 因为它们未必能够阻止意志坚定的对手进行未授权访问.不过, 两者之间的比较清楚地表明, 用 Digest 替换 Basic 是有价值的, 甚至可能是必要的.

对于这种协议可能使用到的事务类型来说, 最大威胁是网络窃听.这类事务例如可能涉及在线访问一个仅对付费订阅者开放的数据库.若使用 Basic 认证, 窃听者能够获得用户密码.这不仅会让其访问数据库中的任何内容, 而且更糟糕的是, 还可能让其访问用户用同一密码保护的其他任何资源.

相比之下, 在 Digest 认证下, 窃听者只能获取当前事务中的信息, 而无法获得用户密码.窃听者所得到的信息可能允许发起重放攻击, 但通常也只能针对同一文档请求, 并且即便如此, 也还会受到服务器所选择 nonce 的限制.

4.5 重放攻击

对于简单的 GET 请求, 基于 Digest 认证的重放攻击通常没有意义, 因为窃听者已经看到了通过重放所能获得的唯一文档.这是因为所请求文档的 URI 已经被纳入客户端请求的摘要中, 服务器也只会返回该文档.相比之下, 在 Basic 认证下, 一旦窃听者掌握了用户密码, 任何受该密码保护的文档都将对其开放.

因此, 对于某些用途, 防御重放攻击仍是必要的.良好的 Digest 实现可以通过多种方式做到这一点.服务器创建的 nonce 值依赖于具体实现, 但如果它包含客户端 IP、时间戳、资源 ETag 以及服务器私钥的摘要 (如上文建议), 那么重放攻击就不会那么容易.攻击者必须说服服务器相信该请求来自一个伪造的 IP 地址, 还必须让服务器把文档发送到一个与服务器自认为目标地址不同的 IP 地址上.该攻击只能在时间戳过期之前的时间窗口内成功.将客户端 IP 与时间戳摘要进 nonce 中, 还允许实现无需在事务之间维护状态.

对于那些连重放攻击的可能性都无法容忍的应用, 服务器可以使用一次性 nonce 值, 即第二次不再接受同一个 nonce.这要求服务器在 nonce 时间戳过期前, 额外记录哪些 nonce 值已经被使用过.

4.6 多种认证方案带来的弱点

当服务器在 WWW-Authenticate 首部中提供多种认证方案时, 客户端应选择它所支持的最强方案.不过, 如果攻击者能够篡改响应并移除较强方案, 客户端就可能被迫使用较弱方案.

4.7 在线字典攻击

如果服务器不限制认证尝试的速率, 攻击者就可以尝试大量密码来猜测正确值.服务器 SHOULD 限制来自单一 IP 地址的失败认证尝试速率.

4.8 中间人攻击

Digest 认证容易受到中间人攻击.攻击者可以拦截客户端与服务器之间的通信, 并修改或替换消息.使用 TLS 或其他传输层安全机制可以防止此类攻击.

4.9 选择明文攻击

Digest 认证容易受到选择明文攻击.攻击者可以选择特定 URI 并观察所产生的摘要值, 从而可能获得与密码有关的信息.

4.10 预计算字典攻击

如果攻击者能够访问服务器的密码文件, 他就可以预先计算常见密码的摘要, 再将这些摘要与文件中的摘要进行比对.使用盐值 (salt) 可以提高这种攻击的难度.

4.11 批量暴力破解攻击

如果攻击者能够捕获多次认证交互, 他就可以离线暴力破解密码.使用强密码并限制 nonce 的有效期, 可以降低这种风险.

4.12 伪造服务器欺骗

客户端 SHOULD 验证服务器身份, 以防连接到伪造服务器.使用带有服务器证书校验的 TLS 可以防止此类攻击.

4.13 密码存储

服务器 SHOULD NOT 以明文形式存储密码, 而应存储密码的散列值.对于 Digest 认证, 服务器可以存储 H(username:realm:password), 这样就能在不保存明文密码的情况下验证客户端.

4.14 小结

Digest 认证比 Basic 认证提供了更好的安全性, 但它并不是完整的安全解决方案.对于需要强安全性的应用, 应使用 TLS 或其他更强的安全机制.尽管如此, 对许多应用来说, Digest 认证仍是一种务实且有用的改进.