毫无疑问,世界上存在各种各样的语言,但没有一种是毫无意义的。 | |
哥林多前书 14:10 (NIV) |
存在许多特定于语言的安全问题。其中许多可以总结如下:
在实际可行的前提下,启用所有与您相关的警告和保护机制。对于编译型语言,这包括编译时机制和运行时机制。一般来说,与安全相关的程序应该在启用所有警告的情况下干净地编译。
如果可以使用“安全模式”(例如,限制可执行文件活动的模式),请这样做。许多解释型语言都包含这样的模式。一般来说,不要依赖安全模式来提供绝对的保护;大多数语言的安全模式尚未得到充分的安全分析,当进行分析时,人们通常会发现许多利用它的方法。然而,通过编写代码使其在非安全模式下是安全的,然后再添加安全模式,您最终会得到纵深防御(因为在许多情况下,攻击者必须同时攻破您的应用程序代码和安全模式)。
避免语言中危险和已弃用的操作。这里说的“危险”,指的是难以正确使用的操作。例如,许多语言包含一些“神奇”的机制或函数,也就是说,它们试图使用启发式方法来推断“正确”的做法——一般来说,您应该避免它们,因为攻击者可能能够利用这种启发式方法,并做出一些危险的事情,而不是预期的操作。一个常见的错误是“差一”错误,其中边界偏差了一个单位,有时这些错误会导致可利用的漏洞。一般来说,编写代码的方式应尽量减少“差一”错误的发生。如果语言中有标准约定(例如,用于编写循环),请使用它们。
确保语言的基础设施(例如,运行时库)可用且安全。
自动进行垃圾回收字符串的语言应格外小心,立即擦除秘密数据(特别是密钥和密码)。
精确了解您正在使用的操作的语义。在文档中查找每个操作的语义。除非您确定返回值不相关,否则不要忽略它们。不要忽略“有符号”和“无符号”值之间的差异。这在不支持异常的语言(如 C)中尤其困难,但事实就是如此。