强化:C 语言中的路径操作 - 白名单实现不起作用 - fopen 问题



大家好,我有一个强化问题"路径操作"它由 fopen 使用产生。根据 fortify 的说法,我可以实施一个白名单来修复它,所以有我的白名单验证器:

white_list.c

#define BUFF_WHITE_LIST_FILE 200
const char *white_list_validator( char *variable )
{
FILE *fp = NULL;
ssize_t read;
char * line = NULL;
size_t len = 0;
char white_list_file_buff[BUFF_WHITE_LIST_FILE];
if ( __secure_getenv("WHITE_LIST_FILE") == NULL )
return NULL;
else
{
strncpy(white_list_file_buff,
__secure_getenv("WHITE_LIST_FILE"),sizeof(white_list_file_buff)-1);
fp = fopen(white_list_file_buff,"r");
if ( fp == NULL )
return NULL;
else
{
while( (read = getline(&line, &len, fp)) != -1 )
{
if ( strncmp(line,variable,read - 1) == 0 ){
fclose(fp);
return variable;
}
}
fclose(fp);
}
if(line)
free(line);
}
return NULL;
}

如果在 White.list (*) 中找不到变量,则返回 NULL,如果找到它,则返回指向 char 的指针

int main( int argc, char **argv ) {
FILE *fp = NULL;
char mrd[50]={0};
const char *ptr = white_list_validator(argv[1]);
if ( argv[1] == NULL )
return -1;
if(ptr==NULL)
return -1;
else
{
strncpy(mrd,ptr,sizeof(mrd)-1);
printf("variables found : %sn",mrd);
fp = fopen(mrd,"w");  <------   SINK
if ( fp == NULL ){
printf("line 22n");
exit(1);
}
fprintf(fp, "%s %s %s %d", "We", "are", "in", 2077);
fclose(fp);
}
return 0;
}

但是当我运行强化报告时,fopen中出现了一个操纵路径漏洞,我不知道为什么.您可以在代码中看到,在此之前设法使用 fopen 进行文件验证white_list_validator。 所以有人知道为什么它不能正常工作吗?

注(*) : 导出WHITE_LIST_FILE=/路径/白名单

猫白名单

测试1

测试2

东西

当我运行二进制文件时:

./white_list 某事

找到的变量:某物

快速搜索__secure_getenv指向此页面:

https://refspecs.linuxfoundation.org/LSB_1.1.0/gLSB/baselib---secure-getenv-1.html

报价:

__secure_getenv(name)具有与getenv(name)相同的规范,不同之处在于如果程序 正在运行 SUID 或已启用 SGID,结果始终NULL

所以,问题是:您的程序是否使用设置的 SUID 或 SGID 位运行?如 据我所知,__secure_getenv已被重命名为secure_getenv(我的手册页说它出现在 glibc 2.17 中)。 您应该改用它。

另一个原因可能是:如果源字符串的长度长于strncpysize参数, 它不会添加''终止字节。使用strncpy时,您应该 始终确保写入''终止字节。

男人

#include <string.h>
char *strncpy(char *dest, const char *src, size_t n);

strncpy()函数类似,只是最多复制n字节的src警告:如果src的前n个字节中没有空字节, 放置在 Dest 中的字符串不会以 null 结尾。

white_list_file_buff可能不会''终止,因此fopen失败。 但你说你做了export WHITE_LIST_FILE=/path/White.list.是/path/White.list您使用的实际值或长度小于 200个字符?

还有你的代码在这里

while( (read = getline(&line, &len, fp)) != -1 )
{
else if ( strncmp(line,variable,read - 1) == 0 ){
fclose(fp);
return variable;
}
}

要么是错误的,要么是你忘记粘贴整个代码?没有 该else的先前if.

假设您犯了一个复制和粘贴错误,格式如何,如果White.list?每一行只包含变量的名称?你strncmp比较你知道的整条线,如果你只想匹配一个 子字符串,您应该使用strstr.

Fortify 通常不会将白名单验证识别为解决问题 - 验证例程后,您需要告诉它这是一个验证例程。 这将确保不报告使用此例程正确验证的任何跟踪。

应确保已解决其他注释,并验证基础例程本身是否安全。 然后,您应该通过规则编辑器添加自定义规则,将白名单例程注册为验证例程。 执行此操作的最佳方法是验证/清理规则,该规则添加 taintFlag="VALIDATED_PATH_MANIPULATION" 的污点标志 - 路径操作的接收器规则不应报告此污点的问题。

有关使用污点标志的详细信息,请参阅 https://community.softwaregrp.com/dcvta86296/attachments/dcvta86296/fortify-discussions/2950/1/HP_Fortify_SCA_Custom_Rules_Guide_4.21.pdf

白名单方法从环境变量中获取白名单的名称。 这很容易纵,以至于甚至不能证明首先实施白名单的复杂性是合理的,它当然应该是其自身路径操纵漏洞的原因。 使用__secure_getenv()获取值并没有真正的帮助;这只是意味着如果在安全上下文中运行,您的程序将无法工作。

即使白名单自己的路径在编译时是固定的,您仍然会从外部源获取白名单路径。 这比完全未经验证的用户输入更难操纵,但它并不能真正解决漏洞。

如果无法将白名单编译到程序中,请考虑硬编码路径前缀的白名单和可能出现在其余路径组件中的字符白名单。 目前还不清楚Fortify是否真的会认识到这解决了问题,但这足以让我满意地将问题的分析设置为"不是问题"。

最新更新