开发团队的所有成员应当清楚常见的编程错误及原因和减少错误的方法,以及这些内容对当前软件项目的适用性。减少软件项目安全漏洞的关键在于开发团队必须遵循安全编码的最佳方法。
验证输入并对输入进行编码
攻击者常常针对应用程序发动劫持攻击。这种攻击可以采用C语言中的格式字符串的形式,或者采用Web脚本语言中的跨站脚本攻击。如果一个Web应用程序可以接收用户输入,并将用户输入的内容输出或转发给某个可信的功能,它就易于遭受攻击。因而,正确地验证输入以确保它满足应用程序的要求(例如,通过验证用户的输入达到某个长度并且不包含“特定的”HTML字符,并且可以安全地处理任何非法的输入。)如果输入验证允许潜在的恶意字符(例如,在Web应用程序中出现“<”),后果就不容乐观。此时,应用程序就应当对这些字符编码,使其不会被其它功能或依赖它的应用程序误解。
白名单是很受欢迎的输入验证方法,它可以验证那些遵循了确定的可接受参数的输入并拒绝不遵循这些参数的输入。白名单验证已被证明可以高效地过滤与未知攻击有关的输入模式。相比较而言,黑名单这种方法可以验证输入是否与某些确定的与可疑恶意输入有关的不可接受的参数相匹配。黑名单可以接受并未明确标识为“恶意”的所有输入,它在防护未知攻击方面没有什么用处。但它可以清理某些恶意的输入。此外,黑名单还可用来临时过滤与零日漏洞的有关攻击。如果要使用黑名单功能,IT能够将输入转换为标准形式非常重要。IT应当结合使用白名单和黑名单,但应首先用黑名单。
在检测到恶意的输入后,就需要对其管理。最好的方法是简单地拒绝恶意输入,而不是试图“净化”它。然而,净化有时是必要的。在这种情况下,所有被净化的数据都应当被重新发送,以便于用白名单验证确保其有效性。
测试情形应当包括合法数据和非法数据的提交两个方面,而测试者应当重视似是而非(输入验证拒绝了合法输入)和“似非而是”(输入验证接受了非法输入)。如果客户端验证是作为第一层过滤而实施的,还应当测试其JavaScript情况(JavaScript在解析普通的表达式时与服务器的验证引擎略有不同,而且会在客户端生成似是而非的问题,并在服务器端产生“似非而是”的问题)。最后,测试者应当在关闭服务器端和客户端验证的情况下运行应用程序。这样做会揭示接受非法数据如何影响其它应用程序层,并会暴露漏洞。在对输入验证实施了集中化的架构中,测试还可以揭示是否在系统的其它点上需要其它的验证。必须确保验证不能被绕过。在客户端/服务器的设计中,服务器的验证是保护服务器的唯一验证。
标准化
在表达式遵循标准格式时,它就是标准化的。标准化就是对一个表达式进行重新格式化使其满足标准格式。标准化可以确保表达式能够被转化为标准格式。在验证之前对表达式进行标准化可以减少绕过过滤器的风险。
本地化
本地化包括为使一个程序在不同国家使用而创建的程序变种。开发者应当为软件的每一个本地化变种开发误用/滥用的实例和攻击模式。由于某些语言中的源字符串的长度更长,在不同字符编码中字符串长度可用字节或字符来表达,以及由于从一种编码转换到另外一种编码会导致缓冲区大小的增加,所以,与本地程序变种相关的主要问题都与产生缓冲区漏洞的可能性有关。
分析器
开发团队应当使用分析器来管理编码和转换等方面。现在有许多编码方案,如十六进制编码、Unicode编码、URL编码、基于语言的字符编码等。这里存在许多困难,其中之一就是这些编码可以通过双重编码的形式一起使用,从而使得标准化过程变得很困难。应用程序中内置的一系列分析器,如Web服务器和应用程序服务器可以减少这种困难。剩下的就是输入验证问题了,如果这是一种基于模式的验证方法,在分析器将输入变成标准形式之后才进行检查就至关重要了。这可能是一个架构上的挑战,并需要谨慎管理。
软件开发中的使用安全编码其他方法:软件开发:安全编码的九个最佳方法(二)