使用fgets()和推荐的解决方案可能存在安全漏洞?

时间:2016-09-06 14:03:32

标签: c fgets buffer-overflow

我正在使用coverity的SA工具来处理错误。由于使用了fgets(),我收到了一些错误。这是一个片段(SA错误显示为注释) -

FILE *fp;
char my_pubkey[1024];

fp = fopen("publickey.pub", "r");

//tainted_string_argument: fgets taints variable my_pubkey.
if (!fgets(my_pubkey, sizeof(my_pubkey), fp)) {
    printf("failure to read pub key file");
    goto error;
}

//tainted_string: Passing tainted string my_pubkey to a parameter that cannot accept a tainted format string.
if (fprintf(fp, my_pubkey) != strlen(my_pubkey)) {
    printf ("failure to write pub key in key file");
    goto error; 
}

在我的调查中,一些报告建议使用getline()代替,但真的需要吗?如果这是一个有效的问题,可能是什么漏洞?什么是最好的解决方案?

编辑:如果这是误报,为什么呢?什么时候它可以成为一个实际问题?

2 个答案:

答案 0 :(得分:3)

假设密钥的文本最多为1024个可打印字符,则代码应使用char my_pubkey[1024+ 2];\n\0腾出空间。

如果密钥是二进制文件,则以文本模式打开是错误的,并且使用fgets()失败,因为它读取。最好使用fgetc()。也不要使用strlen(),因为代码不处理字符串

此外,应最小化内部缓冲区长度,以减少在陈旧缓冲区中浮动的密钥副本。请参阅setbuf()setvbuf()

fprintf()将字符串解释为格式说明符字符串@Eugene Sh.%的存在引入了潜在的UB。最好使用%s

if (fprintf(fp, "%s", my_pubkey) ...

答案 1 :(得分:3)

Coverity似乎抱怨my_pubkey正在从外部来源获得价值。因此它“受到污染”,因为程序本身并不能确信所收到的数据是正确的还是有效的。这是您可能只需要管理的真正关注点。我不希望使用getline()代替fgets()来改变它 - 这将是解决涉及不同函数(gets())的不同问题的一种方法。

Coverity 抱怨您将受污染的字符串作为格式字符串传递给printf() 。这也是真正的安全问题,甚至可能是一个简单的正确功能问题。将外部提供的字符串用作[f]printf()格式字符串是一个非常糟糕的主意,因为这样的字符串可能包含printf()字段代码。您应该提供明确的格式:

fprintf(fp, "%s", my_pubkey)

或使用fputs()

fputs(my_pubkey, fp)