首页 -> 安全研究

安全研究

安全漏洞
BSD版本make程序存在/tmp"竞争条件"漏洞

发布日期:2000-01-21
更新日期:2000-01-21

受影响系统:
FreeBSD FreeBSD 3.4
NetBSD  NetBSD 1.4.1
OpenBSD OpenBSD 2.6
描述:
在一些BSD版本的make中存在一个漏洞,有可能导致发生所谓"竞争条件"的问题.当使用"-j"
参数时,make用一种不安全的方式与子进程通讯:"make"会将一些shell命令写到/tmp目录下
的临时文件中,然后临时文件将被子进程读取并执行.然而,make总是用同一个文件名来创建
并重用临时文件.因此如果攻击者能发现这个临时文件名,他有可能在合法命令被写入后再将
自己的命令写入这些文件中.当这些命令被子进程执行后,攻击者就可能获得执行make的用户
(甚至是root)的权限.


<* 来源: FreeBSD安全公告  
         FreeBSD-SA-00:01: Insecure temporary file handling in make(1)
*>

建议:
FreeBSD已经提供了补丁文件:

cd /usr/src/usr.bin/make
patch < /path/to/patch/file
make all
make install

    Index: job.c
    ===================================================================
    RCS file: /home/ncvs/src/usr.bin/make/job.c,v
    retrieving revision 1.16
    diff -u -r1.16 job.c
    --- job.c    1999/09/11 13:08:01    1.16
    +++ job.c    2000/01/17 01:42:57
    @@ -163,14 +163,6 @@
     #define JOB_STOPPED    3       /* The job is stopped */
     
     /*
    - * tfile is the name of a file into which all shell commands are put. It is
    - * used over by removing it before the child shell is executed. The XXXXXXXXXX
    - * in the string are replaced by mkstemp(3).
    - */
    -static char     tfile[sizeof(TMPPAT)];
    -
    -
    -/*
      * Descriptions for various shells.
      */
     static Shell    shells[] = {
    @@ -993,7 +985,7 @@
         /*
          * If we are aborting and the job table is now empty, we finish.
          */
    -    (void) eunlink(tfile);
    +    (void) eunlink(job->tfile);
         Finish(errors);
         }
     }
    @@ -1668,6 +1660,7 @@
         Boolean      cmdsOK;     /* true if the nodes commands were all right */
         Boolean       local;      /* Set true if the job was run locally */
         Boolean       noExec;     /* Set true if we decide not to run the job */
    +    int          tfd;          /* File descriptor for temp file */
     
         if (previous != NULL) {
         previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE);
    @@ -1697,6 +1690,12 @@
         }
         job->flags |= flags;
     
    +    (void) strcpy(job->tfile, TMPPAT);
    +    if ((tfd = mkstemp(job->tfile)) == -1)
    +    Punt("cannot create temp file: %s", strerror(errno));
    +    else
    +    (void) close(tfd);
    +
         /*
          * Check the commands now so any attributes from .DEFAULT have a chance
          * to migrate to the node
    @@ -1722,9 +1721,9 @@
             DieHorribly();
         }
     
    -    job->cmdFILE = fopen(tfile, "w+");
    +    job->cmdFILE = fopen(job->tfile, "w+");
         if (job->cmdFILE == NULL) {
    -        Punt("Could not open %s", tfile);
    +        Punt("Could not open %s", job->tfile);
         }
         (void) fcntl(FILENO(job->cmdFILE), F_SETFD, 1);
         /*
    @@ -1830,7 +1829,7 @@
          * Unlink and close the command file if we opened one
          */
         if (job->cmdFILE != stdout) {
    -        (void) eunlink(tfile);
    +        (void) eunlink(job->tfile);
             if (job->cmdFILE != NULL)
             (void) fclose(job->cmdFILE);
         } else {
    @@ -1859,7 +1858,7 @@
         }
         } else {
         (void) fflush(job->cmdFILE);
    -    (void) eunlink(tfile);
    +    (void) eunlink(job->tfile);
         }
     
         /*
    @@ -2403,13 +2402,6 @@
                      * be running at once. */
     {
         GNode         *begin;     /* node for commands to do at the very start */
    -    int              tfd;
    -
    -    (void) strcpy(tfile, TMPPAT);
    -    if ((tfd = mkstemp(tfile)) == -1)
    -    Punt("cannot create temp file: %s", strerror(errno));
    -    else
    -    (void) close(tfd);
     
         jobs =        Lst_Init(FALSE);
         stoppedJobs = Lst_Init(FALSE);
    @@ -2914,7 +2906,7 @@
             }
         }
         }
    -    (void) eunlink(tfile);
    +    (void) eunlink(job->tfile);
     }
     
     /*
    @@ -2948,7 +2940,6 @@
             }
         }
         }
    -    (void) eunlink(tfile);
         return(errors);
     }
     
    @@ -3024,6 +3015,7 @@
             KILL(job->pid, SIGINT);
             KILL(job->pid, SIGKILL);
     #endif /* RMT_WANTS_SIGNALS */
    +        (void) eunlink(job->tfile);
         }
         }
     
    @@ -3032,7 +3024,6 @@
          */
         while (waitpid((pid_t) -1, &foo, WNOHANG) > 0)
         continue;
    -    (void) eunlink(tfile);
     }
     
     #ifdef REMOTE
    Index: job.h
    ===================================================================
    RCS file: /home/ncvs/src/usr.bin/make/job.h,v
    retrieving revision 1.10
    diff -u -r1.10 job.h
    --- job.h    1999/08/28 01:03:31    1.10
    +++ job.h    2000/01/17 01:42:31
    @@ -93,6 +93,8 @@
     #define JOB_BUFSIZE    1024
     typedef struct Job {
         int           pid;        /* The child's process ID */
    +    char    tfile[sizeof(TMPPAT)];
    +                /* Temporary file to use for job */
         GNode        *node;      /* The target the child is making */
         LstNode     tailCmds;   /* The node of the first command to be
                      * saved when the job has been run */

浏览次数:6941
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障