代码之家  ›  专栏  ›  技术社区  ›  Ethan Heilman

编写安全C和安全C习惯用法

  •  41
  • Ethan Heilman  · 技术社区  · 16 年前

    “普通人不想自由。他只是想安全。”- H. L. Menken

    我正在尝试编写非常安全的C。下面我列出了我使用的一些技术,并询问它们是否像我认为的那样安全。请不要犹豫,撕碎我的代码/成见。任何发现哪怕是最微不足道的弱点或教会我一个新想法的答案都将是错误的 .

    根据 GNU C Programming Tutorial

    getline函数将 自动放大图像块 根据需要,通过realloc存储 太安全了请注意,getline可以 安全地处理您的输入行,无需 不管它有多长。

    在所有输入下 ,防止 buffer overflow 从流中读取时发生。

    Malloc在失败时返回Null:

    如果malloc遇到错误,malloc将返回空指针。这会带来安全风险,因为仍然可以对空(0x0)指针应用指针算法,因此wikipedia recommends

    /* Allocate space for an array with ten elements of type int. */
    int *ptr = (int*)malloc(10 * sizeof (int));
    if (ptr == NULL) {
        /* Memory could not be allocated, the program should handle 
           the error here as appropriate. */
    } 
    

    使用时 sscanf 我习惯于将要提取的字符串的大小分配给输入字符串的大小,希望避免溢出的可能性。例如:

    const char *inputStr = "a01234b4567c";
    const char *formatStr = "a%[0-9]b%[0-9]c":
    char *str1[strlen(inputStr)];
    char *str2[strlen(inputStr)];
    
    sscanf(inputStr, formatStr, str1, str2);
    

    所有可能的值 inputStr是否会导致缓冲区溢出?

    一般问题:

    虽然我已经发布了大量的问题,但我并不期望有人能回答所有的问题。这些问题更多的是指导我寻找的答案。我真的很想学习安全C心态。

    • 经常检查 ?
    • 如何以可测试性或可证明正确的方式强制实施约束?
    • 有没有推荐的C语言静态/动态分析技术或工具?
    • 您遵循什么样的安全C实践,以及如何向自己和他人证明它们的合理性?

    许多资源都是从答案中借来的。

    7 回复  |  直到 14 年前
        1
  •  4
  •   Jonathan Leffler    6 年前
    1. 从溪流中读书

      事实是 getline() “将根据需要自动扩大内存块”意味着这可能被用作拒绝服务攻击,因为生成的输入太长,会耗尽进程(或更糟的是,系统!)的可用内存,这将是微不足道的。一旦出现内存不足情况,其他漏洞也可能发挥作用。代码在低/无内存中的行为很少是好的,而且很难预测。IMHO为所有内容设置合理的上限更安全,尤其是在安全敏感的应用程序中。

      getline() 只给你一个缓冲;它不保证缓冲区的内容(因为安全性完全取决于应用程序)。因此,清除输入仍然是处理和验证用户数据的重要部分。

    2. 我倾向于使用正则表达式库,并为用户数据定义非常狭义的regexp,而不是使用 sscanf . 这样,您可以在输入时执行大量验证。

    3. 一般性意见

      • 可以使用模糊工具生成随机输入(有效和无效),用于测试输入处理
      • 缓冲区管理至关重要:缓冲区溢出、下溢、内存不足
      • 二进制文件可能会被操纵,以将无效值或过大的值注入到标题中,因此文件格式代码必须坚如磐石,并且不能假设二进制数据是有效的
      • 临时文件通常是安全问题的根源,必须小心管理
      • 作为一般原则,我建议有明确定义的界面,其中用户数据(或来自应用程序外部的任何数据)在处理、消毒和验证之前被认为是无效和有害的,并且是用户数据进入应用程序的唯一途径
        2
  •  7
  •   nont    12 年前

    我认为你的sscanf例子是错误的。这样使用时,它仍然会溢出。

    void main(int argc, char **argv)
    {
      char buf[256];
      sscanf(argv[0], "%255s", &buf);
    }
    

    Take a look at this IBM dev article about protecting against buffer overflows.

        3
  •  4
  •   Jonathan Leffler    7 年前

    一个开始研究这个的好地方是 David Wheeler's excellent secure coding site .

    Secure Programming for Linux and Unix HOWTO “是定期更新的优秀资源。

    你可能还想看看他出色的静态分析仪 FlawFinder

    “有工具的傻瓜还是傻瓜” . 认为分析工具(如Failfinder)是安全培训和知识的替代品是错误的

    我个人使用David的资源已经好几年了,我发现它们非常优秀。

        5
  •  1
  •   Pascal Cuoq    16 年前

    Yannick Moy在博士和博士期间为C开发了Hoare/Floyd最弱的前提系统 applied it to the CERT managed strings library . 他发现了一些虫子(见他的回忆录第197页)。好消息是图书馆现在对他的工作更安全了。

        6
  •  1
  •   Jackson    16 年前

    你也可以看看Les Hatton的网站 here 更安全的C 你可以从亚马逊那里得到。

        7
  •  0
  •   Alok Singhal    16 年前

    不要使用 gets() fgets() . 使用

    char buf[N];
    ...
    if (fgets(buf, sizeof buf, fp) != NULL)
    

    如果您决定更改 buf

    #define N whatever
    char buf[N];
    if (fgets(buf, N, fp) != NULL)
    

    缓冲器


    Check the return value of fclose() .


    推荐文章