diff --git a/hydra-http-form.c b/hydra-http-form.c index 857b359..4b02483 100644 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -49,24 +49,18 @@ Added fail or success condition, getting cookies, and allow 5 redirections by da */ -#include "hydra-mod.h" - -/* HTTP Header Types */ -#define HEADER_TYPE_USERHEADER 'h' -#define HEADER_TYPE_USERHEADER_REPL 'H' -#define HEADER_TYPE_DEFAULT 'D' -#define HEADER_TYPE_DEFAULT_REPL 'd' +#include "hydra-http.h" extern char *HYDRA_EXIT; char *buf; char *cond; -typedef struct header_node { +struct header_node { char *header; char *value; char type; struct header_node *next; -} t_header_node, *ptr_header_node; +}; typedef struct cookie_node { char *name; @@ -81,8 +75,6 @@ int32_t auth_flag = 0; char cookie[4096] = "", cmiscptr[1024]; -extern char *webtarget; -extern char *slash; int32_t webport, freemischttpform = 0; char bufferurl[6096 + 24], cookieurl[6096 + 24] = "", userheader[6096 + 24] = "", *url, *variables, *optional1; @@ -396,6 +388,90 @@ char *stringify_headers(ptr_header_node *ptr_head) { return headers_str; } +int32_t parse_options(char *miscptr, ptr_header_node *ptr_head) { + char *ptr, *ptr2; + + /* + * Parse the user-supplied options. + * Beware of the backslashes (\)! + */ + while (*miscptr != 0) { + switch (miscptr[0]) { + case 'c': // fall through + case 'C': + ptr = miscptr + 2; + while (*ptr != 0 && (*ptr != ':' || *(ptr - 1) == '\\')) + ptr++; + if (*ptr != 0) + *ptr++ = 0; + sprintf(cookieurl, "%.1000s", hydra_strrep(miscptr + 2, "\\:", ":")); + miscptr = ptr; + break; + case 'h': + // add a new header at the end + ptr = miscptr + 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, miscptr + 2, hydra_strrep(ptr, "\\:", ":"), HEADER_TYPE_USERHEADER)) { + // Success: break the switch and go ahead + miscptr = ptr2; + break; + } + // Error: abort execution + hydra_report(stderr, "[ERROR] Out of memory for HTTP headers (h)."); + return 0; + case 'H': + // add a new header, or replace an existing one's value + ptr = miscptr + 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, miscptr + 2, hydra_strrep(ptr, "\\:", ":"), HEADER_TYPE_USERHEADER_REPL)) { + // Success: break the switch and go ahead + miscptr = ptr2; + break; + } + // Error: abort execution + hydra_report(stderr, "[ERROR] Out of memory for HTTP headers (H)."); + return 0; + // no default + } + } + return 1; +} char *prepare_http_request(char *type, char *path, char *params, char *headers) { uint32_t reqlen = 0; @@ -1200,81 +1276,8 @@ ptr_header_node initialize(char *ip, unsigned char options, char *miscptr) { * 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 (h)."); - 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 (H)."); - return NULL; - // no default - } - } + if (!parse_options(optional1, &ptr_head)) + return NULL; /* again: no snprintf to be portable. don't worry, buffer can't overflow */ if (use_proxy == 1 && proxy_authentication[selected_proxy] != NULL) { diff --git a/hydra-http.c b/hydra-http.c index ddbec4c..db9b500 100644 --- a/hydra-http.c +++ b/hydra-http.c @@ -1,4 +1,4 @@ -#include "hydra-mod.h" +#include "hydra-http.h" #include "sasl.h" extern char *HYDRA_EXIT; @@ -8,10 +8,10 @@ char *http_buf = NULL; int32_t webport, freemischttp = 0; int32_t http_auth_mechanism = AUTH_BASIC; -int32_t start_http(int32_t s, char *ip, int32_t port, unsigned char options, char *miscptr, FILE * fp, char *type) { +int32_t start_http(int32_t s, char *ip, int32_t port, unsigned char options, char *miscptr, FILE * fp, char *type, ptr_header_node ptr_head) { char *empty = ""; - char *login, *pass, buffer[500], buffer2[500]; - char header[64] = "Content-Length: 0\r\n"; + char *login, *pass, *buffer, buffer2[500]; + char *header; char *ptr, *fooptr; int32_t complete_line = 0; char tmpreplybuf[1024] = "", *tmpreplybufptr; @@ -21,8 +21,15 @@ int32_t start_http(int32_t s, char *ip, int32_t port, unsigned char options, cha if (strlen(pass = hydra_get_next_password()) == 0) pass = empty; - if (strcmp(type, "POST") != 0) - header[0] = 0; + if (strcmp(type, "POST") == 0) + add_header(&ptr_head, "Content-Length", "0", HEADER_TYPE_DEFAULT); + + header = stringify_headers(&ptr_head); + + if(!(buffer = malloc(strlen(header) + 500))) { + free(header); + return 3; + } // we must reset this if buf is NULL and we do MD5 digest if (http_buf == NULL && http_auth_mechanism == AUTH_DIGESTMD5) @@ -62,6 +69,8 @@ int32_t start_http(int32_t s, char *ip, int32_t port, unsigned char options, cha fooptr = buffer2; sasl_digest_md5(fooptr, login, pass, buffer, miscptr, type, webtarget, webport, header); if (fooptr == NULL) { + free(buffer); + free(header); return 3; } @@ -97,8 +106,11 @@ int32_t start_http(int32_t s, char *ip, int32_t port, unsigned char options, cha buf1, header); } - if (hydra_send(s, buffer, strlen(buffer), 0) < 0) + if (hydra_send(s, buffer, strlen(buffer), 0) < 0) { + free(buffer); + free(header); return 1; + } //receive challenge if (http_buf != NULL) @@ -109,8 +121,11 @@ int32_t start_http(int32_t s, char *ip, int32_t port, unsigned char options, cha http_buf = hydra_receive_line(s); } - if (http_buf == NULL) + if (http_buf == NULL) { + free(buffer); + free(header); return 1; + } if (pos != NULL) { char *str; @@ -153,6 +168,8 @@ int32_t start_http(int32_t s, char *ip, int32_t port, unsigned char options, cha } if (hydra_send(s, buffer, strlen(buffer), 0) < 0) { + free(buffer); + free(header); return 1; } @@ -189,6 +206,8 @@ int32_t start_http(int32_t s, char *ip, int32_t port, unsigned char options, cha if (http_buf == NULL) { if (verbose) hydra_report(stderr, "[ERROR] Server did not answer\n"); + free(buffer); + free(header); return 3; } @@ -228,6 +247,8 @@ int32_t start_http(int32_t s, char *ip, int32_t port, unsigned char options, cha if (find_auth) { // free(http_buf); // http_buf = NULL; + free(buffer); + free(header); return 1; } } @@ -235,6 +256,8 @@ int32_t start_http(int32_t s, char *ip, int32_t port, unsigned char options, cha } // free(http_buf); // http_buf = NULL; + free(buffer); + free(header); if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) return 3; return 1; @@ -244,6 +267,7 @@ void service_http(char *ip, int32_t sp, unsigned char options, char *miscptr, FI int32_t run = 1, next_run = 1, sock = -1; int32_t myport = PORT_HTTP, mysslport = PORT_HTTP_SSL; char *ptr, *ptr2; + ptr_header_node ptr_head = NULL; hydra_register_socket(sp); if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) @@ -278,6 +302,17 @@ void service_http(char *ip, int32_t sp, unsigned char options, char *miscptr, FI else webport = mysslport; + /* Advance to options string */ + ptr = miscptr; + while (*ptr != 0 && (*ptr != ':' || *(ptr - 1) == '\\')) + ptr++; + if (*ptr != 0) + *ptr++ = 0; + optional1 = ptr; + + if (!parse_options(optional1, &ptr_head)) + run = 4; + while (1) { next_run = 0; switch (run) { @@ -306,7 +341,7 @@ void service_http(char *ip, int32_t sp, unsigned char options, char *miscptr, FI break; } case 2: /* run the cracking function */ - next_run = start_http(sock, ip, port, options, miscptr, fp, type); + next_run = start_http(sock, ip, port, options, miscptr, fp, type, ptr_head); break; case 3: /* clean exit */ if (sock >= 0) @@ -353,5 +388,7 @@ int32_t service_http_init(char *ip, int32_t sp, unsigned char options, char *mis void usage_http(const char* service) { printf("Module %s requires the page to authenticate.\n" - "For example: \"/secret\" or \"http://bla.com/foo/bar\" or \"https://test.com:8080/members\"\n\n", service); + "The following parameters are optional:\n" + " (h|H)=My-Hdr\\: foo to send a user defined HTTP header with each request\n" + "For example: \"/secret\" or \"http://bla.com/foo/bar:H=Cookie\\: sessid=aaaa\" or \"https://test.com:8080/members\"\n\n", service); } diff --git a/hydra-http.h b/hydra-http.h new file mode 100644 index 0000000..b6b4c2b --- /dev/null +++ b/hydra-http.h @@ -0,0 +1,21 @@ +#ifndef _HYDRA_HTTP_H +#define _HYDRA_HTTP_H + +#include "hydra-mod.h" + +/* HTTP Header Types */ +#define HEADER_TYPE_USERHEADER 'h' +#define HEADER_TYPE_USERHEADER_REPL 'H' +#define HEADER_TYPE_DEFAULT 'D' +#define HEADER_TYPE_DEFAULT_REPL 'd' + +typedef struct header_node t_header_node, *ptr_header_node; + +extern char *webtarget; +extern char *slash; +extern char *optional1; + +extern int32_t parse_options(char *miscptr, ptr_header_node * ptr_head); +extern int32_t add_header(ptr_header_node * ptr_head, char *header, char *value, char type); +extern char *stringify_headers(ptr_header_node *ptr_head); +#endif