-1

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

白名单.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;
 }

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

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

猫白名单

测试1

测试2

某物

当我运行二进制文件时:

./white_list 一些东西

发现变量:某事

4

3 回答 3

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参数长strncpy,则不会添加'\0'终止字节。使用时,strncpy您应始终确保写入'\0'终止字节。

男人 strcpy

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

strncpy()功能类似,不同之处在于最多复制 的 n字节。警告:如果 的第一个字节中没有空字节,则放在 dest 中的字符串不会以空结尾。srcnsrc

white_list_file_buff可能不会被'\0'终止,因此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;
    }

}

是错误的还是您忘记粘贴整个代码?没有以前ifelse

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

于 2018-01-10T21:47:31.183 回答
1

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

于 2018-01-11T18:55:53.197 回答
0

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

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

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

于 2018-01-10T21:55:09.733 回答