mirror of
https://github.com/vanhauser-thc/thc-hydra.git
synced 2025-08-21 05:43:52 -07:00
Merge pull request #342 from mathewmarcus/add_feature_321
Optionally add request headers to http-get
This commit is contained in:
commit
5d94930978
3 changed files with 157 additions and 96 deletions
|
@ -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) {
|
||||
|
|
57
hydra-http.c
57
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);
|
||||
}
|
||||
|
|
21
hydra-http.h
Normal file
21
hydra-http.h
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue