【问题标题】:Why is vsnprintf safe?为什么 vsnprintf 是安全的?
【发布时间】:2014-09-24 07:44:55
【问题描述】:

我看过这个question 以及这些PDF 的12,这个page 并且非常了解如果我这样做printf(SOME_TEST_STRING) 会发生什么。但是我不明白为什么要确保缓冲区的大小vsnprintfvsprintf 相比变得安全?

【问题讨论】:

    标签: c++ c security memory printf


    【解决方案1】:

    这两种情况会发生什么?

    案例一

    char buf[3];
    vsprint(buf, "%s", args);
    

    案例 2

    char buf[3];
    vsnprint(buf, sizeof buf, "%s", args);
    

    在情况 1 中,如果您要格式化的字符串的长度为 3 或更大,则表示缓冲区溢出,vsprintf 可能会写入内存超出 buf 数组的存储空间,这是未定义的行为,可能会造成破坏/安全问题/崩溃/等等。

    在情况 2. vsnprintf 知道将包含结果的缓冲区有多大,并且它会确保不会超过该缓冲区(而是截断结果以适应 buf )。

    【讨论】:

    • 您对 vs{,n}printf 的调用缺少 buf 参数。
    • @nos,它与格式字符串漏洞有什么关系?维基百科:en.wikipedia.org/wiki/Uncontrolled_format_string
    • @user1343318 没有,那是另一类潜在问题。
    • @nos 很好 - 它在很小的程度上......对于只生成过长输出的格式字符串更安全(例如,通过指定过大的字段宽度或精度,只是有更多的常量文本,或者使用像 GCCs 这样的扩展来多次打印相同的参数)。尽管如此,“n”版本并不能防止替换需要的格式字符串,例如一个指向 ASCIIZ 字符串的指针,实际上被赋予了一个数字。 (+1 可提供动手解释。)
    【解决方案2】:

    这是因为vsnprintf 有一个额外的size_t count 参数,而vsprintf(和其他非n *sprintf 方法)没有。实现使用它来确保它写入缓冲区的数据不会跑完。

    超出缓冲区末尾的数据可能会导致数据损坏,或者在被恶意利用时可用作buffer overrun 攻击。

    【讨论】:

      【解决方案3】:

      vsnprintf() 中的“n”表示需要输出字符串的最大大小以避免缓冲区溢出。这使其免受缓冲区溢出的影响,但如果格式字符串来自未经处理的用户输入,则不会使其安全。如果你的用户给你一个巨大的格式字符串,你会避免溢出目标字符串,但是如果用户给你%s并且你没有在编译时在参数列表中传递一个C字符串,你仍然会留下未定义的行为。

      【讨论】:

        【解决方案4】:

        我不确定问题是什么,因为您的问题基本上已经包含答案了。

        通过将缓冲区大小传递给vsnprintf,您可以向该函数提供有关缓冲区大小的信息。该函数现在知道缓冲区在哪里结束,并且可以确保它不会写入超过缓冲区的末尾。

        vsprintf 没有缓冲区大小的信息,所以它不知道缓冲区在哪里结束,也无法防止缓冲区溢出。

        【讨论】:

          猜你喜欢
          • 2014-09-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-04-07
          • 2023-03-30
          • 2019-10-27
          • 2023-03-28
          • 2011-08-25
          相关资源
          最近更新 更多