如何在C++函数中分析,查找和修复安全漏洞?

Sqa*_*ndr 1 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;
    }
Run Code Online (Sandbox Code Playgroud)

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

Yak*_*ont 5

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

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

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

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

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

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

安全必须有多安全?通常,安全代码不容易编写.这就是为什么编写加密系统的第一条规则是"不要".

  1. 摆脱所有手动缓冲管理.
  2. 在静态断言,动态断言和注释中包含正式证明,即缓冲区大小的算法没有缺陷.
  3. 包括每个被调用函数的正式描述,并包括证明您的正式描述准确的原因.为每个被调用函数包含单元测试,以验证它们是否按照您声称的方式执行,并以预期方式失败.
  4. 永远不要取消引用指针或索引缓冲区而不进行检查和形式正确的形式证明.
  5. 不要做任何像前处理宏一样愚蠢的事情.找到一种方法来确保您编写的代码是编译的代码:必须在您正在编写的标记不是读取的标记的环境中进行证明是毫无意义的.
  6. 验证函数可以返回的每个可能值.即,recv - 你检查0或-1.如果它返回-2或 - (2 ^ 31)会发生什么?保证不会发生?然后证明一下.
  7. 找一个关于这个主题的实际专家,让他们告诉你想做什么,或付钱给他们.(我不是这方面的专家)

完成所有这些后,您将需要攻击您的代码并尝试打破它.

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