一般来说,只信任来自可信通道的信息(输入或结果)。例如,例程 getlogin(3) 和 ttyname(3) 返回的信息可以被本地用户控制,因此不要为了安全目的而信任它们。
在大多数计算机网络中(当然对于整个互联网而言),任何未经身份验证的传输都是不可信的。例如,通过公共互联网发送的数据包可以在其路径上的任何点被查看和修改,并且可以伪造任意新的数据包。这些伪造的数据包可能包括关于发送者的伪造信息(例如他们的机器 (IP) 地址和端口)或接收者。因此,除非您可以验证它们(例如使用密码学),否则不要将这些值用作安全决策的主要标准。
这意味着,除非在特殊情况下,否则通常不应将 TCP/IP 中用于验证用户的两种旧技术用作唯一的身份验证机制。一种技术是通过检查数据包中的“from”机器地址来限制用户只能从“特定机器”访问;另一种技术是通过要求发送者使用“受信任”的端口号(小于 1024 的数字)来限制访问。问题是在许多环境中,攻击者可以伪造这些值。
在某些环境中,检查这些值(例如,发送机器的 IP 地址和/或端口)可能具有一定的价值,因此在程序中支持这种检查作为一种选项并不是一个坏主意。例如,如果系统在防火墙后面运行,防火墙无法被突破或绕过,并且防火墙阻止声称来自内部的外部数据包,那么您可以声称任何声称来自内部的数据包确实来自内部。请注意,您不能确定数据包实际上来自它声称来自的机器 - 因此您只是在对抗外部威胁,而不是内部威胁。然而,损坏的防火墙、替代路径和移动代码使得即使这些假设也值得怀疑。
问题在于将不可信的信息作为验证某人身份的唯一方法。如果您需要在不可信的网络上建立可信通道,通常您需要某种密码学服务(至少是密码学上安全的哈希)。有关加密算法和协议的更多信息,请参阅第 11.5 节。如果您正在实现标准的且本质上不安全的协议(例如,ftp 和 rlogin),请提供安全的默认值并清楚地记录假设。
域名服务器 (DNS) 在互联网上被广泛使用,以维护计算机名称及其 IP(数字)地址之间的映射。称为“反向 DNS”的技术消除了一些简单的欺骗攻击,并且对于确定主机名很有用。但是,此技术对于身份验证决策不可信。问题是,最终 DNS 请求将最终发送到可能由攻击者控制的某个远程系统。因此,将 DNS 结果视为需要验证的输入,并且不要信任它来进行严格的访问控制。
任意电子邮件(包括地址的“from”值)也可以被伪造。使用数字签名是阻止许多此类攻击的一种方法。一种更容易被阻止的方法是要求来回发送包含特殊随机创建值的电子邮件,但对于低价值的交易(例如注册公共邮件列表)这通常是可以接受的。
请注意,在任何客户端/服务器模型中,包括 CGI,服务器都必须假设客户端(或客户端和服务器之间的某人)可以修改任何值。例如,所谓的“隐藏字段”和 cookie 值可以在被 CGI 程序接收之前被客户端更改。除非采取特殊的预防措施,否则这些是不可信的。例如,可以对隐藏字段进行签名,只要服务器检查签名,客户端就无法伪造签名。隐藏字段也可以使用只有受信任的服务器才能解密的密钥进行加密(后一种方法是 Kerberos 身份验证系统的基本思想)。InfoSec labs 在 http://www.infoseclabs.com/mschff/mschff.htm 上进一步讨论了隐藏字段和应用加密。一般来说,在客户端/服务器模型中,最好将您关心的数据保存在服务器端。同样,不要依赖 HTTP_REFERER 在 CGI 程序中进行身份验证,因为这是由用户的浏览器(而不是 Web 服务器)发送的。
这个问题也适用于引用其他数据的数据。例如,HTML 或 XML 允许您通过引用包含可能远程存储的其他文件(例如,DTD 和样式表)。但是,这些外部引用可能会被修改,以至于用户看到的文档与预期的文档大相径庭;可以修改样式表以“删除”关键位置的单词,破坏其外观或插入新文本。可以修改外部 DTD 以阻止文档的使用(通过添加破坏验证的声明)或将不同的文本插入到文档中 [St. Laurent 2000]。