char *html_encode(char *string) { char *ret = string; if (ret == NULL) return NULL; if (index(ret, '%') != NULL) ret = hydra_strrep(ret, "%", "%25"); if (index(ret, ' ') != NULL) ret = hydra_strrep(ret, " ", "%20"); if (index(ret, '&') != NULL) ret = hydra_strrep(ret, "&", "%26"); if (index(ret, '#') != NULL) ret = hydra_strrep(ret, "&", "%23"); return ret; }
/* int analyze_server_response(int socket) return 0 or 1 when the cond regex is matched return -1 if no response from server */ int analyze_server_response(int s) { int runs = 0; while ((buf = hydra_receive_line(s)) != NULL) { runs++; //check for http redirection if (strstr(buf, "HTTP/1.1 3") != NULL || strstr(buf, "HTTP/1.0 3") != NULL || strstr(buf, "Status: 3") != NULL) { redirected_flag = 1; } else if (strstr(buf, "HTTP/1.1 401") != NULL || strstr(buf, "HTTP/1.0 401") != NULL) { auth_flag = 1; } else if ((strstr(buf, "HTTP/1.1 403") != NULL) || (strstr(buf, "HTTP/1.1 404") != NULL) || (strstr(buf, "HTTP/1.0 403") != NULL) || (strstr(buf, "HTTP/1.0 404") != NULL)) { return 0; } if (hydra_strcasestr(buf, "Location: ") != NULL) { char *startloc, *endloc; char str[2048]; startloc = hydra_strcasestr(buf, "Location: ") + strlen("Location: "); strncpy(str, startloc, sizeof(str) - 1); str[sizeof(str) - 1] = 0; endloc = strchr(str, '\n'); if (endloc != NULL) *endloc = 0; endloc = strchr(str, '\r'); if (endloc != NULL) *endloc = 0; strcpy(redirected_url_buff, str); } //there can be multiple cookies if (hydra_strcasestr(buf, "Set-Cookie: ") != NULL) { char *cookiebuf = buf; do { char *startcookie, *endcookie1, *endcookie2; char str[1024], tmpcookie[4096] = "", tmpname[128] = "", *ptr, *ptr2; memset(str, 0, sizeof(str)); startcookie = hydra_strcasestr(cookiebuf, "Set-Cookie: ") + strlen("Set-Cookie: "); strncpy(str, startcookie, sizeof(str) - 1); str[sizeof(str) - 1] = 0; endcookie1 = strchr(str, '\n'); endcookie2 = strchr(str, ';'); //terminate string after cookie data if (endcookie1 != NULL && endcookie1 < endcookie2) *endcookie1 = 0; else if (endcookie2 != NULL) *endcookie2 = 0; // is the cookie already there? if yes, remove it! if (index(startcookie, '=') != NULL && (ptr = index(startcookie, '=')) - startcookie + 1 <= sizeof(tmpname)) { strncpy(tmpname, startcookie, sizeof(tmpname) - 2); tmpname[sizeof(tmpname) - 2] = 0; ptr = index(tmpname, '='); *(++ptr) = 0; // is the cookie already in the cookiejar? (so, does it have to be replaced?) if ((ptr = hydra_strcasestr(cookie, tmpname)) != NULL) { // yes it is. // if the cookie is not in the beginning of the cookiejar, copy the ones before if (ptr != cookie && *(ptr - 1) == ' ') { strncpy(tmpcookie, cookie, ptr - cookie - 2); tmpcookie[ptr - cookie - 2] = 0; } ptr += strlen(tmpname); // if there are any cookies after this one in the cookiejar, copy them over if ((ptr2 = strstr(ptr, "; ")) != NULL) { ptr2 += 2; strncat(tmpcookie, ptr2, sizeof(tmpcookie) - strlen(tmpcookie) - 1); } if (debug) printf("[DEBUG] removing cookie %s in jar\n before: %s\n after: %s\n", tmpname, cookie, tmpcookie); strcpy(cookie, tmpcookie); } } ptr = index(str, '='); // only copy the cookie if it has a value (otherwise the server wants to delete the cookie if (ptr != NULL && *(ptr + 1) != ';' && *(ptr + 1) != 0 && *(ptr + 1) != '\n' && *(ptr + 1) != '\r') { if (strlen(cookie) > 0) strncat(cookie, "; ", sizeof(cookie) - strlen(cookie) - 1); strncat(cookie, str, sizeof(cookie) - strlen(cookie) - 1); } cookiebuf = startcookie; } while (hydra_strcasestr(cookiebuf, "Set-Cookie: ") != NULL); } #ifdef HAVE_PCRE if (hydra_string_match(buf, cond) == 1) { #else if (strstr(buf, cond) != NULL) { #endif free(buf); // printf("DEBUG: STRING %s FOUND!!:\n%s\n", cond, buf); return 1; } // else printf("DEBUG: STRING %s NOT FOUND:\n%s\n", cond, buf); free(buf); } if (runs == 0) { if (debug) hydra_report(stderr, "DEBUG: no response from server\n"); return -1; } return 0; } void hydra_reconnect(int s, char *ip, int port, unsigned char options) { if (s >= 0) s = hydra_disconnect(s); if ((options & OPTION_SSL) == 0) { s = hydra_connect_tcp(ip, port); } else { s = hydra_connect_ssl(ip, port); } } int start_http_form(int s, char *ip, int port, unsigned char options, char *miscptr, FILE * fp, char *type) { char *empty = ""; char *login, *pass, buffer[9000], clogin[256], cpass[256]; char header[8096], *upd3variables, cuserheader[1024]; int found = !success_cond, i, j; memset(header, 0, sizeof(header)); cookie[0] = 0; // reset cookies from potential previous attempt if (strlen(login = hydra_get_next_login()) == 0) login = empty; if (strlen(pass = hydra_get_next_password()) == 0) pass = empty; strncpy(clogin, html_encode(login), sizeof(clogin) - 1); clogin[sizeof(clogin) - 1] = 0; strncpy(cpass, html_encode(pass), sizeof(cpass) - 1); cpass[sizeof(cpass) - 1] = 0; upd3variables = hydra_strrep(variables, "^USER^", clogin); upd3variables = hydra_strrep(upd3variables, "^PASS^", cpass); if (strstr(userheader, "^USER^") == NULL && strstr(userheader, "^PASS^") == NULL) { strcpy(cuserheader, userheader); } else { // we use the encoded version strncpy(cuserheader, hydra_strrep(userheader, "^USER^", clogin), sizeof(cuserheader) - 1); cuserheader[sizeof(cuserheader) - 1] = 0; strncpy(cuserheader, hydra_strrep(cuserheader, "^PASS^", cpass), sizeof(cuserheader) - 1); cuserheader[sizeof(cuserheader) - 1] = 0; } /* again: no snprintf to be portable. dont worry, buffer cant overflow */ if (use_proxy == 1 && proxy_authentication != NULL) { // proxy with authentication if (getcookie) { //doing a GET to save cookies sprintf(buffer, "GET http://%s:%d%.600s HTTP/1.0\r\nHost: %s\r\nProxy-Authorization: Basic %s\r\nUser-Agent: Mozilla 5.0 (Hydra Proxy Auth)\r\n%s%s\r\n", webtarget, webport, cookieurl, webtarget, proxy_authentication, header, cuserheader); if (hydra_send(s, buffer, strlen(buffer), 0) < 0) { return 1; } i = analyze_server_response(s); // return value ignored if (strlen(cookie) > 0) { sprintf(header, "Cookie: %s\r\n", cookie); } hydra_reconnect(s, ip, port, options); } if (strcmp(type, "POST") == 0) { sprintf(buffer, "POST http://%s:%d%.600s HTTP/1.0\r\nHost: %s\r\nProxy-Authorization: Basic %s\r\nUser-Agent: Mozilla/5.0 (Hydra Proxy Auth)\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\n%s%s\r\n%s", webtarget, webport, url, webtarget, proxy_authentication, (int) strlen(upd3variables), header, cuserheader, upd3variables); if (hydra_send(s, buffer, strlen(buffer), 0) < 0) { return 1; } } else { sprintf(buffer, "GET http://%s:%d%.600s?%s HTTP/1.0\r\nHost: %s\r\nProxy-Authorization: Basic %s\r\nUser-Agent: Mozilla/5.0 (Hydra Proxy Auth)\r\n%s%s\r\n", webtarget, webport, url, upd3variables, webtarget, proxy_authentication, header, cuserheader); if (hydra_send(s, buffer, strlen(buffer), 0) < 0) { return 1; } } } else { if (use_proxy == 1) { // proxy without authentication if (getcookie) { //doing a GET to get cookies sprintf(buffer, "GET http://%s:%d%.600s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (Hydra Proxy)\r\n%s%s\r\n", webtarget, webport, cookieurl, webtarget, header, cuserheader); if (hydra_send(s, buffer, strlen(buffer), 0) < 0) { return 1; } i = analyze_server_response(s); // ignore result if (strlen(cookie) > 0) { sprintf(header, "Cookie: %s\r\n", cookie); } hydra_reconnect(s, ip, port, options); } if (strcmp(type, "POST") == 0) { sprintf(buffer, "POST http://%s:%d%.600s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (Hydra)\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\n%s%s\r\n%s", webtarget, webport, url, webtarget, (int) strlen(upd3variables), header, cuserheader, upd3variables); if (hydra_send(s, buffer, strlen(buffer), 0) < 0) { return 1; } } else { sprintf(buffer, "GET http://%s:%d%.600s?%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (Hydra)\r\n%s%s\r\n", webtarget, webport, url, upd3variables, webtarget, header, cuserheader); if (hydra_send(s, buffer, strlen(buffer), 0) < 0) { return 1; } } } else { // direct web server, no proxy if (getcookie) { //doing a GET to save cookies sprintf(buffer, "GET %.600s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (Hydra)\r\n%s\r\n", cookieurl, webtarget, cuserheader); if (hydra_send(s, buffer, strlen(buffer), 0) < 0) { return 1; } i = analyze_server_response(s); // ignore result if (strlen(cookie) > 0) { sprintf(header, "Cookie: %s\r\n", cookie); } hydra_reconnect(s, ip, port, options); } if (strcmp(type, "POST") == 0) { sprintf(buffer, "POST %.600s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (Hydra)\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\n%s%s\r\n%s", url, webtarget, (int) strlen(upd3variables), header, cuserheader, upd3variables); if (hydra_send(s, buffer, strlen(buffer), 0) < 0) { return 1; } } else { sprintf(buffer, "GET %.600s?%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (Hydra)\r\n%s%s\r\n", url, upd3variables, webtarget, header, cuserheader); if (hydra_send(s, buffer, strlen(buffer), 0) < 0) { return 1; } } } } found = analyze_server_response(s); if (auth_flag) { // we received a 401 error - user using wrong module hydra_report(stderr, "[ERROR] the target is using HTTP auth, not a web form, received HTTP error code 401. Use module \"http%s-get\" instead.\n", (options & OPTION_SSL) > 0 ? "s" : ""); return 4; } if (strlen(cookie) > 0) { sprintf(header, "Cookie: %.1000s\r\n", cookie); } //if page was redirected, follow the location header redirected_cpt = MAX_REDIRECT; if (debug) printf("[DEBUG] attempt result: found %d, redirect %d, location: %s\n", found, redirected_flag, redirected_url_buff); while (found == 0 && redirected_flag && (redirected_url_buff[0] != 0) && (redirected_cpt > 0)) { //we have to split the location char *startloc, *endloc; char str[2048]; char str2[2048]; char str3[2048]; redirected_cpt--; redirected_flag = 0; //check if the redirect page contains the fail/success condition #ifdef HAVE_PCRE if (hydra_string_match(redirected_url_buff, cond) == 1) { #else if (strstr(redirected_url_buff, cond) != NULL) { #endif found = success_cond; } else { //location could be either absolute http(s):// or / something //or relative startloc = strstr(redirected_url_buff, "://"); if (startloc != NULL) { startloc += strlen("://"); if ((endloc = strchr(startloc, '\r')) != NULL) { startloc[endloc - startloc] = 0; } if ((endloc = strchr(startloc, '\n')) != NULL) { startloc[endloc - startloc] = 0; } strncpy(str, startloc, sizeof(str)); str[sizeof(str) - 1] = 0; endloc = strchr(str, '/'); if (endloc != NULL) { strncpy(str2, str, endloc - str); str2[endloc - str] = 0; } else strncpy(str2, str, sizeof(str)); if (strlen(str) - strlen(str2) == 0) { strcpy(str3, "/"); } else { strncpy(str3, str + strlen(str2), strlen(str) - strlen(str2) - 1); str3[strlen(str) - strlen(str2) - 1] = 0; } } else { strncpy(str2, webtarget, sizeof(str2) - 1); str2[sizeof(str2) - 1] = 0; if (redirected_url_buff[0] != '/') { //it's a relative path, so we have to concatenate it //with the path from the first url given char *urlpath; char urlpath_extracted[2048]; memset(urlpath_extracted, 0, sizeof(urlpath_extracted)); urlpath = strrchr(url, '/'); if (urlpath != NULL) { strncpy(urlpath_extracted, url, urlpath - url); sprintf(str3, "%.1000s/%.1000s", urlpath_extracted, redirected_url_buff); } else { sprintf(str3, "%.1000s/%.1000s", url, redirected_url_buff); } } else strncpy(str3, redirected_url_buff, sizeof(str3)); if (debug) hydra_report(stderr, "[DEBUG] host=%s redirect=%s origin=%s\n", str2, str3, url); } if (str3[0] != '/') { j = strlen(str3); str3[j + 1] = 0; for (i = j; i > 0; i--) str3[i] = str3[i - 1]; str3[0] = '/'; } if (verbose) hydra_report(stderr, "[VERBOSE] Page redirected to http://%s%s\n", str2, str3); //re-use the code above to check for proxy use if (use_proxy == 1 && proxy_authentication != NULL) { // proxy with authentication sprintf(buffer, "GET http://%s:%d%.600s HTTP/1.0\r\nHost: %s\r\nProxy-Authorization: Basic %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\n%s\r\n", webtarget, webport, str3, str2, proxy_authentication, header); } else { if (use_proxy == 1) { // proxy without authentication sprintf(buffer, "GET http://%s:%d%.600s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\n%s\r\n", webtarget, webport, str3, str2, header); } else { //direct web server, no proxy sprintf(buffer, "GET %.600s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\n%s\r\n", str3, str2, header); } } hydra_reconnect(s, ip, port, options); if (hydra_send(s, buffer, strlen(buffer), 0) < 0) { return 1; } found = analyze_server_response(s); if (strlen(cookie) > 0) { sprintf(header, "Cookie: %s\r\n", cookie); } } } //if the last status is still 3xx, set it as a false if (found != -1 && found == success_cond && redirected_flag == 0 && redirected_cpt >= 0) { hydra_report_found_host(port, ip, "www-form", fp); hydra_completed_pair_found(); } else { hydra_completed_pair(); } return 1; } void service_http_form(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *type) { int run = 1, next_run = 1, sock = -1; int myport = PORT_HTTP, mysslport = PORT_HTTP_SSL; char *ptr, *ptr2; hydra_register_socket(sp); if (webtarget != NULL && (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) { if (freemischttpform == 0) { freemischttpform = 1; 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) webtarget = hydra_address2string(ip); if (port != 0) webport = port; else if ((options & OPTION_SSL) == 0) webport = myport; else webport = mysslport; sprintf(bufferurl, "%.1000s", miscptr); url = bufferurl; ptr = url; while (*ptr != 0 && (*ptr != ':' || *(ptr - 1) == '\\')) ptr++; if (*ptr != 0) *ptr++ = 0; variables = ptr; while (*ptr != 0 && (*ptr != ':' || *(ptr - 1) == '\\')) ptr++; if (*ptr != 0) *ptr++ = 0; cond = ptr; while (*ptr != 0 && (*ptr != ':' || *(ptr - 1) == '\\')) ptr++; if (*ptr != 0) *ptr++ = 0; optional1 = ptr; if (strstr(url, "\\:") != NULL) { if ((ptr = malloc(strlen(url))) != NULL) { // no need for +1 strcpy(ptr, hydra_strrep(url, "\\:", ":")); url = ptr; } } if (strstr(variables, "\\:") != NULL) { if ((ptr = malloc(strlen(variables))) != NULL) { // no need for +1 strcpy(ptr, hydra_strrep(variables, "\\:", ":")); variables = ptr; } } if (strstr(cond, "\\:") != NULL) { if ((ptr = malloc(strlen(cond))) != NULL) { // no need for +1 strcpy(ptr, hydra_strrep(cond, "\\:", ":")); cond = ptr; } } if (url == NULL || variables == NULL || cond == NULL /*|| optional1 == NULL */ ) hydra_child_exit(2); //printf("url: %s, var: %s, cond: %s, opt: %s\n", url, variables, cond, optional1); if (*cond == 0) { fprintf(stderr, "[ERROR] invalid number of parameters in module option\n"); hydra_child_exit(2); } sprintf(cookieurl, "%.1000s", url); //conditions now have to contain F or S to set the fail or success condition if (*cond != 0 && (strpos(cond, "F=") == 0)) { success_cond = 0; cond += 2; } else if (*cond != 0 && (strpos(cond, "S=") == 0)) { success_cond = 1; cond += 2; } else { //by default condition is a fail success_cond = 0; } while ( /*(optional1 = strtok(NULL, ":")) != NULL */ *optional1 != 0) { switch (optional1[0]) { case 'c': // fall through case 'C': ptr = optional1 + 2; while (*ptr != 0 && (*ptr != ':' || *(ptr - 1) == '\\')) ptr++; if (*ptr != 0) *ptr++ = 0; sprintf(cookieurl, "%.1000s", hydra_strrep(optional1 + 2, "\\:", ":")); optional1 = ptr; break; case 'h': // fall through case 'H': ptr = optional1 + 2; while (*ptr != 0 && (*ptr != ':' || *(ptr - 1) == '\\')) ptr++; if (*ptr != 0) *ptr++ = 0; ptr2 = ptr; while (*ptr2 != 0 && (*ptr2 != ':' || *(ptr2 - 1) == '\\')) ptr2++; if (*ptr2 != 0) *ptr2++ = 0; if (sizeof(userheader) - strlen(userheader) > 4) { strncat(userheader, optional1 + 2, sizeof(userheader) - strlen(userheader) - 4); strcat(userheader, ":"); strncat(userheader, hydra_strrep(ptr, "\\:", ":"), sizeof(userheader) - strlen(userheader) - 3); strcat(userheader, "\r\n"); } optional1 = ptr2; break; // no default } } while (1) { if (run == 2) { if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) { if (freemischttpform) free(miscptr); freemischttpform = 0; hydra_child_exit(1); } } switch (run) { case 1: /* connect and service init function */ { if (sock >= 0) sock = hydra_disconnect(sock); 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) { hydra_report(stderr, "[ERROR] Child with pid %d terminating, can not connect\n", (int) getpid()); if (freemischttpform) free(miscptr); freemischttpform = 0; 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); if (freemischttpform) free(miscptr); freemischttpform = 0; hydra_child_exit(0); break; case 4: /* silent error exit */ if (sock >= 0) sock = hydra_disconnect(sock); if (freemischttpform) free(miscptr); freemischttpform = 0; hydra_child_exit(1); break; default: if (freemischttpform) free(miscptr); freemischttpform = 0; hydra_report(stderr, "[ERROR] Caught unknown return code, exiting!\n"); hydra_child_exit(0); } run = next_run; } if (freemischttpform) free(miscptr); }
/* int analyze_server_response(int socket) return 0 or 1 when the cond regex is matched return -1 if no response from server */ int analyze_server_response(int s) { int runs = 0; while ((buf = hydra_receive_line(s)) != NULL) { runs++; //check for http redirection if (strstr(buf, "HTTP/1.1 3") != NULL || strstr(buf, "HTTP/1.0 3") != NULL || strstr(buf, "Status: 3") != NULL) { redirected_flag = 1; } else if (strstr(buf, "HTTP/1.1 401") != NULL || strstr(buf, "HTTP/1.0 401") != NULL) { auth_flag = 1; } else if ((strstr(buf, "HTTP/1.1 403") != NULL) || (strstr(buf, "HTTP/1.1 404") != NULL) || (strstr(buf, "HTTP/1.0 403") != NULL) || (strstr(buf, "HTTP/1.0 404") != NULL)) { return 0; } if (hydra_strcasestr(buf, "Location: ") != NULL) { char *startloc, *endloc; char str[2048]; startloc = hydra_strcasestr(buf, "Location: ") + strlen("Location: "); strncpy(str, startloc, sizeof(str) - 1); str[sizeof(str) - 1] = 0; endloc = strchr(str, '\n'); if (endloc != NULL) *endloc = 0; endloc = strchr(str, '\r'); if (endloc != NULL) *endloc = 0; strcpy(redirected_url_buff, str); } //there can be multiple cookies if (hydra_strcasestr(buf, "Set-Cookie: ") != NULL) { char *cookiebuf = buf; do { char *startcookie, *endcookie1, *endcookie2; char str[1024], tmpcookie[4096] = "", tmpname[128] = "", *ptr, *ptr2; memset(str, 0, sizeof(str)); startcookie = hydra_strcasestr(cookiebuf, "Set-Cookie: ") + strlen("Set-Cookie: "); strncpy(str, startcookie, sizeof(str) - 1); str[sizeof(str) - 1] = 0; endcookie1 = strchr(str, '\n'); endcookie2 = strchr(str, ';'); //terminate string after cookie data if (endcookie1 != NULL && ((endcookie1 < endcookie2) || (endcookie2 == NULL))) { if (*(endcookie1 - 1) == '\r') endcookie1--; *endcookie1 = 0; } else if (endcookie2 != NULL) *endcookie2 = 0; // is the cookie already there? if yes, remove it! if (index(startcookie, '=') != NULL && (ptr = index(startcookie, '=')) - startcookie + 1 <= sizeof(tmpname)) { strncpy(tmpname, startcookie, sizeof(tmpname) - 2); tmpname[sizeof(tmpname) - 2] = 0; ptr = index(tmpname, '='); *(++ptr) = 0; // is the cookie already in the cookiejar? (so, does it have to be replaced?) if ((ptr = hydra_strcasestr(cookie, tmpname)) != NULL) { // yes it is. // if the cookie is not in the beginning of the cookiejar, copy the ones before if (ptr != cookie && *(ptr - 1) == ' ') { strncpy(tmpcookie, cookie, ptr - cookie - 2); tmpcookie[ptr - cookie - 2] = 0; } ptr += strlen(tmpname); // if there are any cookies after this one in the cookiejar, copy them over if ((ptr2 = strstr(ptr, "; ")) != NULL) { ptr2 += 2; strncat(tmpcookie, ptr2, sizeof(tmpcookie) - strlen(tmpcookie) - 1); } if (debug) printf("[DEBUG] removing cookie %s in jar\n before: %s\n after: %s\n", tmpname, cookie, tmpcookie); strcpy(cookie, tmpcookie); } } ptr = index(str, '='); // only copy the cookie if it has a value (otherwise the server wants to delete the cookie) if (ptr != NULL && *(ptr + 1) != ';' && *(ptr + 1) != 0 && *(ptr + 1) != '\n' && *(ptr + 1) != '\r') { if (strlen(cookie) > 0) strncat(cookie, "; ", sizeof(cookie) - strlen(cookie) - 1); strncat(cookie, str, sizeof(cookie) - strlen(cookie) - 1); } cookiebuf = startcookie; } while (hydra_strcasestr(cookiebuf, "Set-Cookie: ") != NULL); } #ifdef HAVE_PCRE if (hydra_string_match(buf, cond) == 1) { #else if (strstr(buf, cond) != NULL) { #endif free(buf); // printf("DEBUG: STRING %s FOUND!!:\n%s\n", cond, buf); return 1; } // else printf("DEBUG: STRING %s NOT FOUND:\n%s\n", cond, buf); free(buf); } if (runs == 0) { if (debug) hydra_report(stderr, "DEBUG: no response from server\n"); return -1; } return 0; } void hydra_reconnect(int s, char *ip, int port, unsigned char options) { if (s >= 0) s = hydra_disconnect(s); if ((options & OPTION_SSL) == 0) { s = hydra_connect_tcp(ip, port); } else { s = hydra_connect_ssl(ip, port); } } int start_http_form(int s, char *ip, int port, unsigned char options, char *miscptr, FILE * fp, char *type, ptr_header_node ptr_head) { char *empty = ""; char *login, *pass, clogin[256], cpass[256]; char header[8096], *upd3variables; char *http_request; int found = !success_cond, i, j; char content_length[MAX_CONTENT_LENGTH], proxy_string[MAX_PROXY_LENGTH]; memset(header, 0, sizeof(header)); cookie[0] = 0; // reset cookies from potential previous attempt // Take the next login/pass pair if (strlen(login = hydra_get_next_login()) == 0) login = empty; if (strlen(pass = hydra_get_next_password()) == 0) pass = empty; strncpy(clogin, html_encode(login), sizeof(clogin) - 1); clogin[sizeof(clogin) - 1] = 0; strncpy(cpass, html_encode(pass), sizeof(cpass) - 1); cpass[sizeof(cpass) - 1] = 0; upd3variables = hydra_strrep(variables, "^USER^", clogin); upd3variables = hydra_strrep(upd3variables, "^PASS^", cpass); // Replace the user/pass placeholders in the user-supplied headers hdrrep(&ptr_head, "^USER^", clogin); hdrrep(&ptr_head, "^PASS^", cpass); /* again: no snprintf to be portable. dont worry, buffer cant overflow */ if (use_proxy == 1 && proxy_authentication != NULL) { if (getcookie) { memset(proxy_string, 0, sizeof(proxy_string)); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s:%d%.600s", webtarget, webport, cookieurl); http_request = prepare_http_request("GET", proxy_string, NULL, cookie_request); if (hydra_send(s, http_request, strlen(http_request), 0) < 0) return 1; i = analyze_server_response(s); // ignore result if (strlen(cookie) > 0) add_header(&ptr_head, "Cookie", cookie, HEADER_TYPE_DEFAULT_REPL); hydra_reconnect(s, ip, port, options); } // now prepare for the "real" request if (strcmp(type, "POST") == 0) { memset(proxy_string, 0, sizeof(proxy_string)); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s:%d%.600s", webtarget, webport, url); snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int) strlen(upd3variables)); if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) hdrrepv(&ptr_head, "Content-Length", content_length); else add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) add_header(&ptr_head, "Content-Type", "application/x-www-form-urlencoded", HEADER_TYPE_DEFAULT); normal_request = stringify_headers(&ptr_head); http_request = prepare_http_request("POST", proxy_string, upd3variables, normal_request); if (hydra_send(s, http_request, strlen(http_request), 0) < 0) return 1; } else { normal_request = stringify_headers(&ptr_head); http_request = prepare_http_request("GET", url, upd3variables, normal_request); if (hydra_send(s, http_request, strlen(http_request), 0) < 0) return 1; } } else { if (use_proxy == 1) { // proxy without authentication if (getcookie) { //doing a GET to get cookies memset(proxy_string, 0, sizeof(proxy_string)); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s:%d%.600s", webtarget, webport, cookieurl); http_request = prepare_http_request("GET", proxy_string, NULL, cookie_request); if (hydra_send(s, http_request, strlen(http_request), 0) < 0) return 1; i = analyze_server_response(s); // ignore result if (strlen(cookie) > 0) add_header(&ptr_head, "Cookie", cookie, HEADER_TYPE_DEFAULT_REPL); hydra_reconnect(s, ip, port, options); } // now prepare for the "real" request if (strcmp(type, "POST") == 0) { memset(proxy_string, 0, sizeof(proxy_string)); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s:%d%.600s", webtarget, webport, url); snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int) strlen(upd3variables)); if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) hdrrepv(&ptr_head, "Content-Length", content_length); else add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) add_header(&ptr_head, "Content-Type", "application/x-www-form-urlencoded", HEADER_TYPE_DEFAULT); normal_request = stringify_headers(&ptr_head); http_request = prepare_http_request("POST", proxy_string, upd3variables, normal_request); if (hydra_send(s, http_request, strlen(http_request), 0) < 0) return 1; } else { normal_request = stringify_headers(&ptr_head); http_request = prepare_http_request("GET", url, upd3variables, normal_request); if (hydra_send(s, http_request, strlen(http_request), 0) < 0) return 1; } } else { // direct web server, no proxy if (getcookie) { //doing a GET to save cookies http_request = prepare_http_request("GET", cookieurl, NULL, cookie_request); if (hydra_send(s, http_request, strlen(http_request), 0) < 0) return 1; i = analyze_server_response(s); // ignore result if (strlen(cookie) > 0) { add_header(&ptr_head, "Cookie", cookie, HEADER_TYPE_DEFAULT_REPL); normal_request = stringify_headers(&ptr_head); } hydra_reconnect(s, ip, port, options); } // now prepare for the "real" request if (strcmp(type, "POST") == 0) { snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int) strlen(upd3variables)); if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) hdrrepv(&ptr_head, "Content-Length", content_length); else add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) add_header(&ptr_head, "Content-Type", "application/x-www-form-urlencoded", HEADER_TYPE_DEFAULT); normal_request = stringify_headers(&ptr_head); http_request = prepare_http_request("POST", url, upd3variables, normal_request); if (hydra_send(s, http_request, strlen(http_request), 0) < 0) return 1; } else { normal_request = stringify_headers(&ptr_head); http_request = prepare_http_request("GET", url, upd3variables, normal_request); if (hydra_send(s, http_request, strlen(http_request), 0) < 0) return 1; } } } if (debug) hydra_report_debug(stdout, "HTTP request sent:\n%s\n", http_request); found = analyze_server_response(s); if (auth_flag) { // we received a 401 error - user using wrong module hydra_report(stderr, "[ERROR] the target is using HTTP auth, not a web form, received HTTP error code 401. Use module \"http%s-get\" instead.\n", (options & OPTION_SSL) > 0 ? "s" : ""); return 4; } if (strlen(cookie) > 0) add_header(&ptr_head, "Cookie", cookie, HEADER_TYPE_DEFAULT_REPL); //if page was redirected, follow the location header redirected_cpt = MAX_REDIRECT; if (debug) printf("[DEBUG] attempt result: found %d, redirect %d, location: %s\n", found, redirected_flag, redirected_url_buff); while (found == 0 && redirected_flag && (redirected_url_buff[0] != 0) && (redirected_cpt > 0)) { //we have to split the location char *startloc, *endloc; char str[2048]; char str2[2048]; char str3[2048]; redirected_cpt--; redirected_flag = 0; //check if the redirect page contains the fail/success condition #ifdef HAVE_PCRE if (hydra_string_match(redirected_url_buff, cond) == 1) { #else if (strstr(redirected_url_buff, cond) != NULL) { #endif found = success_cond; } else { //location could be either absolute http(s):// or / something //or relative startloc = strstr(redirected_url_buff, "://"); if (startloc != NULL) { startloc += strlen("://"); if ((endloc = strchr(startloc, '\r')) != NULL) { startloc[endloc - startloc] = 0; } if ((endloc = strchr(startloc, '\n')) != NULL) { startloc[endloc - startloc] = 0; } strcpy(str, startloc); endloc = strchr(str, '/'); if (endloc != NULL) { strncpy(str2, str, endloc - str); str2[endloc - str] = 0; } else strncpy(str2, str, sizeof(str)); if (strlen(str) - strlen(str2) == 0) { strcpy(str3, "/"); } else { strncpy(str3, str + strlen(str2), strlen(str) - strlen(str2) - 1); str3[strlen(str) - strlen(str2) - 1] = 0; } } else { strncpy(str2, webtarget, sizeof(str2)); if (redirected_url_buff[0] != '/') { //it's a relative path, so we have to concatenate it //with the path from the first url given char *urlpath; char urlpath_extracted[2048]; memset(urlpath_extracted, 0, sizeof(urlpath_extracted)); urlpath = strrchr(url, '/'); if (urlpath != NULL) { strncpy(urlpath_extracted, url, urlpath - url); sprintf(str3, "%.1000s/%.1000s", urlpath_extracted, redirected_url_buff); } else { sprintf(str3, "%.1000s/%.1000s", url, redirected_url_buff); } } else strncpy(str3, redirected_url_buff, sizeof(str3)); if (debug) hydra_report(stderr, "[DEBUG] host=%s redirect=%s origin=%s\n", str2, str3, url); } if (str3[0] != '/') { j = strlen(str3); str3[j + 1] = 0; for (i = j; i > 0; i--) str3[i] = str3[i - 1]; str3[0] = '/'; } if (verbose) hydra_report(stderr, "[VERBOSE] Page redirected to http://%s%s\n", str2, str3); //re-use the code above to check for proxy use if (use_proxy == 1 && proxy_authentication != NULL) { // proxy with authentication hdrrepv(&ptr_head, "Host", str2); memset(proxy_string, 0, sizeof(proxy_string)); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s:%d%.600s", webtarget, webport, str3); normal_request = stringify_headers(&ptr_head); http_request = prepare_http_request("GET", proxy_string, NULL, normal_request); } else { if (use_proxy == 1) { // proxy without authentication hdrrepv(&ptr_head, "Host", str2); memset(proxy_string, 0, sizeof(proxy_string)); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s:%d%.600s", webtarget, webport, str3); normal_request = stringify_headers(&ptr_head); http_request = prepare_http_request("GET", proxy_string, NULL, normal_request); } else { //direct web server, no proxy hdrrepv(&ptr_head, "Host", str2); normal_request = stringify_headers(&ptr_head); http_request = prepare_http_request("GET", str3, NULL, normal_request); } } hydra_reconnect(s, ip, port, options); if (hydra_send(s, http_request, strlen(http_request), 0) < 0) return 1; found = analyze_server_response(s); if (strlen(cookie) > 0) add_header(&ptr_head, "Cookie", cookie, HEADER_TYPE_DEFAULT_REPL); } } //if the last status is still 3xx, set it as a false if (found != -1 && found == success_cond && (redirected_flag == 0 || success_cond == 1) && redirected_cpt >= 0) { hydra_report_found_host(port, ip, "www-form", fp); hydra_completed_pair_found(); } else { hydra_completed_pair(); } return 1; } void service_http_form(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port, char *type, ptr_header_node * ptr_head) { int run = 1, next_run = 1, sock = -1; int myport = PORT_HTTP, mysslport = PORT_HTTP_SSL; // register our socket descriptor hydra_register_socket(sp); /* * Iterate through the runs. Possible values are the following: * - 1 -> Open connection to remote server. * - 2 -> Run password attempts. * - 3 -> Disconnect and end with success. * - 4 -> Disconnect and end with error. */ while (1) { if (run == 2) { if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) { if (freemischttpform) free(miscptr); freemischttpform = 0; hydra_child_exit(1); } } switch (run) { case 1: /* connect and service init function */ { if (sock >= 0) sock = hydra_disconnect(sock); 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) { hydra_report(stderr, "[ERROR] Child with pid %d terminating, cannot connect\n", (int) getpid()); if (freemischttpform) free(miscptr); freemischttpform = 0; 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, *ptr_head); break; case 3: /* clean exit */ if (sock >= 0) sock = hydra_disconnect(sock); if (freemischttpform) free(miscptr); freemischttpform = 0; hydra_child_exit(0); break; case 4: /* silent error exit */ if (sock >= 0) sock = hydra_disconnect(sock); if (freemischttpform) free(miscptr); freemischttpform = 0; hydra_child_exit(1); break; default: if (freemischttpform) free(miscptr); freemischttpform = 0; hydra_report(stderr, "[ERROR] Caught unknown return code, exiting!\n"); hydra_child_exit(0); } run = next_run; } if (freemischttpform) free(miscptr); }
ptr_header_node initialize(char *ip, unsigned char options, char *miscptr) { ptr_header_node ptr_head = NULL; char *ptr, *ptr2, *proxy_string; if (webtarget != NULL && (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) { if (freemischttpform == 0) { if ((miscptr = malloc(strlen(ptr2) + 1)) != NULL) { freemischttpform = 1; strcpy(miscptr, ptr2); *ptr2 = 0; } } } else webtarget = NULL; } if (cmdlinetarget != NULL && webtarget == NULL) webtarget = cmdlinetarget; else if (webtarget == NULL && cmdlinetarget == NULL) webtarget = hydra_address2string(ip); if (port != 0) webport = port; else if ((options & OPTION_SSL) == 0) webport = PORT_HTTP; else webport = PORT_HTTP_SSL; sprintf(bufferurl, "%.1000s", miscptr); url = bufferurl; ptr = url; while (*ptr != 0 && (*ptr != ':' || *(ptr - 1) == '\\')) ptr++; if (*ptr != 0) *ptr++ = 0; variables = ptr; while (*ptr != 0 && (*ptr != ':' || *(ptr - 1) == '\\')) ptr++; if (*ptr != 0) *ptr++ = 0; cond = ptr; while (*ptr != 0 && (*ptr != ':' || *(ptr - 1) == '\\')) ptr++; if (*ptr != 0) *ptr++ = 0; optional1 = ptr; if (strstr(url, "\\:") != NULL) { if ((ptr = malloc(strlen(url))) != NULL) { strcpy(ptr, hydra_strrep(url, "\\:", ":")); url = ptr; } } if (strstr(variables, "\\:") != NULL) { if ((ptr = malloc(strlen(variables))) != NULL) { strcpy(ptr, hydra_strrep(variables, "\\:", ":")); variables = ptr; } } if (strstr(cond, "\\:") != NULL) { if ((ptr = malloc(strlen(cond))) != NULL) { strcpy(ptr, hydra_strrep(cond, "\\:", ":")); cond = ptr; } } if (url == NULL || variables == NULL || cond == NULL /*|| optional1 == NULL */ ) hydra_child_exit(2); if (*cond == 0) { fprintf(stderr, "[ERROR] invalid number of parameters in module option\n"); return NULL; } sprintf(cookieurl, "%.1000s", url); //conditions now have to contain F or S to set the fail or success condition if (*cond != 0 && (strpos(cond, "F=") == 0)) { success_cond = 0; cond += 2; } else if (*cond != 0 && (strpos(cond, "S=") == 0)) { success_cond = 1; cond += 2; } else { //by default condition is a fail success_cond = 0; } /* * Parse the user-supplied options. * Beware of the backslashes (\)! */ while (*optional1 != 0) { switch (optional1[0]) { case 'c': // fall through case 'C': ptr = optional1 + 2; while (*ptr != 0 && (*ptr != ':' || *(ptr - 1) == '\\')) ptr++; if (*ptr != 0) *ptr++ = 0; sprintf(cookieurl, "%.1000s", hydra_strrep(optional1 + 2, "\\:", ":")); optional1 = ptr; break; case 'h': // add a new header at the end ptr = optional1 + 2; while (*ptr != 0 && *ptr != ':') ptr++; if (*(ptr - 1) == '\\') *(ptr - 1) = 0; if (*ptr != 0){ *ptr = 0; ptr += 2; } ptr2 = ptr; while (*ptr2 != 0 && (*ptr2 != ':' || *(ptr2 - 1) == '\\')) ptr2++; if (*ptr2 != 0) *ptr2++ = 0; /* * At this point: * - (optional1 + 2) contains the header's name * - ptr contains the header's value */ if (add_header(&ptr_head, optional1 + 2, hydra_strrep(ptr, "\\:", ":"), HEADER_TYPE_USERHEADER)) { // Success: break the switch and go ahead optional1 = ptr2; break; } // Error: abort execution hydra_report(stderr, "[ERROR] Out of memory for HTTP headers."); return NULL; case 'H': // add a new header, or replace an existing one's value ptr = optional1 + 2; while (*ptr != 0 && *ptr != ':') ptr++; if (*(ptr - 1) == '\\') *(ptr - 1) = 0; if (*ptr != 0){ *ptr = 0; ptr += 2; } ptr2 = ptr; while (*ptr2 != 0 && (*ptr2 != ':' || *(ptr2 - 1) == '\\')) ptr2++; if (*ptr2 != 0) *ptr2++ = 0; /* * At this point: * - (optional1 + 2) contains the header's name * - ptr contains the header's value */ if (add_header(&ptr_head, optional1 + 2, hydra_strrep(ptr, "\\:", ":"), HEADER_TYPE_USERHEADER_REPL)) { // Success: break the switch and go ahead optional1 = ptr2; break; } // Error: abort execution hydra_report(stderr, "[ERROR] Out of memory for HTTP headers."); return NULL; // no default } } /* again: no snprintf to be portable. dont worry, buffer cant overflow */ if (use_proxy == 1 && proxy_authentication != NULL) { // proxy with authentication add_header(&ptr_head, "Host", webtarget, HEADER_TYPE_DEFAULT); add_header(&ptr_head, "User-Agent", "Mozilla 5.0 (Hydra Proxy Auth)", HEADER_TYPE_DEFAULT); proxy_string = (char *) malloc(strlen(proxy_authentication) + 6); if (proxy_string) { strcpy(proxy_string, "Basic "); strncat(proxy_string, proxy_authentication, strlen(proxy_authentication) - 6); add_header(&ptr_head, "Proxy-Authorization", proxy_string, HEADER_TYPE_DEFAULT); } else { hydra_report(stderr, "Out of memory for \"Proxy-Authorization\" header."); return NULL; } if (getcookie) { //doing a GET to save cookies cookie_request = stringify_headers(&ptr_head); } normal_request = stringify_headers(&ptr_head); } else { if (use_proxy == 1) { // proxy without authentication add_header(&ptr_head, "Host", webtarget, HEADER_TYPE_DEFAULT); add_header(&ptr_head, "User-Agent", "Mozilla/5.0 (Hydra Proxy)", HEADER_TYPE_DEFAULT); if (getcookie) { //doing a GET to get cookies cookie_request = stringify_headers(&ptr_head); } normal_request = stringify_headers(&ptr_head); } else { // direct web server, no proxy add_header(&ptr_head, "Host", webtarget, HEADER_TYPE_DEFAULT); add_header(&ptr_head, "User-Agent", "Mozilla/5.0 (Hydra)", HEADER_TYPE_DEFAULT); if (getcookie) { //doing a GET to save cookies cookie_request = stringify_headers(&ptr_head); } normal_request = stringify_headers(&ptr_head); } } return ptr_head; }
int start_ldap(int s, char *ip, int port, unsigned char options, char *miscptr, FILE * fp, char version, int auth_method) { char *empty = ""; char *login = "", *pass; unsigned char buffer[512]; int length = 0; int ldap_auth_mechanism = auth_method; /* The LDAP "simple" method has three modes of operation: * anonymous= no user no pass * unauthenticated= user but no pass * user/password authenticated= user and pass */ if ((miscptr != NULL) && (ldap_auth_mechanism == AUTH_CLEAR)) { login = miscptr; } else { if (strlen(login = hydra_get_next_login()) == 0) login = empty; } if (strlen(pass = hydra_get_next_password()) == 0) pass = empty; switch (ldap_auth_mechanism) { case AUTH_CLEAR: length = 14 + strlen(login) + strlen(pass); break; #ifdef LIBOPENSSL case AUTH_CRAMMD5: length = 14 + strlen(miscptr) + strlen("CRAM-MD5") + 2; break; case AUTH_DIGESTMD5: length = 14 + strlen(miscptr) + strlen("DIGEST-MD5") + 2; break; #endif } memset(buffer, 0, sizeof(buffer)); buffer[0] = 48; buffer[1] = length - 2; buffer[2] = 2; buffer[3] = 1; buffer[4] = counter % 256; buffer[5] = 96; buffer[6] = length - 7; buffer[7] = 2; buffer[8] = 1; buffer[9] = version; buffer[10] = 4; if (ldap_auth_mechanism == AUTH_CLEAR) { buffer[11] = strlen(login); /* DN */ memcpy(&buffer[12], login, strlen(login)); buffer[12 + strlen(login)] = (unsigned char) 128; buffer[13 + strlen(login)] = strlen(pass); memcpy(&buffer[14 + strlen(login)], pass, strlen(pass)); /* PASS */ } else { char *authm = "DIGEST-MD5"; if (ldap_auth_mechanism == AUTH_CRAMMD5) { authm = "CRAM-MD5"; } if ((strlen(miscptr)) > sizeof(buffer) - 16 - strlen(authm)) { miscptr[sizeof(buffer) - 16 - strlen(authm)] = '\0'; } buffer[11] = strlen(miscptr); /* DN */ memcpy(&buffer[12], miscptr, strlen(miscptr)); buffer[12 + strlen(miscptr)] = 163; buffer[13 + strlen(miscptr)] = 2 + strlen(authm); buffer[14 + strlen(miscptr)] = 4; buffer[15 + strlen(miscptr)] = strlen(authm); memcpy(&buffer[16 + strlen(miscptr)], authm, strlen(authm)); } if (hydra_send(s, (char *) buffer, length, 0) < 0) return 1; if ((buf = (unsigned char *) hydra_receive_line(s)) == NULL) return 1; if (buf[0] != 0 && buf[0] != 32 && buf[9] == 2) { if (verbose) hydra_report(stderr, "[VERBOSE] Protocol invalid\n"); free(buf); return 3; } if (buf[0] != 0 && buf[0] != 32 && buf[9] == 13) { if (verbose) hydra_report(stderr, "[VERBOSE] Confidentiality required, TLS has to be enabled\n"); tls_required = 1; free(buf); return 1; } if ((buf[0] != 0 && buf[0] != 32) && buf[9] == 34) { hydra_report(stderr, "[ERROR] Invalid DN Syntax\n"); hydra_child_exit(2); free(buf); return 3; } #ifdef LIBOPENSSL /* one more step auth for CRAM and DIGEST */ if (ldap_auth_mechanism == AUTH_CRAMMD5) { /* get the challenge, need to extract it */ char *ptr; char buf2[32]; ptr = strstr((char *) buf, "<"); sasl_cram_md5(buf2, pass, ptr); if (buf2 == NULL) return 1; counter++; if (strstr(miscptr, "^USER^") != NULL) { miscptr = hydra_strrep(miscptr, "^USER^", login); } length = 12 + strlen(miscptr) + 4 + strlen("CRAM-MD5") + 2 + strlen(login) + 1 + strlen(buf2); memset(buffer, 0, sizeof(buffer)); buffer[0] = 48; buffer[1] = length - 2; buffer[2] = 2; buffer[3] = 1; buffer[4] = counter % 256; buffer[5] = 96; buffer[6] = length - 7; buffer[7] = 2; buffer[8] = 1; buffer[9] = version; buffer[10] = 4; buffer[11] = strlen(miscptr); /* DN */ memcpy(&buffer[12], miscptr, strlen(miscptr)); buffer[12 + strlen(miscptr)] = 163; buffer[13 + strlen(miscptr)] = 2 + strlen("CRAM-MD5") + 2 + strlen(login) + 1 + strlen(buf2); buffer[14 + strlen(miscptr)] = 4; buffer[15 + strlen(miscptr)] = strlen("CRAM-MD5"); memcpy(&buffer[16 + strlen(miscptr)], "CRAM-MD5", strlen("CRAM-MD5")); buffer[16 + strlen(miscptr) + strlen("CRAM-MD5")] = 4; buffer[17 + strlen(miscptr) + strlen("CRAM-MD5")] = strlen(login) + 1 + strlen(buf2); memcpy(&buffer[18 + strlen(miscptr) + strlen("CRAM-MD5")], login, strlen(login)); buffer[18 + strlen(miscptr) + strlen("CRAM-MD5") + strlen(login)] = ' '; memcpy(&buffer[18 + strlen(miscptr) + strlen("CRAM-MD5") + strlen(login) + 1], buf2, strlen(buf2)); if (hydra_send(s, (char *) buffer, length, 0) < 0) return 1; free(buf); if ((buf = (unsigned char *) hydra_receive_line(s)) == NULL) return 1; } else { if (ldap_auth_mechanism == AUTH_DIGESTMD5) { char *ptr; char buffer2[500]; int ind = 0; ptr = strstr((char *) buf, "realm="); counter++; if (strstr(miscptr, "^USER^") != NULL) { miscptr = hydra_strrep(miscptr, "^USER^", login); } sasl_digest_md5(buffer2, login, pass, ptr, miscptr, "ldap", NULL, 0, NULL); if (buffer2 == NULL) { free(buf); return 3; } length = 26 + strlen(miscptr) + strlen("DIGEST-MD5") + strlen(buffer2); memset(buffer, 0, sizeof(buffer)); ind = 0; buffer[ind] = 48; ind++; buffer[ind] = 130; ind++; if (length - 4 > 255) { buffer[ind] = 1; ind++; buffer[ind] = length - 256 - 4; ind++; } else { buffer[ind] = 0; ind++; buffer[ind] = length - 4; ind++; } buffer[ind] = 2; ind++; buffer[ind] = 1; ind++; buffer[ind] = counter % 256; ind++; buffer[ind] = 96; /*0x60 */ ind++; buffer[ind] = 130; ind++; if (length - 7 - 4 > 255) { buffer[ind] = 1; ind++; buffer[ind] = length - 256 - 11; ind++; } else { buffer[ind] = 0; ind++; buffer[ind] = length - 11; ind++; } buffer[ind] = 2; ind++; buffer[ind] = 1; ind++; buffer[ind] = version; ind++; buffer[ind] = 4; ind++; buffer[ind] = strlen(miscptr); ind++; memcpy(&buffer[ind], miscptr, strlen(miscptr)); /*DN*/ buffer[ind + strlen(miscptr)] = 163; //0xa3 ind++; buffer[ind + strlen(miscptr)] = 130; //0x82 ind++; if (strlen(buffer2) + 6 + strlen("DIGEST-MD5") > 255) { buffer[ind + strlen(miscptr)] = 1; ind++; buffer[ind + strlen(miscptr)] = strlen(buffer2) + 6 + strlen("DIGEST-MD5") - 256; } else { buffer[ind + strlen(miscptr)] = 0; ind++; buffer[ind + strlen(miscptr)] = strlen(buffer2) + 6 + strlen("DIGEST-MD5"); } ind++; buffer[ind + strlen(miscptr)] = 4; ind++; buffer[ind + strlen(miscptr)] = strlen("DIGEST-MD5"); ind++; memcpy(&buffer[ind + strlen(miscptr)], "DIGEST-MD5", strlen("DIGEST-MD5")); buffer[ind + strlen(miscptr) + strlen("DIGEST-MD5")] = 4; ind++; buffer[ind + strlen(miscptr) + strlen("DIGEST-MD5")] = 130; ind++; if (strlen(buffer2) > 255) { buffer[ind + strlen(miscptr) + strlen("DIGEST-MD5")] = 1; ind++; buffer[ind + strlen(miscptr) + strlen("DIGEST-MD5")] = strlen(buffer2) - 256; } else { buffer[ind + strlen(miscptr) + strlen("DIGEST-MD5")] = 0; ind++; buffer[ind + strlen(miscptr) + strlen("DIGEST-MD5")] = strlen(buffer2); } ind++; memcpy(&buffer[ind + strlen(miscptr) + strlen("DIGEST-MD5")], buffer2, strlen(buffer2)); ind++; if (hydra_send(s, (char *) buffer, length, 0) < 0) return 1; free(buf); if ((buf = (unsigned char *) hydra_receive_line(s)) == NULL) return 1; } } #endif /* success is: 0a 01 00 - failure is: 0a 01 31 */ if ((buf[0] != 0 && buf[9] == 0) || (buf[0] != 32 && buf[9] == 32)) { hydra_report_found_host(port, ip, "ldap", fp); hydra_completed_pair_found(); free(buf); if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) return 3; return 1; } if ((buf[0] != 0 && buf[0] != 32) && buf[9] == 7) { hydra_report(stderr, "[ERROR] Unknown authentication method\n"); free(buf); hydra_child_exit(2); } if ((buf[0] != 0 && buf[0] != 32) && buf[9] == 53) { if (verbose) hydra_report(stderr, "[VERBOSE] Server unwilling to perform action, maybe deny by server config or too busy when tried login: %s password: %s\n", login, pass); free(buf); return 1; } if ((buf[0] != 0 && buf[0] != 32) && buf[9] == 2) { hydra_report(stderr, "[ERROR] Invalid protocol version, you tried ldap%c, better try ldap%c\n", version + '0', version == 2 ? '3' : '2'); free(buf); hydra_child_exit(2); sleep(1); hydra_child_exit(2); } //0 0x30, 0x84, 0x20, 0x20, 0x20, 0x10, 0x02, 0x01, //8 0x01, 0x61, 0x84, 0x20, 0x20, 0x20, 0x07, 0x0a, //16 0x01, 0x20, 0x04, 0x20, 0x04, 0x20, 0x00, 0x00, // this is for w2k8 active directory ldap auth if (buf[0] == 48 && buf[1] == 132) { if (buf[9] == 0x61 && buf[1] == 0x84) { if (buf[17] == 0 || buf[17] == 0x20) { hydra_report_found_host(port, ip, "ldap", fp); hydra_completed_pair_found(); free(buf); if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) return 3; return 1; } } } else { if (buf[9] != 49 && buf[9] != 2 && buf[9] != 53) { hydra_report(stderr, "[ERROR] Uh, unknown LDAP response! Please report this: \n"); print_hex((unsigned char *) buf, 24); free(buf); return 3; } } hydra_completed_pair(); free(buf); if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) return 3; return 2; }