在我的代码中,我使用了fprintf。我使用flawfinder检查代码中的漏洞,我得到了:
358:[4](格式)
fprintf
:如果格式字符串受到影响 攻击者,他们可以被剥削。对格式使用常量 说明书
有人可以向我解释格式规范使用常量实际意味着什么?是否有fprintf
的安全版本?
答案 0 :(得分:7)
问题是fprintf
通过检查格式字符串来确定应该获得多少个参数。如果格式字符串与实际参数不一致,则您有未定义的行为,这可能表现为安全漏洞。
如果提供的字符串可能会受到程序用户的影响,那么问题尤其严重,因为他可以专门设计字符串以使程序做坏事。
C标准中没有fprintf
的安全版本。 C ++流避免了这个问题,代价是没有格式字符串,并且使用了更详细的语法来指定格式化选项。
答案 1 :(得分:6)
一个常量字符串,如字符串文字。
喜欢
fprintf(someFile, "%s", someStringVariable);
和 不 喜欢
fprintf(someFile, someStringVariable);
答案 2 :(得分: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
以引发他们可能利用的未定义行为。< / p>
显然,如果您在n
个不同的格式字符串之间进行选择,所有这些字符串都是代码中的字符串文字,并且都使用相同的格式说明符,但是您在运行时选择哪一个,然后遵循此建议是有点尴尬,不会让你的代码更安全。但是您可以使用n
个函数而不是n
个字符串,并且每个函数都使用不同的字符串文字调用fprintf
。
如果你正在从配置文件中读取格式字符串(这是从头开始实现国际化的一种相当粗略的方式)那么你基本上没有运气。 linter不信任您的翻译人员使用正确的格式代码来提供给调用的参数。可以说你也不应该: - )