我们在输入校验攻击的讨论中已经介绍了多种对策。但是,重申阻止这些攻击的几个关键点仍很重要:
·使用客户端校验是为了性能而不是安全。客户端输入校验机制避免无害的输入错误和打字错误到达服务器。这种先发制人的校验步骤能够避免无意的错误数据到达服务器,降低了服务器的负载。恶意的用户能够简单地绕过客户端校验控制,所以它们应该始终得到服务器端控制的补充。
·规范化输入值。许多攻击具有几十种基于字符集和十六进制表现的替代编码。输入数据在应用安全和校验检查之前应该是规范化的。否则,编码的载荷可能仅仅通过一个过滤器,在稍后的步骤中被解码为恶意的载荷。这个步骤还包括规范化文件和路径名的措施。
·应用服务器端输入校验。所有来自Web浏览器的数据可能用任意内容修改。因此,正确的输入校验必须在服务器完成,在服务器上不可能绕过校验功能。
·限制数据类型。应用不应该处理不符合基本类型、格式和长度要求的数据。例如,数字值应该赋予数字数据结构,字符串值应该赋予字符串数据结构。此外,美国的邮政编码不仅接受数字值,还可以是精确的5位数字(“ZIP plus four”格式)。
·使用安全字符编码和“输出校验”。用于HTML和SQL格式的字符应该以避免应用错误解读的风格进行编码。例如,以HTML编码方式表示尖括号(<和>)。这种输出校验或者字符重新格式化可以作为对抗HTML注入攻击的附加安全层。即使恶意的载荷成功地通过输入过滤器,其影响也会在输出阶段失效。
·使用白名单和黑名单。使用正则表达式,将数据与授权或者未授权内容匹配。白名单包含可接受内容的模式。黑名单包含不可接受或者恶意内容的模式。依靠白名单一般较容易(也更审慎),因为所有需要阻止的恶意内容集合可能是无限的。而且,你只能创建已知攻击的黑名单模式;新的攻击将避开这种过滤。不过,使用少数恶意结构如用于简单SQL注入和跨站脚本攻击的黑名单仍然是个好主意。
提示 有些字符串有多种引用方法(所谓实体标记):命名、十进制、十六进制和UTF-8(Unicode);更多关于实体编码与浏览器安全关联的内容参见http://code.google.com/p/browsersec/wiki/Part1#HTML_entity_encoding。
·安全地处理错误。不管用什么语言编写应用,错误处理都应该遵循try、catch、finally异常处理概念。Try(尝试)一个操作;Catch(捕捉)操作可能导致的异常;Finally(最终),如果其他方法都失败,则正常退出。一个通用的、有礼貌的不包含任何系统信息的错误页面也是必不可少的。
·要求验证。在某些情况下,配置服务器对目录中所有文件要求目录级的适当验证也是很有意义的。
·使用最少权限访问。用可能的最小权限账户运行Web服务器和任何支持应用。对于容易遭到任意命令执行攻击的应用来说,在不能访问/sbin目录(许多Unix管理员工具存储的位置)的情况下风险低于能够以root用户执行命令的类似应用。