只信任值得信任的通道

一般而言,不要信任靠不住的通道上的结果。

在大多数计算机网络中(当然包括Internet),未经证明的传输都是不可靠的。例如,在Internet上可以伪造任意数据包,包括包头的值,所以不要用它们的值作为安全决定的主要依据,除非可以证实。在某些情况下可以断定一个声称来自“内部”的数据包确实来自内部,因为本地防火墙会阻止外部的欺骗,但是被破坏的防火墙、可选择的路径和活动编码使这样的假设都值得怀疑。与之相似,不要假设低端口号(小于1024)是可靠的;在大多数网络中这样的请求可以被伪造或着某个平台会允许使用低端口号的端口。

如果是在实现一个标准,而且继承了不安全的协议(如FTP和RLOGIN),请提供安全的缺省项并明确说明所做的假设。

域名服务器(DNS)被广泛应用在Internet上来维持计算机名与其IP(数字)地址之间的映射。所谓“反向DNS”的技术排除了一些简单的欺骗攻击,并对确定主机名有所帮助。但是,此技术对于确认的决定是不可信的。其问题在于,DNS请求最终会被送到某些可能被攻击者控制的远端系统上。因此,要把DNS的结果当作需要证实的输入来处理,不要靠它来完成严肃的访问控制。

如果要求密码的话,应该力图建立可靠的路径(如要求在登陆前输入一个不可伪造的键值,或者显示诸如发光LED一类的不可伪造的图样)。不幸的是,标准Linux即使对于普通的登录序列都没有一条可靠的路径,而且由于目前普通用户可以改变LED,使得LED目前还不能被用来确认一条可靠的路径。在处理密码时,在可靠的端点之间要进行加密。

任意的email(包括地址的“from”值)也是可以伪造的。使用数字签名是防止这类攻击的一个方法。一个更简单的防范方法是要求email来回传送特别的随机生成值,这通常只是对于签署公开邮件列表一类的低价值事务是可以接受的。

如果需要在不可靠网络上建立一条可信通道,就需要某些密码学服务(最起码是在密码学上安全的一个散列);参见下面的加密算法和协议一节。

注意,在客户/服务器模型中,包括CGI,服务器都必须假定客户可以修改任何值。例如,所谓的“隐藏域”和cookie值可以在被CGI程序接收到之前被客户改变。除非它们被以客户无法伪造的方法标识而且服务器检查该标识,这些值是不可靠的。

本地用户可以控制例程getlogin(3)和ttyname(3)返回的信息,所以不要在用于安全目的时信任它们。

这个问题也适用于引用其它数据的数据。例如,HTML或XML允许通过引用包含可能存储在远端的其它文件(如DTD和格式表单)。但是这些外部引用可能被修改,所以用户可能会得到一个意料之外的不同文档;格式表单可能在关键位置的词语被修改为“清空”,使其显示被涂改,或插入新的文本。外部的DTD可能被修改为阻止文档使用(通过增加破坏合法性的声明)或在文档中插入不同的文本[St. Laurent 2000]。