C++ 如何修复fprintf漏洞?

C++ 如何修复fprintf漏洞?,c++,c,printf,C++,C,Printf,在我的代码中,我使用了fprintf。我使用Failfinder检查代码的漏洞,我得到: 358:[4](格式)fprintf:如果格式字符串受 如果是攻击者,则可以利用它们。为格式使用一个常量 规格 有人能给我解释一下,在格式规范中使用常量实际上意味着什么吗?是否有安全版本的fprintf?常量字符串,如字符串文字 喜欢 fprintf(someFile, "%s", someStringVariable); 和不一样 fprintf(someFile, someStringVariable

在我的代码中,我使用了fprintf。我使用Failfinder检查代码的漏洞,我得到:

358:[4](格式)
fprintf
:如果格式字符串受 如果是攻击者,则可以利用它们。为格式使用一个常量 规格


有人能给我解释一下,在格式规范中使用常量实际上意味着什么吗?是否有安全版本的
fprintf

常量字符串,如字符串文字

喜欢

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

fprintf(someFile, someStringVariable);

这意味着它想让你写:

fprintf(out, "foo %s", some_string);
而不是你所拥有的,我猜是这样的:

const char *format = "foo %s";

/* some time later */

fprintf(out, format, some_string);
原因是担心
format
可能来自用户输入或其他信息,恶意用户可能会提供格式
foo%s%s
,以引发他们可能利用的未定义行为

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


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

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

如果提供的字符串可能会受到程序用户的影响,那么问题尤其严重,因为用户可以专门设计字符串,使程序做坏事


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

在很多情况下,字符串将从特定于区域的消息文件中出来。(我认为GNU版本的
gettext
将验证格式说明符是否相同,但在其他方面,您就被卡住了。)@JamesKanze:有趣的是,我刚刚写了同样的东西。是的,
printf
很容易用于i18n,当然比iostream格式更接近于解决整个问题。但是,如果你担心这种错误,那么它就是不够。我不确定
printf
是否更适合I18n;这取决于你要翻译的文本类型。(要获得真正流畅、任意的句子,每种语言都需要一个单独的DLL。对于简单的错误消息,
std::ostream
至少与
printf
一样好,而且更易于使用。)@James:i18n的一个典型示例(需要格式化:固定消息当然不需要)类似于邮件合并。您需要翻译一句话,如“谢谢您,您的x订单将由”交付。这可以很容易地配置为包含printf格式代码的单个字符串,对于iostream来说,它必须是几个独立的部分。词序问题是通过Posix对
printf
的扩展来处理的,而且使用streams相当麻烦。不过,根据译者的不同,翻译文本中的格式可能只是一个非初学者。然而,我巧妙地避免了将句子措辞为要求复数,因此您当然是对的,翻译可能需要比
printf
或流格式本身能够提供的更多逻辑。但是对于“以正确的顺序组装正确的位”,这通常足以覆盖大部分工作,
printf
在我看来更容易、更有效,因为配置文件更好。当然,任何一种格式都足以编写一个不使用varargs的printf样式的格式化程序。正确使用时只会稍微详细一点,而且更加灵活和结构化。@JamesKanze:它们非常灵活。。。除非你想翻译你的程序。考虑这一点:<代码> fPrtuf(“约翰拿走了%D苹果”),5) VS:<代码> CUT确定这是因为代码有一个<代码> fPrtuf(Outf,No.CistangthString,…)< />代码,而不是<代码> fPrtuf(Outf,“某些常量字符串”,…)< />代码。