multipart feature finished

This commit is contained in:
motypi 2025-02-07 14:27:04 +01:00
commit 65c897da68

View file

@ -8,7 +8,7 @@ web-based login forms that require username and password variables via
either a GET or POST request. either a GET or POST request.
The module works similarly to the HTTP basic auth module and will honour The module works similarly to the HTTP basic auth module and will honour
proxy mode (with authentication) as well as SSL. The module can be invoked proxy mode (with authenticaion) as well as SSL. The module can be invoked
with the service names of "http-get-form", "http-post-form", with the service names of "http-get-form", "http-post-form",
"https-get-form" and "https-post-form". "https-get-form" and "https-post-form".
@ -76,7 +76,6 @@ char bufferurl[6096 + 24], cookieurl[6096 + 24] = "", userheader[6096 + 24] = ""
#define MAX_REDIRECT 8 #define MAX_REDIRECT 8
#define MAX_CONTENT_LENGTH 20 #define MAX_CONTENT_LENGTH 20
#define MAX_CONTENT_DISPOSITION 200
#define MAX_PROXY_LENGTH 2048 // sizeof(cookieurl) * 2 #define MAX_PROXY_LENGTH 2048 // sizeof(cookieurl) * 2
char redirected_url_buff[2048] = ""; char redirected_url_buff[2048] = "";
@ -85,11 +84,6 @@ int32_t redirected_cpt = MAX_REDIRECT;
char *cookie_request = NULL, *normal_request = NULL; // Buffers for HTTP headers char *cookie_request = NULL, *normal_request = NULL; // Buffers for HTTP headers
void service_http_form(char *ip, int32_t sp, unsigned char options, char *miscptr,
FILE *fp, int32_t port, char *hostname, char *type,
ptr_header_node *ptr_head, ptr_cookie_node *ptr_cookie);
/* /*
* Function to perform some initial setup. * Function to perform some initial setup.
*/ */
@ -108,8 +102,6 @@ ptr_header_node header_exists(ptr_header_node *ptr_head, char *header_name, char
return found_header; return found_header;
} }
#if defined(__sun) #if defined(__sun)
/* Written by Kaveh R. Ghazi <ghazi@caip.rutgers.edu> */ /* Written by Kaveh R. Ghazi <ghazi@caip.rutgers.edu> */
@ -463,8 +455,8 @@ int32_t parse_options(char *miscptr, ptr_header_node *ptr_head) {
else else
miscptr += strlen(miscptr); miscptr += strlen(miscptr);
break; break;
case 'm': //fall through case 'm': // fall through
case 'M': case 'M':
multipart_mode = 1; multipart_mode = 1;
tmp = strchr(miscptr, ':'); tmp = strchr(miscptr, ':');
if (tmp) if (tmp)
@ -551,100 +543,96 @@ int32_t parse_options(char *miscptr, ptr_header_node *ptr_head) {
} }
char *build_multipart_body(char *multipart_boundary) { char *build_multipart_body(char *multipart_boundary) {
if (!variables) if (!variables)
return NULL; return NULL;
char *body = NULL; char *body = NULL;
size_t body_size = 0; size_t body_size = 0;
// Duplicate "variables" for tokenizing // Duplicate "variables" for tokenizing
char *vars_dup = strdup(variables); char *vars_dup = strdup(variables);
if (!vars_dup) if (!vars_dup)
return NULL; return NULL;
// Tokenize the string using '&' as a delimiter // Tokenize the string using '&' as a delimiter
char *pair = strtok(vars_dup, "&"); char *pair = strtok(vars_dup, "&");
while (pair != NULL) { while (pair != NULL) {
// Find the '=' separator in each pair // Find the '=' separator in each pair
char *equal_sign = strchr(pair, '='); char *equal_sign = strchr(pair, '=');
if (!equal_sign) { if (!equal_sign) {
pair = strtok(NULL, "&"); pair = strtok(NULL, "&");
continue; continue;
} }
*equal_sign = '\0'; *equal_sign = '\0';
char *key = pair; char *key = pair;
char *value = equal_sign + 1; char *value = equal_sign + 1;
// Build the multipart section for the field // Build the multipart section for the field
// Expected format: int section_len = snprintf(NULL, 0,
// --<boundary>\r\n "--%s\r\n"
// Content-Disposition: form-data; name="<key>"\r\n "Content-Disposition: form-data; name=\"%s\"\r\n"
// \r\n "\r\n"
// <value>\r\n "%s\r\n",
int section_len = snprintf(NULL, 0, multipart_boundary, key, value);
"--%s\r\n"
"Content-Disposition: form-data; name=\"%s\"\r\n"
"\r\n"
"%s\r\n",
multipart_boundary, key, value);
char *section = malloc(section_len + 1); char *section = malloc(section_len + 1);
if (!section) { if (!section) {
free(body); free(body);
free(vars_dup); free(vars_dup);
return NULL; return NULL;
} }
snprintf(section, section_len + 1, snprintf(section, section_len + 1,
"--%s\r\n" "--%s\r\n"
"Content-Disposition: form-data; name=\"%s\"\r\n" "Content-Disposition: form-data; name=\"%s\"\r\n"
"\r\n" "\r\n"
"%s\r\n", "%s\r\n",
multipart_boundary, key, value); multipart_boundary, key, value);
// Reallocate the body buffer to add this section // Reallocate the body buffer to add this section
size_t new_body_size = body_size + section_len; size_t new_body_size = body_size + section_len;
char *new_body = realloc(body, new_body_size + 1); // +1 for null terminator char *new_body = realloc(body, new_body_size + 1); // +1 for null terminator
if (!new_body) { if (!new_body) {
free(section); free(section);
free(body); free(body);
free(vars_dup); free(vars_dup);
return NULL; return NULL;
} }
body = new_body; body = new_body;
if (body_size == 0) if (body_size == 0)
strcpy(body, section); strcpy(body, section);
else else
strcat(body, section); strcat(body, section);
body_size = new_body_size; body_size = new_body_size;
free(section); free(section);
pair = strtok(NULL, "&"); pair = strtok(NULL, "&");
} }
free(vars_dup); free(vars_dup);
// Append the closing boundary: --<boundary>--\r\n // Append the closing boundary: --<boundary>--\r\n
int closing_len = snprintf(NULL, 0, "--%s--\r\n", multipart_boundary); int closing_len = snprintf(NULL, 0, "--%s--\r\n", multipart_boundary);
char *closing = malloc(closing_len + 1); char *closing = malloc(closing_len + 1);
if (!closing) { if (!closing) {
free(body); free(body);
return NULL; return NULL;
} }
snprintf(closing, closing_len + 1, "--%s--\r\n", multipart_boundary); snprintf(closing, closing_len + 1, "--%s--\r\n", multipart_boundary);
size_t final_size = body_size + closing_len; size_t final_size = body_size + closing_len;
char *final_body = realloc(body, final_size + 1); char *final_body = realloc(body, final_size + 1);
if (!final_body) { if (!final_body) {
free(closing); free(closing);
free(body); free(body);
return NULL; return NULL;
} }
body = final_body; body = final_body;
strcat(body, closing); strcat(body, closing);
free(closing); free(closing);
return body; return body;
} }
char *prepare_http_request(char *type, char *path, char *params, char *headers) { char *prepare_http_request(char *type, char *path, char *params, char *headers) {
uint32_t reqlen = 0; uint32_t reqlen = 0;
char *http_request = NULL; char *http_request = NULL;
@ -785,7 +773,7 @@ int32_t analyze_server_response(int32_t s) {
if ((ptr = hydra_strcasestr(cookie, tmpname)) != NULL) { if ((ptr = hydra_strcasestr(cookie, tmpname)) != NULL) {
// yes it is. // yes it is.
// if the cookie is not in the beginning of the cookiejar, copy the // if the cookie is not in the beginning of the cookiejar, copy the
// ones before // ones before
if (ptr != cookie && *(ptr - 1) == ' ') { if (ptr != cookie && *(ptr - 1) == ' ') {
strncpy(tmpcookie, cookie, ptr - cookie - 2); strncpy(tmpcookie, cookie, ptr - cookie - 2);
tmpcookie[ptr - cookie - 2] = 0; tmpcookie[ptr - cookie - 2] = 0;
@ -845,9 +833,7 @@ void hydra_reconnect(int32_t s, char *ip, int32_t port, unsigned char options, c
} }
} }
int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options, int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options, char *miscptr, FILE *fp, char *hostname, char *type, ptr_header_node ptr_head, ptr_cookie_node ptr_cookie) {
char *miscptr, FILE *fp, char *hostname, char *type,
ptr_header_node ptr_head, ptr_cookie_node ptr_cookie) {
char *empty = ""; char *empty = "";
char *login, *pass, clogin[256], cpass[256], b64login[345], b64pass[345]; char *login, *pass, clogin[256], cpass[256], b64login[345], b64pass[345];
char header[8096], *upd3variables; char header[8096], *upd3variables;
@ -855,13 +841,14 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options
char *http_request = NULL; char *http_request = NULL;
int32_t found = !success_cond, i, j; int32_t found = !success_cond, i, j;
char content_length[MAX_CONTENT_LENGTH], proxy_string[MAX_PROXY_LENGTH]; char content_length[MAX_CONTENT_LENGTH], proxy_string[MAX_PROXY_LENGTH];
char content_type[256];
memset(header, 0, sizeof(header)); memset(header, 0, sizeof(header));
cookie[0] = 0; cookie[0] = 0; // reset cookies from potential previous attempt
if (use_proxy > 0 && proxy_count > 0) if (use_proxy > 0 && proxy_count > 0)
selected_proxy = random() % proxy_count; selected_proxy = random() % proxy_count;
// Take the next login/pass pair
if (strlen(login = hydra_get_next_login()) == 0) if (strlen(login = hydra_get_next_login()) == 0)
login = empty; login = empty;
if (strlen(pass = hydra_get_next_password()) == 0) if (strlen(pass = hydra_get_next_password()) == 0)
@ -874,16 +861,37 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options
clogin[sizeof(clogin) - 1] = 0; clogin[sizeof(clogin) - 1] = 0;
strncpy(cpass, html_encode(pass), sizeof(cpass) - 1); strncpy(cpass, html_encode(pass), sizeof(cpass) - 1);
cpass[sizeof(cpass) - 1] = 0; cpass[sizeof(cpass) - 1] = 0;
upd3variables = hydra_strrep(variables, "^USER^", clogin);
upd3variables = hydra_strrep(upd3variables, "^PASS^", cpass);
upd3variables = hydra_strrep(upd3variables, "^USER64^", b64login);
upd3variables = hydra_strrep(upd3variables, "^PASS64^", b64pass);
if (multipart_mode) {
char multipart_boundary[32] = "----THC-HydraBoundaryz2Z2z";
snprintf(content_type, sizeof(content_type), "multipart/form-data; boundary=%s", multipart_boundary);
char *multipart_body = build_multipart_body(multipart_boundary);
upd3variables = multipart_body;
upd3variables = hydra_strrep(upd3variables, "^USER^", clogin);
upd3variables = hydra_strrep(upd3variables, "^PASS^", cpass);
upd3variables = hydra_strrep(upd3variables, "^USER64^", b64login);
upd3variables = hydra_strrep(upd3variables, "^PASS64^", b64pass);
}else{
snprintf(content_type, sizeof(content_type), "application/x-www-form-urlencoded");
upd3variables = hydra_strrep(variables, "^USER^", clogin);
upd3variables = hydra_strrep(upd3variables, "^PASS^", cpass);
upd3variables = hydra_strrep(upd3variables, "^USER64^", b64login);
upd3variables = hydra_strrep(upd3variables, "^PASS64^", b64pass);
}
// Replace the user/pass placeholders in the user-supplied headers
hdrrep(&ptr_head, "^USER^", clogin); hdrrep(&ptr_head, "^USER^", clogin);
hdrrep(&ptr_head, "^PASS^", cpass); hdrrep(&ptr_head, "^PASS^", cpass);
hdrrep(&ptr_head, "^USER64^", b64login); hdrrep(&ptr_head, "^USER64^", b64login);
hdrrep(&ptr_head, "^PASS64^", b64pass); hdrrep(&ptr_head, "^PASS64^", b64pass);
/* again: no snprintf to be portable. don't worry, buffer can't overflow */
if (use_proxy == 1 && proxy_authentication[selected_proxy] != NULL) { if (use_proxy == 1 && proxy_authentication[selected_proxy] != NULL) {
if (getcookie) { if (getcookie) {
memset(proxy_string, 0, sizeof(proxy_string)); memset(proxy_string, 0, sizeof(proxy_string));
@ -893,11 +901,12 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options
http_request = prepare_http_request("GET", proxy_string, NULL, cookie_request); http_request = prepare_http_request("GET", proxy_string, NULL, cookie_request);
if (hydra_send(s, http_request, strlen(http_request), 0) < 0) if (hydra_send(s, http_request, strlen(http_request), 0) < 0)
return 1; return 1;
i = analyze_server_response(s); i = analyze_server_response(s); // ignore result
if (strlen(cookie) > 0) if (strlen(cookie) > 0)
process_cookies(&ptr_cookie, cookie); process_cookies(&ptr_cookie, cookie);
hydra_reconnect(s, ip, port, options, hostname); hydra_reconnect(s, ip, port, options, hostname);
} }
// now prepare for the "real" request
if (strcmp(type, "POST") == 0) { if (strcmp(type, "POST") == 0) {
memset(proxy_string, 0, sizeof(proxy_string)); memset(proxy_string, 0, sizeof(proxy_string));
snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, url); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, url);
@ -907,69 +916,10 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options
else else
add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT);
if (!header_exists(&ptr_head, "Content-Type", 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); if (multipart_mode)
if (cookie_header != NULL) add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT);
free(cookie_header); else
cookie_header = stringify_cookies(ptr_cookie); add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT);
if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT))
add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT);
else
hdrrepv(&ptr_head, "Cookie", cookie_header);
if (normal_request != NULL)
free(normal_request);
normal_request = stringify_headers(&ptr_head);
if (http_request != NULL)
free(http_request);
http_request = prepare_http_request("POST", proxy_string, upd3variables, normal_request);
if (hydra_send(s, http_request, strlen(http_request), 0) < 0) {
free(cookie_header);
return 1;
}
} else {
if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT))
hdrrepv(&ptr_head, "Content-Length", "0");
if (cookie_header != NULL)
free(cookie_header);
cookie_header = stringify_cookies(ptr_cookie);
if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT))
add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT);
else
hdrrepv(&ptr_head, "Cookie", cookie_header);
if (normal_request != NULL)
free(normal_request);
normal_request = stringify_headers(&ptr_head);
if (http_request != NULL)
free(http_request);
http_request = prepare_http_request("GET", proxy_string, upd3variables, normal_request);
if (hydra_send(s, http_request, strlen(http_request), 0) < 0) {
free(cookie_header);
return 1;
}
}
} else if (use_proxy == 1) {
if (getcookie) {
memset(proxy_string, 0, sizeof(proxy_string));
snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, cookieurl);
if (http_request != NULL)
free(http_request);
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);
if (strlen(cookie) > 0)
process_cookies(&ptr_cookie, cookie);
hydra_reconnect(s, ip, port, options, hostname);
}
if (strcmp(type, "POST") == 0) {
memset(proxy_string, 0, sizeof(proxy_string));
snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, url);
snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)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);
if (cookie_header != NULL) if (cookie_header != NULL)
free(cookie_header); free(cookie_header);
cookie_header = stringify_cookies(ptr_cookie); cookie_header = stringify_cookies(ptr_cookie);
@ -1009,102 +959,137 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options
} }
} }
} else { } else {
/* Direct access to the server (no proxy) */ if (use_proxy == 1) {
normal_request = NULL; // proxy without authentication
if (getcookie) { if (getcookie) {
if (http_request != NULL) // doing a GET to get cookies
free(http_request); memset(proxy_string, 0, sizeof(proxy_string));
http_request = prepare_http_request("GET", cookieurl, NULL, cookie_request); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s%.600s", webtarget, cookieurl);
if (hydra_send(s, http_request, strlen(http_request), 0) < 0) if (http_request != NULL)
return 1; free(http_request);
i = analyze_server_response(s); http_request = prepare_http_request("GET", proxy_string, NULL, cookie_request);
if (strlen(cookie) > 0) { if (hydra_send(s, http_request, strlen(http_request), 0) < 0)
process_cookies(&ptr_cookie, cookie); return 1;
i = analyze_server_response(s); // ignore result
if (strlen(cookie) > 0)
process_cookies(&ptr_cookie, cookie);
hydra_reconnect(s, ip, port, options, hostname);
}
// 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%.600s", webtarget, url);
snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)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", content_type, HEADER_TYPE_DEFAULT);
if (cookie_header != NULL)
free(cookie_header);
cookie_header = stringify_cookies(ptr_cookie);
if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT))
add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT);
else
hdrrepv(&ptr_head, "Cookie", cookie_header);
if (normal_request != NULL) if (normal_request != NULL)
free(normal_request); free(normal_request);
normal_request = stringify_headers(&ptr_head); normal_request = stringify_headers(&ptr_head);
} if (http_request != NULL)
hydra_reconnect(s, ip, port, options, hostname); free(http_request);
} http_request = prepare_http_request("POST", proxy_string, upd3variables, normal_request);
if (multipart_mode) { if (hydra_send(s, http_request, strlen(http_request), 0) < 0) {
char *multipart_body = NULL; free(cookie_header);
char multipart_boundary[64] = "----THC-HydraBoundaryz2Z2z"; return 1;
multipart_body = build_multipart_body(multipart_boundary); }
if (multipart_body == NULL) { } else {
hydra_report(stderr, "[ERROR] Failed to build multipart body.\n"); if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT))
return 0; hdrrepv(&ptr_head, "Content-Length", "0");
} if (cookie_header != NULL)
snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)strlen(multipart_body)); free(cookie_header);
if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) cookie_header = stringify_cookies(ptr_cookie);
hdrrepv(&ptr_head, "Content-Length", content_length); if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT))
else add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT);
add_header(&ptr_head, "Content-Length", content_length, HEADER_TYPE_DEFAULT); else
hdrrepv(&ptr_head, "Cookie", cookie_header);
char content_type[256]; if (normal_request != NULL)
snprintf(content_type, sizeof(content_type) - 1, "multipart/form-data; boundary=%s", multipart_boundary); free(normal_request);
if (!header_exists(&ptr_head, "Content-Type", HEADER_TYPE_DEFAULT)) normal_request = stringify_headers(&ptr_head);
add_header(&ptr_head, "Content-Type", content_type, HEADER_TYPE_DEFAULT); if (http_request != NULL)
else free(http_request);
hdrrepv(&ptr_head, "Content-Type", content_type); http_request = prepare_http_request("GET", proxy_string, upd3variables, normal_request);
if (hydra_send(s, http_request, strlen(http_request), 0) < 0) {
if (cookie_header != NULL) free(cookie_header);
free(cookie_header); return 1;
cookie_header = stringify_cookies(ptr_cookie); }
if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT))
add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT);
else
hdrrepv(&ptr_head, "Cookie", cookie_header);
if (normal_request != NULL)
free(normal_request);
http_request = prepare_http_request("POST", url, multipart_body, normal_request);
free(multipart_body);
return 1;
}
if (strcmp(type, "POST") == 0) {
snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)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);
if (cookie_header != NULL)
free(cookie_header);
cookie_header = stringify_cookies(ptr_cookie);
if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT))
add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT);
else
hdrrepv(&ptr_head, "Cookie", cookie_header);
if (normal_request != NULL)
free(normal_request);
normal_request = stringify_headers(&ptr_head);
if (http_request != NULL)
free(http_request);
http_request = prepare_http_request("POST", url, upd3variables, normal_request);
if (hydra_send(s, http_request, strlen(http_request), 0) < 0) {
free(cookie_header);
return 1;
} }
} else { } else {
if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT)) // direct web server, no proxy
hdrrepv(&ptr_head, "Content-Length", "0"); normal_request = NULL;
if (cookie_header != NULL) if (getcookie) {
free(cookie_header); // doing a GET to save cookies
cookie_header = stringify_cookies(ptr_cookie); if (http_request != NULL)
if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT)) free(http_request);
add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT); http_request = prepare_http_request("GET", cookieurl, NULL, cookie_request);
else if (hydra_send(s, http_request, strlen(http_request), 0) < 0)
hdrrepv(&ptr_head, "Cookie", cookie_header); return 1;
if (normal_request != NULL) i = analyze_server_response(s); // ignore result
free(normal_request); if (strlen(cookie) > 0) {
normal_request = stringify_headers(&ptr_head); // printf("[DEBUG] Got cookie: %s\n", cookie);
if (http_request != NULL) process_cookies(&ptr_cookie, cookie);
free(http_request); if (normal_request != NULL)
http_request = prepare_http_request("GET", url, upd3variables, normal_request); free(normal_request);
if (hydra_send(s, http_request, strlen(http_request), 0) < 0) { normal_request = stringify_headers(&ptr_head);
free(cookie_header); }
return 1; hydra_reconnect(s, ip, port, options, hostname);
}
// now prepare for the "real" request
if (strcmp(type, "POST") == 0) {
snprintf(content_length, MAX_CONTENT_LENGTH - 1, "%d", (int32_t)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", content_type, HEADER_TYPE_DEFAULT);
if (cookie_header != NULL)
free(cookie_header);
cookie_header = stringify_cookies(ptr_cookie);
if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT))
add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT);
else
hdrrepv(&ptr_head, "Cookie", cookie_header);
if (normal_request != NULL)
free(normal_request);
normal_request = stringify_headers(&ptr_head);
if (http_request != NULL)
free(http_request);
http_request = prepare_http_request("POST", url, upd3variables, normal_request);
if (hydra_send(s, http_request, strlen(http_request), 0) < 0) {
free(cookie_header);
return 1;
}
} else {
if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT))
hdrrepv(&ptr_head, "Content-Length", "0");
if (cookie_header != NULL)
free(cookie_header);
cookie_header = stringify_cookies(ptr_cookie);
if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT))
add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT);
else
hdrrepv(&ptr_head, "Cookie", cookie_header);
if (normal_request != NULL)
free(normal_request);
normal_request = stringify_headers(&ptr_head);
if (http_request != NULL)
free(http_request);
http_request = prepare_http_request("GET", url, upd3variables, normal_request);
if (hydra_send(s, http_request, strlen(http_request), 0) < 0) {
free(cookie_header);
return 1;
}
} }
} }
} }
@ -1114,11 +1099,12 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options
found = analyze_server_response(s); found = analyze_server_response(s);
if (redirected_flag && code_302_is_success) if (redirected_flag && code_302_is_success) {
found = success_cond; found = success_cond;
}
if (auth_flag) { if (auth_flag) { // we received a 401 error - user may be using wrong module
if (code_401_is_failure) { if (code_401_is_failure) { // apparently they don't think so -- treat 401 as failure
hydra_completed_pair(); hydra_completed_pair();
return 1; return 1;
} else { } else {
@ -1133,18 +1119,159 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options
if (strlen(cookie) > 0) if (strlen(cookie) > 0)
process_cookies(&ptr_cookie, cookie); process_cookies(&ptr_cookie, cookie);
// if page was redirected, follow the location header
redirected_cpt = MAX_REDIRECT; redirected_cpt = MAX_REDIRECT;
if (debug) if (debug)
printf("[DEBUG] attempt result: found %d, redirect %d, location: %s\n", found, redirected_flag, redirected_url_buff); printf("[DEBUG] attempt result: found %d, redirect %d, location: %s\n", found, redirected_flag, redirected_url_buff);
while (found == 0 && redirected_flag && !code_302_is_success && while (found == 0 && redirected_flag && !code_302_is_success && (redirected_url_buff[0] != 0) && (redirected_cpt > 0)) {
(redirected_url_buff[0] != 0) && (redirected_cpt > 0)) { // we have to split the location
// Processing redirection (code omitted) char *startloc, *endloc;
char str[2048], str2[2048], str3[2048], str4[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) {
*endloc = 0;
}
if ((endloc = strchr(startloc, '\n')) != NULL) {
*endloc = 0;
}
strncpy(str, startloc, sizeof(str) - 1);
str[sizeof(str) - 1] = 0;
endloc = strchr(str, '/');
if (endloc != NULL) {
strncpy(str2, str, endloc - str);
str2[endloc - str] = 0;
} else {
strcpy(str2, str);
}
if (strlen(str) - strlen(str2) == 0) {
strcpy(str3, "/");
} else {
strncpy(str3, str + strlen(str2), strlen(str) - strlen(str2));
str3[strlen(str) - strlen(str2)] = 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) - 1);
str3[sizeof(str3) - 1] = 0;
}
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 (strrchr(str2, ':') == NULL && (port != 80 || port != 443)) {
sprintf(str4, "%.2000s:%d", str2, port);
strcpy(str2, str4);
}
if (verbose)
hydra_report(stderr, "[VERBOSE] Page redirected to http[s]://%s%s\n", str2, str3);
if (header_exists(&ptr_head, "Content-Length", HEADER_TYPE_DEFAULT))
hdrrepv(&ptr_head, "Content-Length", "0");
// re-use the above code to set cookies
if (cookie_header != NULL)
free(cookie_header);
cookie_header = stringify_cookies(ptr_cookie);
if (!header_exists(&ptr_head, "Cookie", HEADER_TYPE_DEFAULT))
add_header(&ptr_head, "Cookie", cookie_header, HEADER_TYPE_DEFAULT);
else
hdrrepv(&ptr_head, "Cookie", cookie_header);
// re-use the code above to check for proxy use
if (use_proxy == 1 && proxy_authentication[selected_proxy] != 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%.600s", webtarget, str3);
if (normal_request != NULL)
free(normal_request);
normal_request = stringify_headers(&ptr_head);
if (http_request != NULL)
free(http_request);
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%.600s", webtarget, str3);
if (normal_request != NULL)
free(normal_request);
normal_request = stringify_headers(&ptr_head);
if (http_request != NULL)
free(http_request);
http_request = prepare_http_request("GET", proxy_string, NULL, normal_request);
} else {
// direct web server, no proxy
hdrrepv(&ptr_head, "Host", str2);
if (normal_request != NULL)
free(normal_request);
normal_request = stringify_headers(&ptr_head);
if (http_request != NULL)
free(http_request);
http_request = prepare_http_request("GET", str3, NULL, normal_request);
}
}
hydra_reconnect(s, ip, port, options, hostname);
if (hydra_send(s, http_request, strlen(http_request), 0) < 0) {
free(cookie_header);
return 1;
}
found = analyze_server_response(s);
if (strlen(cookie) > 0)
process_cookies(&ptr_cookie, cookie);
}
} }
if (found != -1 && found == success_cond && // if the last status is still 3xx, set it as a false
((redirected_flag && code_302_is_success) || redirected_flag == 0 || success_cond == 1) && if (found != -1 && found == success_cond && ((redirected_flag && code_302_is_success) || redirected_flag == 0 || success_cond == 1) && redirected_cpt >= 0) {
redirected_cpt >= 0) {
hydra_report_found_host(port, ip, "www-form", fp); hydra_report_found_host(port, ip, "www-form", fp);
hydra_completed_pair_found(); hydra_completed_pair_found();
} else { } else {
@ -1154,6 +1281,83 @@ int32_t start_http_form(int32_t s, char *ip, int32_t port, unsigned char options
return 1; return 1;
} }
void service_http_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname, char *type, ptr_header_node *ptr_head, ptr_cookie_node *ptr_cookie) {
int32_t run = 1, next_run = 1, sock = -1;
int32_t 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) {
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, hostname);
port = mysslport;
}
if (sock < 0) {
hydra_report(stderr, "[ERROR] Child with pid %d terminating, cannot connect\n", (int32_t)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, hostname, type, *ptr_head, *ptr_cookie);
break;
case 3: /* clean exit */
if (sock >= 0)
sock = hydra_disconnect(sock);
hydra_child_exit(0);
break;
case 4: /* silent error exit */
if (sock >= 0)
sock = hydra_disconnect(sock);
hydra_child_exit(1);
break;
default:
hydra_report(stderr, "[ERROR] Caught unknown return code, exiting!\n");
hydra_child_exit(0);
}
run = next_run;
}
}
void service_http_get_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) {
ptr_cookie_node ptr_cookie = NULL;
ptr_header_node ptr_head = initialize(ip, options, miscptr);
if (ptr_head)
service_http_form(ip, sp, options, miscptr, fp, port, hostname, "GET", &ptr_head, &ptr_cookie);
else {
hydra_report(stderr, "[ERROR] Could not launch head. Error while initializing.\n");
hydra_child_exit(2);
}
}
void service_http_post_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) { void service_http_post_form(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) {
ptr_cookie_node ptr_cookie = NULL; ptr_cookie_node ptr_cookie = NULL;
ptr_header_node ptr_head = initialize(ip, options, miscptr); ptr_header_node ptr_head = initialize(ip, options, miscptr);