【问题标题】:How to fix fprintf vulnerability?如何修复 fprintf 漏洞?
【发布时间】:2013-12-10 16:55:02
【问题描述】:

在我的代码中,我使用了 fprintf。我使用漏洞查找器检查代码是否存在漏洞,我得到了:

358: [4] (format) fprintf: 如果格式字符串可以被影响 攻击者,他们可以被利用。使用常量作为格式 规范。

谁能向我解释一下对格式规范使用常量究竟是什么意思? fprintf 有安全版本吗?

【问题讨论】:

  • 确定这是因为代码有一个fprintf(outf, non_constant_string, ...) 而不是fprintf(outf, "some constant string", ...)

标签: c++ c printf


【解决方案1】:

问题在于fprintf 通过检查格式字符串来确定它应该获得多少个参数。如果格式字符串与实际参数不一致,则您的行为未定义,这可能会表现为安全漏洞。

如果提供的字符串会受到程序用户的影响,问题就特别严重,因为他可以专门设计字符串来让你的程序做坏事。

C 标准中没有fprintf 的安全版本。 C++ 流避免了这个问题,代价是没有格式字符串并使用更冗长的语法来指定格式选项。

【讨论】:

  • 如果使用得当,只会稍微冗长一些,而且更加灵活和结构化。
  • @JamesKanze:它们很灵活……除非你想翻译你的程序。考虑一下:fprintf(_"(John took %d apples"), 5) 与此:cout << _("John took ") << 5 << _(" apples")
【解决方案2】:

一个常量字符串,就像在字符串文字中一样。

点赞

fprintf(someFile, "%s", someStringVariable);

并且喜欢

fprintf(someFile, someStringVariable);

【讨论】:

    【解决方案3】:

    表示它要你写:

    fprintf(out, "foo %s", some_string);
    

    而不是你所拥有的,我猜是这样的:

    const char *format = "foo %s";
    
    /* some time later */
    
    fprintf(out, format, some_string);
    

    原因是它担心format 可能来自用户输入或其他东西,恶意用户可能会提供格式foo %s%s%s 以引发他们可能能够利用的未定义行为。

    显然,如果您在 n 不同的格式字符串之间进行选择,所有这些都是代码中的字符串文字并且都使用相同的格式说明符,但是您在运行时选择了哪一个,那么遵循这个建议有点尴尬并且不会使您的代码更安全。但是您可以使用 n 函数而不是 n 字符串,并且每个函数都使用不同的字符串字面量调用 fprintf

    如果您从配置文件中读取格式字符串(这是一种从头开始实现国际化的相当粗略的方法),那么您基本上就没有运气了。 linter 不相信您的翻译器对提供给调用的参数使用正确的格式代码。可以说你也不应该:-)

    【讨论】:

    • 在很多情况下,字符串将来自特定于语言环境的消息文件。 (我认为 GNU 的 gettext 版本会验证格式说明符是否相同,否则,你会被卡住。)
    • @JamesKanze:有趣,我只是在写同样的东西。是的,printf 很想用于 i18n,而且肯定比 iostream 格式更接近于为您解决整个问题。但是,如果您担心这种错误,那就功亏一篑了。
    • 我不确定printf 是否更适合 I18n;这实际上取决于您要翻译的文本类型。 (要获得真正流畅、任意的句子,您需要为每种语言创建一个单独的 DLL。对于简单的错误消息,std::ostream 至少与printf 一样好,并且更易于使用。)
    • @James:一个典型的 i18n 示例(需要格式化:固定邮件当然不需要)类似于邮件合并。您想翻译一个句子,如“谢谢,您的 x 订单将在 前送达”。这可以很容易地配置为包含 printf 格式代码的单个字符串,对于 iostream,它必须是几个单独的部分。词序问题由 printf 的 Posix 扩展处理,使用流相当尴尬。但是,根据翻译人员的不同,翻译文本中的格式可能只是一个初学者。
    • 但是,我巧妙地避免将句子表述为需要复数形式,因此您当然是对的,翻译可能需要比printf 或流格式本身能够提供的更多逻辑.但是对于“以正确的顺序组装正确的位”,这通常足以涵盖大部分工作,printf 是更容易和更有效的 IMO,因为配置文件更好。当然,任何一个都足以编写不使用可变参数的 printf 样式格式化程序。
    猜你喜欢
    • 2021-08-14
    • 1970-01-01
    • 2022-01-17
    • 2021-08-20
    • 2020-02-15
    • 2018-12-24
    • 2019-11-13
    • 2020-09-03
    相关资源
    最近更新 更多