From bb53072a7392554bf9937665d7d14a468ea42c8a Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 12 Oct 2016 17:37:51 +0200 Subject: [PATCH] proxy file support implemented --- CHANGES | 3 + README | 21 ++-- hydra-http-form.c | 16 ++- hydra-http.c | 15 +-- hydra-mod.c | 56 +++++++---- hydra-mod.h | 12 ++- hydra.c | 247 +++++++++++++++++++++++++++++----------------- hydra.h | 2 + web/CHANGES | 7 +- web/README | 21 ++-- 10 files changed, 257 insertions(+), 143 deletions(-) diff --git a/CHANGES b/CHANGES index 667fdb0..31a59d4 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,9 @@ Changelog for hydra ------------------- Release 8.4-dev +* Proxy support re-implemented: + - HYDRA_PROXY[_HTTP] environment can be a text file with up to 64 entries + - HYDRA_PROXY_AUTH was deprecated, set login/password in HTTP_PROXY[_HTTP] * New command line option -y which disables -x 1aA interpretation, thanks to crondaemon for the patch * The protocols vnc, xmpp, telnet, imap, nntp and pcanywhere got accidentially long sleep commands due a patch in 8.2, fixed * Added special error message for clueless users :) diff --git a/README b/README index a1ef2ff..27a5bd1 100644 --- a/README +++ b/README @@ -256,18 +256,21 @@ from little endian to big endian, or from solaris to aix) HOW TO SCAN/CRACK OVER A PROXY ------------------------------ The environment variable HYDRA_PROXY_HTTP defines the web proxy (this works -just for the http/www service!). +just for the http services!). The following syntax is valid: HYDRA_PROXY_HTTP="http://123.45.67.89:8080/" -For all other services, use the HYDRA_PROXY variable to scan/crack -via by default a web proxy's CONNECT call. It uses the same syntax. eg: - HYDRA_PROXY=[http|socks4|socks5]://proxy_addr:proxy_port -for example: - HYDRA_PROXY=http://proxy.anonymizer.com:8000 + HYDRA_PROXY_HTTP="http://login:password@123.45.67.89:8080/" + HYDRA_PROXY_HTTP="proxylist.txt" +The last example is a text file containing up to 64 proxies (in the same +format definition as the other examples). -If you require authentication for the proxy, use the HYDRA_PROXY_AUTH -environment variable: - HYDRA_PROXY_AUTH="the_login:the_password" +For all other services, use the HYDRA_PROXY variable to scan/crack. +It uses the same syntax. eg: + HYDRA_PROXY=[connect|socks4|socks5]://[login:password@]proxy_addr:proxy_port +for example: + HYDRA_PROXY=connect://proxy.anonymizer.com:8000 + HYDRA_PROXY=socks4://auth:pw@127.0.0.1:1080 + HYDRA_PROXY=socksproxylist.txt diff --git a/hydra-http-form.c b/hydra-http-form.c index 2226a3a..f051626 100644 --- a/hydra-http-form.c +++ b/hydra-http-form.c @@ -570,6 +570,9 @@ int start_http_form(int s, char *ip, int port, unsigned char options, char *misc memset(header, 0, sizeof(header)); cookie[0] = 0; // reset cookies from potential previous attempt + if (use_proxy > 0 && proxy_count > 0) + selected_proxy = random() % proxy_count; + // Take the next login/pass pair if (strlen(login = hydra_get_next_login()) == 0) login = empty; @@ -587,7 +590,7 @@ int start_http_form(int s, char *ip, int port, unsigned char options, char *misc hdrrep(&ptr_head, "^PASS^", cpass); /* again: no snprintf to be portable. dont worry, buffer cant overflow */ - if (use_proxy == 1 && proxy_authentication != NULL) { + if (use_proxy == 1 && proxy_authentication[selected_proxy] != NULL) { if (getcookie) { memset(proxy_string, 0, sizeof(proxy_string)); snprintf(proxy_string, MAX_PROXY_LENGTH - 1, "http://%s:%d%.600s", webtarget, webport, cookieurl); @@ -829,7 +832,7 @@ int start_http_form(int s, char *ip, int port, unsigned char options, char *misc hdrrepv(&ptr_head, "Content-Length", "0"); //re-use the code above to check for proxy use - if (use_proxy == 1 && proxy_authentication != NULL) { + if (use_proxy == 1 && proxy_authentication[selected_proxy] != NULL) { // proxy with authentication hdrrepv(&ptr_head, "Host", str2); memset(proxy_string, 0, sizeof(proxy_string)); @@ -996,6 +999,9 @@ int service_http_form_init(char *ip, int sp, unsigned char options, char *miscpt ptr_header_node initialize(char *ip, unsigned char options, char *miscptr) { ptr_header_node ptr_head = NULL; char *ptr, *ptr2, *proxy_string; + + if (use_proxy > 0 && proxy_count > 0) + selected_proxy = random() % proxy_count; if (webtarget != NULL && (webtarget = strstr(miscptr, "://")) != NULL) { webtarget += strlen("://"); @@ -1166,14 +1172,14 @@ ptr_header_node initialize(char *ip, unsigned char options, char *miscptr) { } /* again: no snprintf to be portable. dont worry, buffer cant overflow */ - if (use_proxy == 1 && proxy_authentication != NULL) { + if (use_proxy == 1 && proxy_authentication[selected_proxy] != 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); + proxy_string = (char *) malloc(strlen(proxy_authentication[selected_proxy]) + 6); if (proxy_string) { strcpy(proxy_string, "Basic "); - strncat(proxy_string, proxy_authentication, strlen(proxy_authentication) - 6); + strncat(proxy_string, proxy_authentication[selected_proxy], strlen(proxy_authentication[selected_proxy]) - 6); add_header(&ptr_head, "Proxy-Authorization", proxy_string, HEADER_TYPE_DEFAULT); } else { hydra_report(stderr, "Out of memory for \"Proxy-Authorization\" header."); diff --git a/hydra-http.c b/hydra-http.c index cc6e66d..a7d773f 100644 --- a/hydra-http.c +++ b/hydra-http.c @@ -28,15 +28,18 @@ int start_http(int s, char *ip, int port, unsigned char options, char *miscptr, if (http_buf == NULL && http_auth_mechanism == AUTH_DIGESTMD5) http_auth_mechanism = AUTH_BASIC; + if (use_proxy > 0 && proxy_count > 0) + selected_proxy = random() % proxy_count; + switch (http_auth_mechanism) { case AUTH_BASIC: sprintf(buffer2, "%.50s:%.50s", login, pass); hydra_tobase64((unsigned char *) buffer2, strlen(buffer2), sizeof(buffer2)); /* again: no snprintf to be portable. dont worry, buffer cant overflow */ - if (use_proxy == 1 && proxy_authentication != NULL) + if (use_proxy == 1 && proxy_authentication[selected_proxy] != NULL) sprintf(buffer, "%s http://%s:%d%.250s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\nAuthorization: Basic %s\r\nProxy-Authorization: Basic %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\n%s\r\n", - type, webtarget, webport, miscptr, webtarget, buffer2, proxy_authentication, header); + type, webtarget, webport, miscptr, webtarget, buffer2, proxy_authentication[selected_proxy], header); else { if (use_proxy == 1) sprintf(buffer, "%s http://%s:%d%.250s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\nAuthorization: Basic %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\n%s\r\n", @@ -81,10 +84,10 @@ int start_http(int s, char *ip, int port, unsigned char options, char *miscptr, /* to be portable, no snprintf, buffer is big enough so it cant overflow */ //send the first.. - if (use_proxy == 1 && proxy_authentication != NULL) + if (use_proxy == 1 && proxy_authentication[selected_proxy] != NULL) sprintf(buffer, "%s http://%s:%d%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\nAuthorization: NTLM %s\r\nProxy-Authorization: Basic %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\nConnection: keep-alive\r\n%s\r\n", - type, webtarget, webport, miscptr, webtarget, buf1, proxy_authentication, header); + type, webtarget, webport, miscptr, webtarget, buf1, proxy_authentication[selected_proxy], header); else { if (use_proxy == 1) sprintf(buffer, "%s http://%s:%d%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\nAuthorization: NTLM %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\nConnection: keep-alive\r\n%s\r\n", @@ -130,10 +133,10 @@ int start_http(int s, char *ip, int port, unsigned char options, char *miscptr, to64frombits(buf1, buf2, SmbLength((tSmbNtlmAuthResponse *) buf2)); //create the auth response - if (use_proxy == 1 && proxy_authentication != NULL) + if (use_proxy == 1 && proxy_authentication[selected_proxy] != NULL) sprintf(buffer, "%s http://%s:%d%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\nAuthorization: NTLM %s\r\nProxy-Authorization: Basic %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\nConnection: keep-alive\r\n%s\r\n", - type, webtarget, webport, miscptr, webtarget, buf1, proxy_authentication, header); + type, webtarget, webport, miscptr, webtarget, buf1, proxy_authentication[selected_proxy], header); else { if (use_proxy == 1) sprintf(buffer, "%s http://%s:%d%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\nAuthorization: NTLM %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\nConnection: keep-alive\r\n%s\r\n", diff --git a/hydra-mod.c b/hydra-mod.c index 972907f..be4b223 100644 --- a/hydra-mod.c +++ b/hydra-mod.c @@ -86,7 +86,7 @@ void interrupt() { /* ----------------- internal functions ----------------- */ int internal__hydra_connect(char *host, int port, int protocol, int type) { - int s, ret = -1, ipv6 = 0; + int s, ret = -1, ipv6 = 0, reset_selected = 0; #ifdef AF_INET6 struct sockaddr_in6 target6; @@ -96,11 +96,16 @@ int internal__hydra_connect(char *host, int port, int protocol, int type) { struct sockaddr_in sin; char *buf, *tmpptr = NULL; int err = 0; + + if (proxy_count > 0 && use_proxy > 0 && selected_proxy == -1) { + reset_selected = 1; + selected_proxy = random() % proxy_count; + } #ifdef AF_INET6 memset(&target6, 0, sizeof(target6)); memset(&sin6, 0, sizeof(sin6)); - if ((host[0] == 16 && proxy_string_ip[0] != 4) || proxy_string_ip[0] == 16) + if ((host[0] == 16 && proxy_string_ip[selected_proxy][0] != 4) || proxy_string_ip[selected_proxy][0] == 16) ipv6 = 1; #endif @@ -150,6 +155,8 @@ int internal__hydra_connect(char *host, int port, int protocol, int type) { if (errno == EACCES && (getuid() > 0)) { fprintf(stderr, "[ERROR] You need to be root to test this service\n"); close(s); + if (reset_selected) + selected_proxy = -1; return -1; } } @@ -157,17 +164,18 @@ int internal__hydra_connect(char *host, int port, int protocol, int type) { bind_ok = 1; } } - if (use_proxy > 0) { - if (proxy_string_ip[0] == 4) { - memcpy(&target.sin_addr.s_addr, &proxy_string_ip[1], 4); + if (use_proxy > 0 && proxy_count > 0) { + + if (proxy_string_ip[selected_proxy][0] == 4) { + memcpy(&target.sin_addr.s_addr, &proxy_string_ip[selected_proxy][1], 4); target.sin_family = AF_INET; - target.sin_port = htons(proxy_string_port); + target.sin_port = htons(proxy_string_port[selected_proxy]); } #ifdef AF_INET6 - if (proxy_string_ip[0] == 16) { - memcpy(&target6.sin6_addr, &proxy_string_ip[1], 16); + if (proxy_string_ip[selected_proxy][0] == 16) { + memcpy(&target6.sin6_addr, &proxy_string_ip[selected_proxy][1], 16); target6.sin6_family = AF_INET6; - target6.sin6_port = htons(proxy_string_port); + target6.sin6_port = htons(proxy_string_port[selected_proxy]); } #endif } else { @@ -230,6 +238,8 @@ int internal__hydra_connect(char *host, int port, int protocol, int type) { extern_socket = -1; close(s); ret = -1; + if (reset_selected) + selected_proxy = -1; return ret; } ret = s; @@ -242,6 +252,8 @@ int internal__hydra_connect(char *host, int port, int protocol, int type) { if ((buf = malloc(4096)) == NULL) { fprintf(stderr, "[ERROR] could not malloc()\n"); close(s); + if (reset_selected) + selected_proxy = -1; return -1; } memset(&target, 0, sizeof(target)); @@ -259,16 +271,16 @@ int internal__hydra_connect(char *host, int port, int protocol, int type) { } #endif - if (hydra_strcasestr(proxy_string_type, "connect") || hydra_strcasestr(proxy_string_type, "http")) { - if (proxy_authentication == NULL) + if (hydra_strcasestr(proxy_string_type[selected_proxy], "connect") || hydra_strcasestr(proxy_string_type[selected_proxy], "http")) { + if (proxy_authentication[selected_proxy] == NULL) if (host[0] == 16) snprintf(buf, 4096, "CONNECT [%s]:%d HTTP/1.0\r\n\r\n", hydra_address2string(host), port); else snprintf(buf, 4096, "CONNECT %s:%d HTTP/1.0\r\n\r\n", hydra_address2string(host), port); else if (host[0] == 16) - snprintf(buf, 4096, "CONNECT [%s]:%d HTTP/1.0\r\nProxy-Authorization: Basic %s\r\n\r\n", hydra_address2string(host), port, proxy_authentication); + snprintf(buf, 4096, "CONNECT [%s]:%d HTTP/1.0\r\nProxy-Authorization: Basic %s\r\n\r\n", hydra_address2string(host), port, proxy_authentication[selected_proxy]); else - snprintf(buf, 4096, "CONNECT %s:%d HTTP/1.0\r\nProxy-Authorization: Basic %s\r\n\r\n", hydra_address2string(host), port, proxy_authentication); + snprintf(buf, 4096, "CONNECT %s:%d HTTP/1.0\r\nProxy-Authorization: Basic %s\r\n\r\n", hydra_address2string(host), port, proxy_authentication[selected_proxy]); send(s, buf, strlen(buf), 0); recv(s, buf, 4096, 0); @@ -284,14 +296,14 @@ int internal__hydra_connect(char *host, int port, int protocol, int type) { } // free(buf); } else { - if (hydra_strcasestr(proxy_string_type, "socks5")) { + if (hydra_strcasestr(proxy_string_type[selected_proxy], "socks5")) { // char buf[1024]; size_t cnt, wlen; /* socks v5 support */ buf[0] = SOCKS_V5; buf[1] = 1; - if (proxy_authentication == NULL) + if (proxy_authentication[selected_proxy] == NULL) buf[2] = SOCKS_NOAUTH; else buf[2] = SOCKS_PASSAUTH; @@ -312,9 +324,9 @@ int internal__hydra_connect(char *host, int port, int protocol, int type) { /* SOCKS_DOMAIN not supported here, do we need it ? */ if (err != 1) { /* send user/pass */ - if (proxy_authentication != NULL) { + if (proxy_authentication[selected_proxy] != NULL) { //format was checked previously - char *login = strtok(proxy_authentication, ":"); + char *login = strtok(proxy_authentication[selected_proxy], ":"); char *pass = strtok(NULL, ":"); snprintf(buf, sizeof(buf), "\x01%c%s%c%s", (char) strlen(login), login, (char) strlen(pass), pass); @@ -383,7 +395,7 @@ int internal__hydra_connect(char *host, int port, int protocol, int type) { } } } else { - if (hydra_strcasestr(proxy_string_type, "socks4")) { + if (hydra_strcasestr(proxy_string_type[selected_proxy], "socks4")) { if (ipv6) { hydra_report(stderr, "[ERROR] SOCKS4 proxy does not support IPv6\n"); err = 1; @@ -419,7 +431,7 @@ int internal__hydra_connect(char *host, int port, int protocol, int type) { } } } else { - hydra_report(stderr, "[ERROR] Unknown proxy type: %s, valid type are \"connect\", \"socks4\" or \"socks5\"\n", proxy_string_type); + hydra_report(stderr, "[ERROR] Unknown proxy type: %s, valid type are \"connect\", \"socks4\" or \"socks5\"\n", proxy_string_type[selected_proxy]); err = 1; } } @@ -429,12 +441,18 @@ int internal__hydra_connect(char *host, int port, int protocol, int type) { if (err) { close(s); extern_socket = -1; + if (reset_selected) + selected_proxy = -1; ret = -1; return ret; } fail = 0; + if (reset_selected) + selected_proxy = -1; return ret; } + if (reset_selected) + selected_proxy = -1; return ret; } diff --git a/hydra-mod.h b/hydra-mod.h index 00217c5..e4dcbde 100644 --- a/hydra-mod.h +++ b/hydra-mod.h @@ -48,12 +48,14 @@ int debug; int verbose; int waittime; int port; -int use_proxy; int found; -char proxy_string_ip[36]; -int proxy_string_port; -char proxy_string_type[10]; -char *proxy_authentication; +int proxy_count; +int use_proxy; +int selected_proxy; +char proxy_string_ip[MAX_PROXY_COUNT][36]; +int proxy_string_port[MAX_PROXY_COUNT]; +char proxy_string_type[MAX_PROXY_COUNT][10]; +char *proxy_authentication[MAX_PROXY_COUNT]; char *cmdlinetarget; typedef int BOOL; diff --git a/hydra.c b/hydra.c index 3a6e76a..3ce44ab 100644 --- a/hydra.c +++ b/hydra.c @@ -285,10 +285,12 @@ extern int waittime; extern int port; extern int found; extern int use_proxy; -extern int proxy_string_port; -extern char proxy_string_ip[36]; -extern char proxy_string_type[10]; -extern char *proxy_authentication; +extern int proxy_count; +extern int selected_proxy; +extern int proxy_string_port[MAX_PROXY_COUNT]; +extern char proxy_string_ip[MAX_PROXY_COUNT][36]; +extern char proxy_string_type[MAX_PROXY_COUNT][10]; +extern char *proxy_authentication[MAX_PROXY_COUNT]; extern char *cmdlinetarget; extern char *fe80; @@ -378,10 +380,11 @@ void help(int ext) { printf("These services were not compiled in: %s.\n", unsupported); } if (ext) { - printf("\nUse HYDRA_PROXY_HTTP or HYDRA_PROXY - and if needed HYDRA_PROXY_AUTH - environment for a proxy setup.\n"); - printf("E.g.: %% export HYDRA_PROXY=socks5://127.0.0.1:9150 (or socks4:// or connect://)\n"); - printf(" %% export HYDRA_PROXY_HTTP=http://proxy:8080\n"); - printf(" %% export HYDRA_PROXY_AUTH=user:pass\n"); + printf("\nUse HYDRA_PROXY_HTTP or HYDRA_PROXY environment variables for a proxy setup.\n"); + printf("E.g. %% export HYDRA_PROXY=socks5://l:p@127.0.0.1:9150 (or: socks4:// connect://)\n"); + printf(" %% export HYDRA_PROXY=connect_and_socks_proxylist.txt (up to 64 entries)\n"); + printf(" %% export HYDRA_PROXY_HTTP=http://login:pass@proxy:8080\n"); + printf(" %% export HYDRA_PROXY_HTTP=proxylist.txt (up to 64 entries)\n"); } printf("\nExample%s:%s hydra -l user -P passlist.txt ftp://192.168.0.1\n", ext == 0 ? "" : "s", ext == 0 ? "" : "\n"); @@ -594,7 +597,7 @@ void module_usage() { " \"/login.php:user=^USER^&pass=^PASS^:incorrect\"\n" " \"/login.php:user=^USER^&pass=^PASS^&colon=colon\\:escape:S=authlog=.*success\"\n" " \"/login.php:user=^USER^&pass=^PASS^&mid=123:authlog=.*failed\"\n" - " \"/:user=^USER&pass=^PASS^:failed:H=Authorization\\: Basic dT1w:H=Cookie\\: sessid=aaaa:h=X-User\\: ^USER^\"\n" + " \"/:user=^USER&pass=^PASS^:failed:H=Authorization\\: Basic dT1w:H=Cookie\\: sessid=aaaa:h=X-User\\: ^USER^:H=User-Agent\\: wget\"\n" " \"/exchweb/bin/auth/owaauth.dll:destination=http%%3A%%2F%%2F%%2Fexchange&flags=0&username=%%5C^USER^&password=^PASS^&SubmitCreds=x&trusted=0:reason=:C=/exchweb\"\n", hydra_options.service); find = 1; @@ -2192,9 +2195,133 @@ int hydra_select_target() { return target_no; } +void process_proxy_line(int type, char *string) { + char *type_string = string, *target_string, *port_string, *auth_string = NULL, *device_string = NULL, *sep; + int port; + struct addrinfo hints, *res, *p; + struct sockaddr_in6 *ipv6 = NULL; + struct sockaddr_in *ipv4 = NULL; + + if (string == NULL || string[0] == 0 || string[0] == '#') + return; + while (*string == ' ' || *string == '\t') + string++; + if (*string == '#' || *string == ';' || strlen(string) < 5) + return; + if (string[strlen(string) - 1] == '\n') + string[strlen(string) - 1] = 0; + if (string[strlen(string) - 1] == '\r') + string[strlen(string) - 1] = 0; + if (proxy_count > MAX_PROXY_COUNT) { + fprintf(stderr, "[WARNING] maximum amount of proxies loaded, ignoring this entry: %s\n", string); + return; + } + if (debug) + printf("[DEBUG] proxy line: %s\n", string); + if ((sep = strstr(string, "://")) == NULL) { + fprintf(stderr, "[WARNING] invalid proxy definition: %s (ignored)\n", string); + return; + } + *sep = 0; + target_string = sep + 3; + if ((sep = index(target_string, '@')) != NULL) { + auth_string = target_string; + *sep = 0; + target_string = sep + 1; + if (index(auth_string, ':') == NULL) { + fprintf(stderr, "[WARNING] %s has an invalid authentication definition %s, must be in the format login:pass, entry ignored\n", target_string, auth_string); + return; + } + } + if ((sep = index(target_string, ':')) != NULL) { + *sep = 0; + port_string = sep + 1; + if ((sep = index(port_string, '%')) != NULL) { + *sep = 0; + device_string = sep + 1; + } + if ((sep = index(port_string, '/')) != NULL) + *sep = 0; + port = atoi(port_string); + if (port < 1 || port > 65535) { + fprintf(stderr, "[WARNING] %s has an invalid port definition %d, entry ignored\n", target_string, port); + return; + } + } else { + fprintf(stderr, "[WARNING] %s has not port definition which is required, entry ignored\n", target_string); + return; + } + + if (use_proxy == 1 && strcmp(type_string, "http") != 0) { + fprintf(stderr, "[WARNING] %s:// is an invalid type, must be http:// if you use HYDRA_PROXY_HTTP, entry ignored\n", type_string); + return; + } + if (use_proxy == 2 && strcmp(type_string, "connect") != 0 && strcmp(type_string, "socks4") != 0 && strcmp(type_string, "socks5") != 0) { + fprintf(stderr, "[WARNING] %s:// is an invalid type, must be connect://, socks4:// or socks5:// if you use HYDRA_PROXY, entry ignored\n", type_string); + return; + } + + memset(&hints, 0, sizeof hints); + if (getaddrinfo(target_string, NULL, &hints, &res) != 0) { + fprintf(stderr, "[ERROR] could not resolve proxy target %s, entry ignored\n", target_string); + return; + } + + for (p = res; p != NULL; p = p->ai_next) { +#ifdef AF_INET6 + if (p->ai_family == AF_INET6) { + if (ipv6 == NULL || memcmp((char *) &ipv6->sin6_addr, fe80, 2) == 0) + ipv6 = (struct sockaddr_in6 *) p->ai_addr; + } else +#endif + if (p->ai_family == AF_INET) { + if (ipv4 == NULL) + ipv4 = (struct sockaddr_in *) p->ai_addr; + } + } + freeaddrinfo(res); + + // now fill the stuff +#ifdef AF_INET6 + if (ipv6 != NULL && (ipv4 == NULL || prefer_ipv6)) { + if (memcmp(proxy_string_ip[proxy_count] + 1, fe80, 2) == 0 && device_string == NULL) { + fprintf(stderr, "[WARNING] The proxy address %s is a link local address, link local addresses require the interface being defined like this: fe80::1%%eth0, entry ignored\n", target_string); + return; + } + proxy_string_ip[proxy_count][0] = 16; + memcpy(proxy_string_ip[proxy_count] + 1, (char *) &ipv6->sin6_addr, 16); + if (device_string != NULL && strlen(device_string) <= 16) + strcpy(proxy_string_ip[proxy_count] + 17, device_string); + } else +#endif + if (ipv4 != NULL) { + proxy_string_ip[proxy_count][0] = 4; + memcpy(proxy_string_ip[proxy_count] + 1, (char *) &ipv4->sin_addr, 4); + } else { + fprintf(stderr, "[WARNING] Could not resolve proxy address: %s, entry ignored\n", target_string); + return; + } + if (auth_string != NULL) { + if ((proxy_authentication[proxy_count] = malloc(strlen(auth_string) * 2 + 8)) == NULL) { + perror("malloc"); + return; + } + strcpy(proxy_authentication[proxy_count], auth_string); + if (strncmp(type_string, "socks", 5) != 0) // so it is web + hydra_tobase64((unsigned char *) proxy_authentication[proxy_count], strlen(proxy_authentication[proxy_count]), strlen(auth_string) * 2 + 8); + } else + proxy_authentication[proxy_count] = NULL; + strcpy(proxy_string_type[proxy_count], type_string); + proxy_string_port[proxy_count] = port; + + if (debug) + printf("[DEBUG] count %d type %s target %s port %d auth %s\n", proxy_count, proxy_string_type[proxy_count], target_string, proxy_string_port[proxy_count], proxy_authentication[proxy_count]); + proxy_count++; +} + int main(int argc, char *argv[]) { char *proxy_string = NULL, *device = NULL, *memcheck, *cmdtarget = NULL; - FILE *lfp = NULL, *pfp = NULL, *cfp = NULL, *ifp = NULL, *rfp = NULL; + FILE *lfp = NULL, *pfp = NULL, *cfp = NULL, *ifp = NULL, *rfp = NULL, *proxyfp; size_t countinfile = 1, sizeinfile = 0; unsigned long int math2; int i = 0, j = 0, k, error = 0, modusage = 0; @@ -2297,10 +2424,12 @@ int main(int argc, char *argv[]) { hydra_options.verbose = verbose = 0; found = 0; use_proxy = 0; - proxy_string_ip[0] = 0; - proxy_string_port = 0; - strcpy(proxy_string_type, "connect"); - proxy_authentication = cmdlinetarget = NULL; + proxy_count = 0; + selected_proxy = -1; + proxy_string_ip[0][0] = 0; + proxy_string_port[0] = 0; + strcpy(proxy_string_type[0], "connect"); + proxy_authentication[0] = cmdlinetarget = NULL; hydra_options.login = NULL; hydra_options.loginfile = NULL; hydra_options.pass = NULL; @@ -3452,6 +3581,7 @@ int main(int argc, char *argv[]) { } } // END OF restore == 0 + // PROXY PROCESSING if (getenv("HYDRA_PROXY") && use_proxy == 0) { printf("[INFO] Using Connect Proxy: %s\n", getenv("HYDRA_PROXY")); use_proxy = 2; @@ -3460,83 +3590,22 @@ int main(int argc, char *argv[]) { proxy_string = getenv("HYDRA_PROXY_HTTP"); if (use_proxy == 2) proxy_string = getenv("HYDRA_PROXY"); - if (proxy_string != NULL && proxy_string[0] != 0) { - if (strstr(proxy_string, "//") != NULL) { - char *dslash = strstr(proxy_string, "://"); - - if (dslash) { - proxy_string[dslash - proxy_string] = 0; - strncpy(proxy_string_type, proxy_string, sizeof(proxy_string_type) - 1); - proxy_string_type[sizeof(proxy_string_type) - 1] = 0; - } - - proxy_string = dslash; - proxy_string += 3; - } - if (proxy_string[strlen(proxy_string) - 1] == '/') - proxy_string[strlen(proxy_string) - 1] = 0; - if ((tmpptr = index(proxy_string, ':')) == NULL) - use_proxy = 0; - else { - *tmpptr = 0; - tmpptr++; - memset(&hints, 0, sizeof hints); - if ((device = index(proxy_string, '%')) != NULL) - *device++ = 0; - if (getaddrinfo(proxy_string, NULL, &hints, &res) != 0) { - fprintf(stderr, "[ERROR] could not resolve proxy address: %s\n", proxy_string); - exit(-1); - } else { - for (p = res; p != NULL; p = p->ai_next) { -#ifdef AF_INET6 - if (p->ai_family == AF_INET6) { - if (ipv6 == NULL) - ipv6 = (struct sockaddr_in6 *) p->ai_addr; - } else -#endif - if (p->ai_family == AF_INET) { - if (ipv4 == NULL) - ipv4 = (struct sockaddr_in *) p->ai_addr; - } - } - freeaddrinfo(res); -#ifdef AF_INET6 - if (ipv6 != NULL && (ipv4 == NULL || prefer_ipv6)) { - proxy_string_ip[0] = 16; - memcpy(proxy_string_ip + 1, (char *) &ipv6->sin6_addr, 16); - if (device != NULL && strlen(device) <= 16) - strcpy(proxy_string_ip + 17, device); - if (memcmp(proxy_string_ip + 1, fe80, 2) == 0) { - if (device == NULL) { - fprintf(stderr, "[ERROR] The proxy address is a link local address, link local addresses require the interface being defined like this: fe80::1%%eth0\n"); - exit(-1); - } - } - } else -#endif - if (ipv4 != NULL) { - proxy_string_ip[0] = 4; - memcpy(proxy_string_ip + 1, (char *) &ipv4->sin_addr, 4); - } else { - fprintf(stderr, "[ERROR] Could not resolve proxy address: %s\n", proxy_string); - exit(-1); - } - } - proxy_string_port = atoi(tmpptr); - } - if (use_proxy == 0) - fprintf(stderr, "[WARNING] invalid proxy definition. Syntax: \"HYDRA_PROXY=[connect|socks[4|5]]://1.2.3.4:3128/\".\n"); - } else - use_proxy = 0; - if (use_proxy > 0 && (tmpptr = getenv("HYDRA_PROXY_AUTH")) != NULL && tmpptr[0] != 0) { - if (index(tmpptr, ':') == NULL) { - fprintf(stderr, "[WARNING] invalid proxy authentication. Syntax: \"login:password\". Ignoring ...\n"); + if (use_proxy && getenv("HYDRA_PROXY_AUTH") != NULL) + fprintf(stderr, "[WARNING] environment variable HYDRA_PROXY_AUTH is deprecated, use authentication in the HYDRA_PROXY definitions, e.g. type://auth@target:port\n"); + if (use_proxy && proxy_string != NULL) { + if (strstr(proxy_string, "://") != NULL) { + process_proxy_line(use_proxy, proxy_string); } else { - proxy_authentication = malloc(strlen(tmpptr) * 2 + 50); - strcpy(proxy_authentication, tmpptr); - if (hydra_strcasestr(proxy_string_type, "socks") == NULL) - hydra_tobase64((unsigned char *) proxy_authentication, strlen(proxy_authentication), strlen(tmpptr) * 2 + 8); + if ((proxyfp = fopen(proxy_string, "r")) == NULL) { + fprintf(stderr, "[ERROR] proxy definition %s is neither of the kind type://auth@target:port nor a file containing proxy entries!\n", proxy_string); + exit(-1); + } + while (fgets(buf, sizeof(buf), proxyfp) != NULL) + process_proxy_line(use_proxy, buf); + fclose(proxyfp); } + if (proxy_count == 0) + bail("proxy defined but not valid, exiting"); } if (hydra_options.restore == 0) { diff --git a/hydra.h b/hydra.h index 64170a7..ccec000 100644 --- a/hydra.h +++ b/hydra.h @@ -140,6 +140,8 @@ #define INET_ADDRSTRLEN 16 #endif +#define MAX_PROXY_COUNT 64 + #ifndef _WIN32 int sleepn(time_t seconds); diff --git a/web/CHANGES b/web/CHANGES index 1c1033f..31a59d4 100644 --- a/web/CHANGES +++ b/web/CHANGES @@ -2,7 +2,12 @@ Changelog for hydra ------------------- Release 8.4-dev -* your patch? +* Proxy support re-implemented: + - HYDRA_PROXY[_HTTP] environment can be a text file with up to 64 entries + - HYDRA_PROXY_AUTH was deprecated, set login/password in HTTP_PROXY[_HTTP] +* New command line option -y which disables -x 1aA interpretation, thanks to crondaemon for the patch +* The protocols vnc, xmpp, telnet, imap, nntp and pcanywhere got accidentially long sleep commands due a patch in 8.2, fixed +* Added special error message for clueless users :) Release 8.3 diff --git a/web/README b/web/README index a1ef2ff..27a5bd1 100644 --- a/web/README +++ b/web/README @@ -256,18 +256,21 @@ from little endian to big endian, or from solaris to aix) HOW TO SCAN/CRACK OVER A PROXY ------------------------------ The environment variable HYDRA_PROXY_HTTP defines the web proxy (this works -just for the http/www service!). +just for the http services!). The following syntax is valid: HYDRA_PROXY_HTTP="http://123.45.67.89:8080/" -For all other services, use the HYDRA_PROXY variable to scan/crack -via by default a web proxy's CONNECT call. It uses the same syntax. eg: - HYDRA_PROXY=[http|socks4|socks5]://proxy_addr:proxy_port -for example: - HYDRA_PROXY=http://proxy.anonymizer.com:8000 + HYDRA_PROXY_HTTP="http://login:password@123.45.67.89:8080/" + HYDRA_PROXY_HTTP="proxylist.txt" +The last example is a text file containing up to 64 proxies (in the same +format definition as the other examples). -If you require authentication for the proxy, use the HYDRA_PROXY_AUTH -environment variable: - HYDRA_PROXY_AUTH="the_login:the_password" +For all other services, use the HYDRA_PROXY variable to scan/crack. +It uses the same syntax. eg: + HYDRA_PROXY=[connect|socks4|socks5]://[login:password@]proxy_addr:proxy_port +for example: + HYDRA_PROXY=connect://proxy.anonymizer.com:8000 + HYDRA_PROXY=socks4://auth:pw@127.0.0.1:1080 + HYDRA_PROXY=socksproxylist.txt