让我们在这里说清楚。
- 不安全是上下文问题,而不是“使用”特定功能的情况。如果我在作为用户运行的进程上不安全地使用 memcpy,几乎没有丢失,没有 setuid 或任何此类标志,我能做的“最糟糕的”是为该用户获取一个 shell 并从那里开始。为了实现特权升级,您需要攻击一些您可以欺骗的东西,从而为您提供更高的特权。
- C/C++ 不是“危险工具”。它们是工具。插入关于危险的 DIY 工具的适当比喻。
事实是,正如 Rook 已经说过的,C/C++ 和其他类似的其他机器编译语言在世界上占有一席之地。它们用于构建快速系统、操作系统、系统服务等。它们使您能够根据需要管理自己的内存。你在掌控之中。
除非您引入某种形式的自动内存管理,否则如果您已经超过了分配的内存,就无法真正解决问题。所以,好吧,让我们介绍一个容器。现在需要检查每个内存访问调用。它是否在该特定功能的范围内?有多少物体指向它?在哪里,他们的范围是什么?我可以有原始参考范围之外的指针吗?如果可以,我该如何跟踪它?很快,您就拥有了一台虚拟机,因此您拥有了一种托管语言。
此外,正如在 StackOverflow 上所展示memcpy_s
的那样,无论如何都可以以不安全的方式调用。它并没有真正解决根本问题,只是让犯错变得更加困难。
这就是区别。C/C++ 是花哨的汇编程序,具有执行任何操作所需的所有功能。Java/Python 等以一定的代价保护您免受伤害:速度和功能。
您在今天的过程中反复说过(我也遵循了 SO 版本),您仍然没有得到关于如何在 Linux 等其他系统上使用 C/C++ 安全开发的答案。首先,我几乎习惯性地使用 VS2005/2008 设置CRT_SECURE_NO_DEPRECATE
,但无论如何,这里有一些你可以做的事情:
- 你问 StackOverflow。你记笔记、学习、阅读和重读。
- 您的编译器(大部分)是您的朋友。听这个。使用警告。把它们变成错误。所以
cl /W4
和gcc -Wall -Werror -pedantic -std=c99
。是的,就错误消息而言,它是 OTT。但是如果你不能解释每一个并证明你为什么忽略它,你就不会理解你自己的代码。
- 检查您的内存分配。
valgrind
的默认调用检查您的分配和释放意味着您不会丢失内存。如果您有内存泄漏,那么您对代码的考虑还不够。这是一个好兆头,你有一个错误,无效的边界检查等。
- 再次使用
valgrind
。我刚刚拿起了这个,但是看,valgrind 中有一个实验性的过度/不足检查器。会告诉您,例如,您是否在堆栈末尾崩溃(可能,因为这是分配大多数局部变量的地方)或在brk()
'd 堆之外。
- 使用
splint
又名安全 lint,记下它的输出。同样,如果您无法解释它给出的任何输出,那么您就无法理解您的代码。
内心消化 C 安全编码标准。这里特别相关:
- 如果您使用的是 C++,请使用
std::string
and boost::shared_ptr
(以及相关的;使用适当的)。除了与 C 的交互之外,在 C++中绝对没有参数是malloc'ing
和ing 字符串。即便如此,请将操作留给 C++。memcpy
string.c_str()
- 尽可能动态链接。如果您已将任何第 3 方代码静态链接到您的应用程序中并且结果存在安全问题,那么您也遇到了问题,您也必须重新分发您的图像。共享对象不仅通常更方便,而且默认情况下您还可以获得安全更新。我知道有些情况你不能,这就是为什么我说“在可能的情况下”。
- 将此构建到您的开发周期中。
- 希望你没有错过什么。
- 跟上可能相关的相关安全社区更新。
- 善待安全社区。确认安全漏洞,采取措施修复它们。如果值得运行,所有代码都有(或有)错误。就那么简单。
归根结底,我认为“安全”功能无法解决问题。我认为问题可以通过使用一些不错的工具、一个适当的开发过程来解决,该过程拒绝来自关键版本(后期测试版和发布候选版本)的糟糕代码,最后是对良好实践/当前问题的认识。
最后,memcpy_s
它不是 C99 标准的一部分。它是 C 库的扩展(不是核心的一部分),因此不能保证在我正在使用的平台上。memcpy
是。对于需要跨平台编译的软件项目,这可能是使用哪个功能的决定因素。