在给定的代码中查找安全问题

有人可以告诉我一个在给定的代码中查找安全漏洞的方法。 例如:在给定的套接字程序中。 任何好的例子或良好的书build议是值得欢迎的。

感谢和问候,

像老鼠

在这个类别中最低的悬挂水果将是简单地搜索通常被滥用或难以安全使用的功能的来源,例如:

  • 的strcpy
  • strcat的
  • 的sprintf
  • 得到

然后开始查看那些不是继承太糟糕,但可能被滥用的。 特别是任何写入缓冲区的东西,如果被滥用,都可能是危险的。

  • 的memcpy
  • 的memmove
  • 的recv /阅读
  • 发送/写
  • 整个printf家族应该总是有一个格式字符串的常量

注意:所有这些( gets除外)都可以正确使用,所以不要因为使用函数而认为它是一个缺陷,而应该看看它是如何使用的。 还要注意gets 总是一个缺陷。

注2:这个清单并不详尽,对通常滥用的功能以及如何避免它们做一点研究。

至于工具,我推荐像valgrind和夹板

Evan的答案中没有涉及的一个主要话题是整数溢出。 这里有些例子:

 wchar_t *towcs(const char *s) { size_t l = strlen(s)+1; mbstate_t mbs = {0}; wchar_t *w = malloc(l*sizeof *w), *w2; if (!w || (l=mbsrtowcs(w, (char **)&s, l, &st))==-1) { free(w); return 0; } return (w2=realloc(w, l*sizeof *w)) ? w2 : w; } 

在这里,一个巨大的字符串(在32位上大于1gig)将会乘以大小(我假设是4)溢出,导致一个微小的分配和随后的写入超过它的结尾。

另一个更常见的例子:

 uint32_t cnt; fread(&cnt, 1, 4, f); cnt=ntohl(cnt); struct record *buf = malloc(cnt * sizeof *buf); 

这种类型的代码在读取文件/网络数据时会变得相当多,而且会受到同样的溢出。

基本上,需要检查从不可信源获取的值(最终将用作分配大小/数组偏移量)的任何算术运算。 你可以用廉价的方式来实现(对读取值施加任意的限制,使其远远超出可能溢出的范围,或者你可以在每一步测试溢出:而不是:

 foo = malloc((x+1)*sizeof *foo); 

你需要做的是:

 if (x<=SIZE_MAX-1 && x+1<=SIZE_MAX/sizeof *foo) foo = malloc((x+1)*sizeof *foo); else goto error; 

malloc / realloc在其参数中使用算术运算符的简单grep会发现很多这样的错误(但不是溢出已经发生在几行之上的错误等)。

这里有一个书的建议: 写安全代码 。 不仅演示如何编写安全代码,还演示了暴露安全漏洞的常见陷阱和实践。 它有点过时了(我的副本说它是在2002年出版的),但是它教导的安全概念在8年之后依然适用。

一些你可以留意的源代码构造是:

  • 不做边界检查的函数。 埃文盖得很好。
  • 输入验证和消毒,或缺乏。
  • NULL指针解引用
  • fork()s,execve()s,pipe()s,system()用非静态参数调用(或者更糟糕的是,用户输入)。
  • 对象之间共享的线程与不适当的存储持续时间(自动变量的指针,甚至线程本地存储中的“死”对象)。
  • 在处理文件操作时,确保函数的返回结果使用正确的变量类型。 确保他们检查错误。 不要假设实现 – 创建文件的权限,文件名的唯一性等。
  • 应避免不良来源(加密,通信等)。
  • 无论如何,简单或明显的错误(可能是由于粗心大意)应该被修正。 你永远不知道什么是可利用的,除非是这样。

另外, 数据是否受到保护 ? 那么,如果你不在乎,那很好。 🙂

一些您可以考虑的工具是:

  • valgrind:暴露内存漏洞,在大型应用程序中通常是关键的。
  • 夹板:静态检查器
  • 模糊框架
  • RATS :一个免费的开源工具。 其作者的公司被Fortify收购。

我参加了一个安全课,我们使用了一个名为Fortify 360的商业产品,它对C ++代码进行了静态分析。 我们使用旧版本的OpenSSL运行它,发现了大量的东西,并提供了纠正这些缺陷的指导(顺便说一下,最新版本的OpenSSL已经解决了这个问题)。

无论如何,这是一个有用的商业工具。

一些OpenBSD的人刚刚发表了关于他们的编码实践的介绍 。