第6章 输入注入攻击

输入校验是Web应用防御的第一道防线。许多漏洞如SQL注入、HTML注入(及其子集跨站脚本)以及详细错误信息都是建立在攻击者向应用注入某种类型的意外或者恶意的输入的基础之上。正确实施的输入校验例程确保了数据处于应用所需要的格式、类型、长度和范围。没有这些检查,应用及其信息的机密性、完整性和可用性就存在风险。想象一下应用的发货地址表单的邮政编码域。没有有效的邮政编码,邮政服务就不能很快地分发邮件。我们知道邮政编码应该仅由数字组成。我们也知道它的长度至少为5位数字,还可以选择5位数字、连字号和附加的4位数字(ZIP plus 4)组成总共10个字符,因此第一个校验例程应该是长度检查。输入是否包含5或10个字符?第二个检查是数据类型。输入是否包含非数字的字符?如果长度为5,那么应该只包含数字。如果长度为10,应该有9个数字,在第5和第6个字符中间有个连字号。这种邮政编码格式的校验将包括确保没有数字之外的字符存在——唯一的例外是第6个位置上的连字号。为了检查输入的范围,我们将校验每个数字是0~9。

因为我们使用的代码集有限,所以可以再增加一个检查,从zip4.usps.com查询已知有效邮政编码的列表,或者列表的离线副本如文本文件或者数据库。这个检查确保了输入在有效的邮政编码集之内,成为更加强大的输入验证形式。例如,12345是属于纽约通用电气公司的有效邮政编码。他们经常收到地址为Santa Claus,North Pole 12345的邮件。但是,00000不是有效的邮政编码;尽管它通过了类型、格式和长度检查,还应该进行这种额外的检查,确定其有效性。本章关注于信任用户提供数据所带来的危险,以及应用不能正确地限制所期望数据类型时可能遭到的攻击。

数据校验可能很复杂,但是它是应用安全的重要基础。应用编程人员必须训练对用户可能输入到表单域中的值的预见性。我们刚刚讨论了如何对邮政编码进行类型、长度、格式和范围检查。这些测试可以以JavaScript编程,放在HTML页面中,通过SSL提供。JavaScript解决方案乍一看很简单,但是仍然是开发人员所犯的最大错误之一。你在接下来的小节中将会看到,客户端输入校验例程可能被绕过,SSL仅能保护Web事务的机密性。换句话说,你不能信任Web浏览器进行所期望的安全检查,加密连接(通过SSL)对提交到应用的数据内容也没有影响。