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

时间:2018-01-10 21:20:08

标签: c fopen fortify path-manipulation

大家好我有强化问题"路径操作"它是由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 : %s\n",mrd);

        fp = fopen(mrd,"w");  <------   SINK
        if ( fp == NULL ){
                printf("line 22\n");
                exit(1);
        }
        fprintf(fp, "%s %s %s %d", "We", "are", "in", 2077);
        fclose(fp);

    }

  return 0;
 }

但是当我运行强化报告时出现fopen中的操纵路径漏洞,我不知道为什么。你可以在代码中看到,在设置fopen文件之前,它验证了white_list_validator。 所以任何人都知道为什么它不能正常工作?

注意(*):导出WHITE_LIST_FILE = / path / White.list

cat White.list

TEST1

TEST2

东西

当我运行二进制文件时:

./ white_list something

找到的变量:某事

3 个答案:

答案 0 :(得分:3)

快速搜索__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中)。 你应该改用它。

另一个原因可能是:如果源字符串的长度超过size的{​​{1}}参数, 它不会添加strncpy终止字节。使用'\0'时应该这样做 始终确保写入strncpy终止字节。

  

man strcpy

'\0'
     

#include <string.h> char *strncpy(char *dest, const char *src, size_t n); 函数类似,只是复制了strncpy()n个字节。   警告:如果src的前n个字节中没有空字节,   放在dest中的字符串不会以空值终止。

src可能不是white_list_file_buff - 终止,因此'\0'失败。 但你说你做过fopen。是 export WHITE_LIST_FILE=/path/White.list您使用的实际值或某个长于的路径 200个字符?

此处还有您的代码

/path/White.list

要么错了,要么忘了粘贴整个代码?没有 while( (read = getline(&line, &len, fp)) != -1 ) { else if ( strncmp(line,variable,read - 1) == 0 ){ fclose(fp); return variable; } } 之前的if

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

答案 1 :(得分:1)

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

您应该确保已经解决了其他评论,并且验证了基础例程本身是安全的。然后,您应该通过规则编辑器添加自定义规则,将白名单例程注册为验证例程。最好的方法是验证/清理规则,添加污点标记taintFlag =&#34; VALIDATED_PATH_MANIPULATION&#34; - 路径操作的接收器规则不应报告此污点的问题。

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

答案 2 :(得分:0)

您的白名单方法方法从环境变量中获取白名单的名称。这很容易被操纵,甚至不能证明首先实现白名单的复杂性,并且它当然应该是它自己的路径操纵漏洞的原因。使用__secure_getenv()获取值并不是真的有用;它只是意味着如果在安全的环境中运行,您的程序将无法运行。

即使白名单自己的路径在编译时被修复,您仍然可以从外部源获取白名单路径。与完全未经验证的用户输入相比,操作起来更难,但它并没有真正解决漏洞。

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