如何分析,发现&修复C ++函数中的安全漏洞?

时间:2012-11-29 14:08:31

标签: c++ security

作为一个工作示例,我们可以处理以下代码:

    #include <sys/socket.h>

    #define size_t   SOCKET

    int receive_socket_data(SOCKET sock,//socket representing remote connection
                            unsigned long& version_number,//validPtr->version #
                            unsigned long& message_size,//validPtr->sizeof packet
                            char*& buf // where to copy data from packet
                           )
    {
       int nlen = 0;
       buf = NULL;

       // Receive version_number from the packet
       nlen = recv(sock, (char*) &version_number, sizeof(version_number), 0);
       if (nlen == 0 || nlen == -1) return ERROR_RECEIVING;
       version_number = ntohl(version_number);

       // Receive message_size from the entire packet 
       // (ulong + ulong + sizeof data)
       nlen = recv(sock, (char*) &message_size, sizeof(message_size), 0);
       if (nlen == 0 || nlen == -1) return ERROR_RECEIVING;
       message_size = ntohl(message_size);
       // Allocate a buffer to copy the data part of the packet
       buf = new char[message_size + 1 - 2 * sizeof(unsigned long)];
       buf[message_size - 2 * sizeof(unsigned long)] = '\0';

      // Copy the data part from the packet to the buffer
      if (recv(sock, (char*) buf, message_size-2*sizeof(unsigned long), 0) == -1)
         return ERROR_RECEIVING;

      return SUCCESS_RECEIVING;
    }

例如,我想到的是操作员 new 可能引发的错误。
我不确定数组的索引计算是否也会导致问题。

1 个答案:

答案 0 :(得分:5)

一种可以帮助确定功能的方法是安全的,包括证明和测试以及防御性编码和审查与体验。

防御性编码,因为任意代码不值得分析。使您的代码更易于分析和更安全,然后分析问题。您无法分析任意程序。甚至那些在理论上可以分析的东西也会遇到很多困难。

证明,正如您的功能正确的正式证据一样。这需要完全理解和规范代码与之交互的所有内容。请注意,防御性编码和简化代码使这有点可能。

测试,因为证明仅适用于您对代码所做事情的了解。你的代码模型可能不完整 - 哎呀,我甚至会说它肯定是不完整的。你没有一个模型,说明当前未知物理如何导致代码在你的代码运行的每个硬件中翻转,这是一个模型如何不完整的荒谬例子。几乎可以肯定,你的代码模型不完整的方式会更加荒谬。

回顾一下,因为会有一些你没有想过的事情,并且让更多有能力的人相信你的代码是正确的可以增加你不会错过任何东西的机会。

经验,因为知道在哪里集中注意力是很重要的。经验是记住你过去如何搞砸,或亲眼目睹其他人这样做。

安全必须有多安全?通常,安全代码不容易编写。这就是编写加密系统的第一条规则是“不要”。

  1. 摆脱所有手动缓冲管理。
  2. 包括正式证明,静态断言,动态断言和评论,你的 缓冲区大小算术没有缺陷。
  3. 包括正式 描述每个被称为函数的功能,并包括证据 为什么你的正式描述是准确的。包括单元测试 每个被称为函数,验证他们做了你声称他们做的事情, 并以预期的方式失败。
  4. 永远不要取消引用指针或 索引没有检查的缓冲区和正式证据 良好的。
  5. 不要做任何像前处理器一样愚蠢的事情。 找到一种方法来确保您编写的代码是代码 编译:必须在一个环境中进行证明 你正在写的代币不是没有被读到的东西。
  6. 验证函数可以返回的每个可能值。即,recv - 检查0或-1。如果它返回-2或 - (2 ^ 31)会发生什么?保证没有 即将发生?然后证明一下。
  7. 找一位关于这个主题的实际专家,让他们告诉你想做或付钱 他们这样做。 (我不是这方面的专家)
  8. 完成所有这些操作后,您将需要攻击您的代码并尝试破解它。

    你会希望别人做同样的事情。