This commit is contained in:
root 2015-05-05 01:44:10 +02:00
parent 08fedd8583
commit b6f3e73b65
5 changed files with 4231 additions and 4068 deletions

View file

@ -16,7 +16,7 @@ SRC = hydra-vnc.c hydra-pcnfs.c hydra-rexec.c hydra-nntp.c hydra-socks5.c \
hydra-oracle.c hydra-vmauthd.c hydra-asterisk.c hydra-firebird.c hydra-afp.c hydra-ncp.c \
hydra-oracle-sid.c hydra-http-proxy.c hydra-http-form.c hydra-irc.c \
hydra-rdp.c hydra-s7-300.c hydra-redis.c \
crc32.c d3des.c bfg.c ntlm.c sasl.c hmacmd5.c hydra-mod.c
crc32.c d3des.c bfg.c ntlm.c sasl.c hmacmd5.c hydra-mod.c hydra-rtsp.c
OBJ = hydra-vnc.o hydra-pcnfs.o hydra-rexec.o hydra-nntp.o hydra-socks5.o \
hydra-telnet.o hydra-cisco.o hydra-http.o hydra-ftp.o hydra-imap.o \
hydra-pop3.o hydra-smb.o hydra-icq.o hydra-cisco-enable.o hydra-ldap.o \
@ -27,7 +27,7 @@ OBJ = hydra-vnc.o hydra-pcnfs.o hydra-rexec.o hydra-nntp.o hydra-socks5.o \
hydra-oracle-sid.o hydra-oracle.o hydra-vmauthd.o hydra-asterisk.o hydra-firebird.o hydra-afp.o hydra-ncp.o \
hydra-http-proxy.o hydra-http-form.o hydra-irc.o hydra-redis.o \
hydra-rdp.o hydra-s7-300.c \
crc32.o d3des.o bfg.o ntlm.o sasl.o hmacmd5.o hydra-mod.o
crc32.o d3des.o bfg.o ntlm.o sasl.o hmacmd5.o hydra-mod.o hydra-rtsp.o
BINS = hydra pw-inspector
EXTRA_DIST = README README.arm README.palm CHANGES TODO INSTALL LICENSE \

247
hydra-rtsp.c Normal file
View file

@ -0,0 +1,247 @@
//
// hydra-rtsp.c
// hydra-rtsp
//
// Created by Javier Sánchez on 18/04/15.
//
//
#include <stdio.h>
#include "hydra-mod.h"
#include <string.h>
#include "sasl.h"
extern char *HYDRA_EXIT;
char *buf;
char packet[500];
char packet2[500];
int is_Unauthorized(char * s){
if (strstr(s,"401 Unauthorized")!= NULL){
return 1;
}else{
return 0;
}
}
int is_NotFound(char * s){
if (strstr(s,"404 Stream Not Found")!= NULL){
return 1;
}else{
return 0;
}
}
int is_Authorized(char * s){
if (strstr(s,"200 OK")!= NULL){
return 1;
}else{
return 0;
}
}
int use_Basic_Auth(char * s){
if(strstr(s,"WWW-Authenticate: Basic")!=NULL){
return 1;
}else{
return 0;
}
}
int use_Digest_Auth(char * s){
if(strstr(s,"WWW-Authenticate: Digest")!=NULL){
return 1;
}else{
return 0;
}
}
void create_core_packet(int control,char* ip, int port){
char buffer[500];
char * target=hydra_address2string(ip);
if (control==0){
if (strlen(packet) <= 0){
sprintf(packet, "DESCRIBE rtsp://%s:%i RTSP/1.0\r\nCSeq: 2\r\n\r\n",target,port);
}
}else{
if (strlen(packet2) <= 0){
sprintf(packet2, "DESCRIBE rtsp://%s:%i RTSP/1.0\r\nCSeq: 3\r\n",target,port);
}
}
}
int start_rtsp(int s, char *ip, int port, unsigned char options, char *miscptr, FILE * fp)
{
char *empty = "";
char *login, *pass, buffer[500],buffer2[500];
char * lresp;
if (strlen(login = hydra_get_next_login()) == 0)
login = empty;
if (strlen(pass = hydra_get_next_password()) == 0)
pass = empty;
create_core_packet(0,ip,port);
if (hydra_send(s, packet, strlen(packet), 0) < 0) {
return 1;
}
lresp = hydra_receive_line(s);
if (lresp == NULL){
printf("null");
return 1;
}
if (is_NotFound(lresp)){
printf("Server dont need credentials\r\n");
hydra_completed_pair_found();
if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0){
return 3;
}
return 1;
} else {
create_core_packet(1,ip, port);
if (use_Basic_Auth(lresp)==1) {
sprintf(buffer2,"%s:%s",login,pass);
hydra_tobase64((unsigned char *) buffer2, strlen(buffer2), sizeof(buffer2));
sprintf(buffer, "%sAuthorization: : Basic %s\r\n\r\n",packet2,buffer2);
if (debug){
hydra_report(stderr, "C:%s\n", buffer);
}
}
if(use_Digest_Auth(lresp)==1){
char dbuffer[500];
char aux[500];
char *pbuffer = hydra_strcasestr(lresp,"WWW-Authenticate: Digest ");
strncpy(aux,pbuffer + strlen("WWW-Authenticate: Digest "), sizeof(buffer));
aux[sizeof(aux)-1]='\0';
#ifdef LIBOPENSSL
sasl_digest_md5(&dbuffer, login, pass, aux, miscptr, "rtsp", hydra_address2string(ip), port, "");
#endif
if (dbuffer==NULL) {
printf("digest fail, dbuffer null\r\n");
return 3;
}
sprintf(buffer, "%sAuthorization: Digest %s\r\n\r\n", packet2, dbuffer);
if (debug){
hydra_report(stderr, "C:%s\n", buffer);
}
}
if (hydra_send(s, buffer, strlen(buffer), 0) < 0) {
return 1;
}
lresp = NULL;
lresp = hydra_receive_line(s);
if ((is_NotFound(lresp))){
hydra_completed_pair_found();
if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0){
return 3;
}
return 1;
}
hydra_completed_pair();
}
if(memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
return 3;
//not rechead
return 2;
}
void service_rtsp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port) {
int run = 1, next_run = 1, sock = -1;
int myport = PORT_RTSP, mysslport = PORT_RTSP_SSL;
char *ptr, *ptr2;
hydra_register_socket(sp);
if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
return;
while (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;
}
if (sock < 0) {
if (verbose || debug)
hydra_report(stderr, "[ERROR] Child with pid %d terminating, can not connect\n", (int) getpid());
hydra_child_exit(1);
}
next_run=2;
break;
case 2: /* run the cracking function */
next_run = start_rtsp(sock, ip, port, options, miscptr, fp);
break;
case 3: /* clean exit */
if (sock >= 0) {
sock = hydra_disconnect(sock);
}
hydra_child_exit(0);
printf("end");
return;
break;
default:
hydra_report(stderr, "[ERROR] Caught unknown return code, exiting!\n");
hydra_child_exit(0);
}
run = next_run;
}
}
int service_rtsp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port) {
// called before the childrens are forked off, so this is the function
// which should be filled if initial connections and service setup has to be
// performed once only.
//
// fill if needed.
//
// return codes:
// 0 all OK
// -1 error, hydra will exit, so print a good error message here
return 0;
}

22
hydra.c
View file

@ -51,6 +51,10 @@ extern void service_s7_300(char *ip, int sp, unsigned char options, char *miscpt
// ADD NEW SERVICES HERE
extern void service_rtsp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port);
// ADD NEW SERVICES HERE
#ifdef HAVE_MATH_H
extern void service_mysql(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port);
extern int service_mysql_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port);
@ -137,10 +141,11 @@ extern int service_s7_300_init(char *ip, int sp, unsigned char options, char *mi
// ADD NEW SERVICES HERE
extern int service_rtsp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port);
// ADD NEW SERVICES HERE
char *SERVICES =
"asterisk afp cisco cisco-enable cvs firebird ftp ftps http[s]-{head|get} http[s]-{get|post}-form http-proxy http-proxy-urlenum icq imap[s] irc ldap2[s] ldap3[-{cram|digest}md5][s] mssql mysql ncp nntp oracle oracle-listener oracle-sid pcanywhere pcnfs pop3[s] postgres rdp redis rexec rlogin rsh s7-300 sapr3 sip smb smtp[s] smtp-enum snmp socks5 ssh sshkey svn teamspeak telnet[s] vmauthd vnc xmpp";
"asterisk afp cisco cisco-enable cvs firebird ftp ftps http[s]-{head|get} http[s]-{get|post}-form http-proxy http-proxy-urlenum icq imap[s] irc ldap2[s] ldap3[-{cram|digest}md5][s] mssql mysql ncp nntp oracle oracle-listener oracle-sid pcanywhere pcnfs pop3[s] postgres rdp redis rexec rlogin rsh s7-300 sapr3 sip smb smtp[s] smtp-enum snmp socks5 ssh sshkey svn teamspeak telnet[s] vmauthd vnc xmpp rtsp";
#define MAXBUF 520
#define MAXLINESIZE ( ( MAXBUF / 2 ) - 4 )
@ -1182,6 +1187,9 @@ void hydra_service_init(int target_no) {
x = service_s7_300_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
// ADD NEW SERVICES HERE
if (strcmp(hydra_options.service, "rtsp") == 0)
x = service_rtsp_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
if (x != 0 && x != 99) {
if (x > 0 && x < 4)
hydra_targets[target_no]->done = x;
@ -1246,8 +1254,11 @@ int hydra_spawn_head(int head_no, int target_no) {
service_asterisk(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
if (strcmp(hydra_options.service, "telnet") == 0)
service_telnet(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
if (strcmp(hydra_options.service, "ftp") == 0)
if (strcmp(hydra_options.service, "ftp") == 0){
service_ftp(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
}
if (strcmp(hydra_options.service, "ftps") == 0)
service_ftps(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
if (strcmp(hydra_options.service, "redis") == 0)
@ -1377,6 +1388,10 @@ int hydra_spawn_head(int head_no, int target_no) {
service_s7_300(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
// ADD NEW SERVICES HERE
if (strcmp(hydra_options.service, "rtsp") == 0){
service_rtsp(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
}
// just in case a module returns (which it shouldnt) we let it exit here
exit(-1);
} else {
@ -1471,6 +1486,7 @@ int hydra_lookup_port(char *service) {
{"asterisk", PORT_ASTERISK, PORT_ASTERISK_SSL},
{"s7-300", PORT_S7_300, PORT_S7_300_SSL},
// ADD NEW SERVICES HERE - add new port numbers to hydra.h
{"rtsp", PORT_RTSP, PORT_RTSP_SSL},
{"", PORT_NOPORT, PORT_NOPORT}
};
@ -2797,6 +2813,8 @@ int main(int argc, char *argv[]) {
bail("-m option is required to specify the DN\n");
}
// ADD NEW SERVICES HERE
if (strcmp(hydra_options.service, "rtsp") == 0)
i = 1;
if (strcmp(hydra_options.service, "s7-300") == 0) {
if (hydra_options.tasks > 8) {
fprintf(stderr, "[INFO] Reduced number of tasks to 8 (the PLC does not like more connections)\n");

View file

@ -118,6 +118,8 @@
#define PORT_S7_300_SSL 102
#define PORT_REDIS 6379
#define PORT_REDIS_SSL 6379
#define PORT_RTSP 554
#define PORT_RTSP_SSL 554
#define False 0
#define True 1

120
sasl.c
View file

@ -1,15 +1,11 @@
#include "sasl.h"
/*
print_hex is used for debug
it displays the string buf hexa values of size len
*/
int print_hex(unsigned char *buf, int len) {
int i;
int n;
for (i = 0, n = 0; i < len; i++) {
if (n > 7) {
printf("\n");
@ -19,23 +15,16 @@ int print_hex(unsigned char *buf, int len) {
n++;
}
printf("\n");
return (0);
}
/*
RFC 4013: SASLprep: Stringprep Profile for User Names and Passwords
code based on gsasl_saslprep from GSASL project
*/
int sasl_saslprep(const char *in, sasl_saslprep_flags flags, char **out) {
#if LIBIDN
int rc;
rc = stringprep_profile(in, out, "SASLprep", (flags & SASL_ALLOW_UNASSIGNED) ? STRINGPREP_NO_UNASSIGNED : 0);
if (rc != STRINGPREP_OK) {
*out = NULL;
return -1;
@ -47,10 +36,8 @@ int sasl_saslprep(const char *in, sasl_saslprep_flags flags, char **out) {
return -1;
}
#endif
#else
size_t i, inlen = strlen(in);
for (i = 0; i < inlen; i++) {
if (in[i] & 0x80) {
*out = NULL;
@ -67,37 +54,26 @@ int sasl_saslprep(const char *in, sasl_saslprep_flags flags, char **out) {
#endif
return 0;
}
/*
RFC 4616: The PLAIN Simple Authentication and Security Layer (SASL) Mechanism
sasl_plain computes the plain authentication from strings login and password
and stored the value in variable result
the first parameter result must be able to hold at least 255 bytes!
*/
void sasl_plain(char *result, char *login, char *pass) {
char *preplogin;
char *preppasswd;
int rc = sasl_saslprep(login, SASL_ALLOW_UNASSIGNED, &preplogin);
if (rc) {
result = NULL;
return;
}
rc = sasl_saslprep(pass, 0, &preppasswd);
if (rc) {
free(preplogin);
result = NULL;
return;
}
if (2 * strlen(preplogin) + 3 + strlen(preppasswd) < 180) {
strcpy(result, preplogin);
strcpy(result + strlen(preplogin) + 1, preplogin);
@ -107,21 +83,14 @@ void sasl_plain(char *result, char *login, char *pass) {
free(preplogin);
free(preppasswd);
}
#ifdef LIBOPENSSL
/*
RFC 2195: IMAP/POP AUTHorize Extension for Simple Challenge/Response
sasl_cram_md5 computes the cram-md5 authentication from password string
and the challenge sent by the server, and stored the value in variable
result
the parameter result must be able to hold at least 100 bytes!
*/
void sasl_cram_md5(char *result, char *pass, char *challenge) {
char ipad[64];
char opad[64];
@ -129,21 +98,17 @@ void sasl_cram_md5(char *result, char *pass, char *challenge) {
MD5_CTX md5c;
int i, rc;
char *preppasswd;
if (challenge == NULL) {
result = NULL;
return;
}
rc = sasl_saslprep(pass, 0, &preppasswd);
if (rc) {
result = NULL;
return;
}
memset(ipad, 0, sizeof(ipad));
memset(opad, 0, sizeof(opad));
if (strlen(preppasswd) >= 64) {
MD5_Init(&md5c);
MD5_Update(&md5c, preppasswd, strlen(preppasswd));
@ -154,7 +119,6 @@ void sasl_cram_md5(char *result, char *pass, char *challenge) {
strcpy(ipad, preppasswd); // safe
strcpy(opad, preppasswd); // safe
}
for (i = 0; i < 64; i++) {
ipad[i] ^= 0x36;
opad[i] ^= 0x5c;
@ -163,7 +127,6 @@ void sasl_cram_md5(char *result, char *pass, char *challenge) {
MD5_Update(&md5c, ipad, 64);
MD5_Update(&md5c, challenge, strlen(challenge));
MD5_Final(md5_raw, &md5c);
MD5_Init(&md5c);
MD5_Update(&md5c, opad, 64);
MD5_Update(&md5c, md5_raw, MD5_DIGEST_LENGTH);
@ -174,15 +137,11 @@ void sasl_cram_md5(char *result, char *pass, char *challenge) {
}
free(preppasswd);
}
/*
sasl_cram_sha1 computes the cram-sha1 authentication from password string
and the challenge sent by the server, and stored the value in variable
result
the parameter result must be able to hold at least 100 bytes!
*/
void sasl_cram_sha1(char *result, char *pass, char *challenge) {
char ipad[64];
@ -191,21 +150,17 @@ void sasl_cram_sha1(char *result, char *pass, char *challenge) {
SHA_CTX shac;
int i, rc;
char *preppasswd;
if (challenge == NULL) {
result = NULL;
return;
}
rc = sasl_saslprep(pass, 0, &preppasswd);
if (rc) {
result = NULL;
return;
}
memset(ipad, 0, sizeof(ipad));
memset(opad, 0, sizeof(opad));
if (strlen(preppasswd) >= 64) {
SHA1_Init(&shac);
SHA1_Update(&shac, preppasswd, strlen(preppasswd));
@ -216,37 +171,29 @@ void sasl_cram_sha1(char *result, char *pass, char *challenge) {
strcpy(ipad, preppasswd); // safe
strcpy(opad, preppasswd); // safe
}
for (i = 0; i < 64; i++) {
ipad[i] ^= 0x36;
opad[i] ^= 0x5c;
}
SHA1_Init(&shac);
SHA1_Update(&shac, ipad, 64);
SHA1_Update(&shac, challenge, strlen(challenge));
SHA1_Final(sha1_raw, &shac);
SHA1_Init(&shac);
SHA1_Update(&shac, opad, 64);
SHA1_Update(&shac, sha1_raw, SHA_DIGEST_LENGTH);
SHA1_Final(sha1_raw, &shac);
for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
sprintf(result, "%02x", sha1_raw[i]);
result += 2;
}
free(preppasswd);
}
/*
sasl_cram_sha256 computes the cram-sha256 authentication from password string
and the challenge sent by the server, and stored the value in variable
result
the parameter result must be able to hold at least 100 bytes!
*/
void sasl_cram_sha256(char *result, char *pass, char *challenge) {
char ipad[64];
@ -255,21 +202,17 @@ void sasl_cram_sha256(char *result, char *pass, char *challenge) {
SHA256_CTX sha256c;
int i, rc;
char *preppasswd;
if (challenge == NULL) {
result = NULL;
return;
}
memset(ipad, 0, sizeof(ipad));
memset(opad, 0, sizeof(opad));
rc = sasl_saslprep(pass, 0, &preppasswd);
if (rc) {
result = NULL;
return;
}
if (strlen(preppasswd) >= 64) {
SHA256_Init(&sha256c);
SHA256_Update(&sha256c, preppasswd, strlen(preppasswd));
@ -280,35 +223,27 @@ void sasl_cram_sha256(char *result, char *pass, char *challenge) {
strcpy(ipad, preppasswd); // safe
strcpy(opad, preppasswd); // safe
}
for (i = 0; i < 64; i++) {
ipad[i] ^= 0x36;
opad[i] ^= 0x5c;
}
SHA256_Init(&sha256c);
SHA256_Update(&sha256c, ipad, 64);
SHA256_Update(&sha256c, challenge, strlen(challenge));
SHA256_Final(sha256_raw, &sha256c);
SHA256_Init(&sha256c);
SHA256_Update(&sha256c, opad, 64);
SHA256_Update(&sha256c, sha256_raw, SHA256_DIGEST_LENGTH);
SHA256_Final(sha256_raw, &sha256c);
for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
sprintf(result, "%02x", sha256_raw[i]);
result += 2;
}
free(preppasswd);
}
/*
RFC 2831: Using Digest Authentication as a SASL Mechanism
the parameter result must be able to hold at least 500 bytes!!
*/
void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *miscptr, char *type, char *webtarget, int webport, char *header) {
char *pbuffer = NULL;
@ -320,16 +255,12 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
MD5_CTX md5c;
char *preplogin;
char *preppasswd;
int rc = sasl_saslprep(login, SASL_ALLOW_UNASSIGNED, &preplogin);
memset(realm, 0, sizeof(realm));
if (rc) {
result = NULL;
return;
}
rc = sasl_saslprep(pass, 0, &preppasswd);
if (rc) {
free(preplogin);
@ -340,7 +271,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
//DEBUG S: nonce="1Mr6c8WjOd/x5r8GUnGeQIRNUtOVtItu3kQOGAmsZfM=",realm="test.com",qop="auth,auth-int,auth-conf",cipher="rc4-40,rc4-56,rc4,des,3des",maxbuf=4096,charset=utf-8,algorithm=md5-sess
//warning some not well configured xmpp server is sending no realm
//DEBUG S: nonce="3448160828",qop="auth",charset=utf-8,algorithm=md5-sess
pbuffer = buffer;
do {
currentpos++;
@ -361,7 +291,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
}
pbuffer++;
} while ((pbuffer[0] != '\0') && (pbuffer[0] > 31) && (ind < array_size));
//save the latest one
if (ind < array_size) {
array[ind] = malloc(currentpos + 1);
@ -369,12 +298,10 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
array[ind][currentpos] = '\0';
ind++;
}
for (i = 0; i < ind; i++) {
//removing space chars between comma separated value if any
while ((array[i] != NULL) && (array[i][0] == ' ')) {
char *tmp = strdup(array[i]);
memset(array[i], 0, sizeof(array[i]));
strcpy(array[i], tmp + 1);
free(tmp);
@ -384,13 +311,11 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
if (strstr(array[i], "\"") != NULL) {
//assume last char is also a double-quote
int nonce_string_len = strlen(array[i]) - strlen("nonce=\"") - 1;
if ((nonce_string_len > 0) && (nonce_string_len <= sizeof(nonce) - 1)) {
strncpy(nonce, strstr(array[i], "nonce=") + strlen("nonce=") + 1, nonce_string_len);
nonce[nonce_string_len] = '\0';
} else {
int j;
for (j = 0; j < ind; j++)
if (array[j] != NULL)
free(array[j]);
@ -407,13 +332,11 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
if (strstr(array[i], "\"") != NULL) {
//assume last char is also a double-quote
int realm_string_len = strlen(array[i]) - strlen("realm=\"") - 1;
if ((realm_string_len > 0) && (realm_string_len <= sizeof(realm) - 1)) {
strncpy(realm, strstr(array[i], "realm=") + strlen("realm=") + 1, realm_string_len);
realm[realm_string_len] = '\0';
} else {
int i;
for (i = 0; i < ind; i++)
if (array[i] != NULL)
free(array[i]);
@ -435,7 +358,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
auth_find = 1;
if ((strstr(array[i], "\"auth\"") == NULL) && (strstr(array[i], "\"auth,") == NULL) && (strstr(array[i], ",auth\"") == NULL)) {
int j;
for (j = 0; j < ind; j++)
if (array[j] != NULL)
free(array[j]);
@ -448,13 +370,11 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
if (strstr(array[i], "\"") != NULL) {
//assume last char is also a double-quote
int algo_string_len = strlen(array[i]) - strlen("algorithm=\"") - 1;
if ((algo_string_len > 0) && (algo_string_len <= sizeof(algo) - 1)) {
strncpy(algo, strstr(array[i], "algorithm=") + strlen("algorithm=") + 1, algo_string_len);
algo[algo_string_len] = '\0';
} else {
int j;
for (j = 0; j < ind; j++)
if (array[j] != NULL)
free(array[j]);
@ -468,7 +388,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
}
if ((strstr(algo, "MD5") == NULL) && (strstr(algo, "md5") == NULL)) {
int j;
for (j = 0; j < ind; j++)
if (array[j] != NULL)
free(array[j]);
@ -480,7 +399,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
free(array[i]);
array[i] = NULL;
}
if (!strlen(algo)) {
//assuming by default algo is MD5
memset(algo, 0, sizeof(algo));
@ -489,19 +407,15 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
//xmpp case, some xmpp server is not sending the realm so we have to set it up
if ((strlen(realm) == 0) && (strstr(type, "xmpp") != NULL))
snprintf(realm, sizeof(realm), "%s", miscptr);
//compute ha1
//support for algo = MD5
snprintf(buffer, 500, "%s:%s:%s", preplogin, realm, preppasswd);
MD5_Init(&md5c);
MD5_Update(&md5c, buffer, strlen(buffer));
MD5_Final(response, &md5c);
//for MD5-sess
if (strstr(algo, "5-sess") != NULL) {
buffer[0] = 0; //memset(buffer, 0, sizeof(buffer)); => buffer is char*!
/* per RFC 2617 Errata ID 1649 */
if ((strstr(type, "proxy") != NULL) || (strstr(type, "GET") != NULL) || (strstr(type, "HEAD") != NULL)) {
memset(buffer3, 0, sizeof(buffer3));
@ -515,7 +429,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
memcpy(buffer, response, sizeof(response));
sprintf(buffer + sizeof(response), ":%s:%s", nonce, "hydra");
}
MD5_Init(&md5c);
MD5_Update(&md5c, buffer, strlen(buffer));
MD5_Final(response, &md5c);
@ -526,7 +439,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
sprintf(pbuffer, "%02x", response[i]);
pbuffer += 2;
}
//compute ha2
//proxy case
if (strstr(type, "proxy") != NULL)
@ -541,18 +453,20 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
sprintf(buffer, "REGISTER:%s:%s", type, miscptr);
else
//others
if (strstr(type, "rtsp") != NULL)
sprintf(buffer, "DESCRIBE:%s://%s:%i", type, webtarget, port);
else
//others
sprintf(buffer, "AUTHENTICATE:%s/%s", type, realm);
MD5_Init(&md5c);
MD5_Update(&md5c, buffer, strlen(buffer));
MD5_Final(response, &md5c);
pbuffer = buffer2;
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
sprintf(pbuffer, "%02x", response[i]);
pbuffer += 2;
}
//compute response
if (!auth_find)
snprintf(buffer, 500, "%s:%s", nonce, buffer2);
@ -563,13 +477,11 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
MD5_Update(&md5c, ":", 1);
MD5_Update(&md5c, buffer, strlen(buffer));
MD5_Final(response, &md5c);
pbuffer = buffer;
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
sprintf(pbuffer, "%02x", response[i]);
pbuffer += 2;
}
//create the auth response
if (strstr(type, "proxy") != NULL) {
snprintf(result, 500,
@ -584,6 +496,9 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
if (strstr(type, "sip") != NULL) {
snprintf(result, 500, "username=\"%s\",realm=\"%s\",nonce=\"%s\",uri=\"%s:%s\",response=%s", preplogin, realm, nonce, type, realm, buffer);
} else{
if (strstr(type, "rtsp") != NULL) {
snprintf(result, 500, "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s://%s:%i\", response=\"%s\"\r\n", preplogin, realm, nonce, type, webtarget, port, buffer);
} else {
if (use_proxy == 1 && proxy_authentication != NULL)
snprintf(result, 500,
"%s http://%s:%d%s HTTP/1.0\r\nHost: %s\r\nAuthorization: Digest username=\"%s\", realm=\"%s\", response=\"%s\", nonce=\"%s\", cnonce=\"hydra\", nc=00000001, algorithm=%s, qop=auth, uri=\"%s\"\r\nProxy-Authorization: Basic %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\nConnection: keep-alive\r\n%s\r\n",
@ -601,21 +516,16 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
}
}
}
}
free(preplogin);
free(preppasswd);
}
/*
RFC 5802: Salted Challenge Response Authentication Mechanism
Note: SCRAM is a client-first SASL mechanism
I want to thx Simon Josefsson for his public server test,
and my girlfriend that let me work on that 2 whole nights ;)
clientfirstmessagebare must be at least 500 bytes in size!
*/
void sasl_scram_sha1(char *result, char *pass, char *clientfirstmessagebare, char *serverfirstmessage) {
int saltlen = 0;
@ -632,18 +542,14 @@ void sasl_scram_sha1(char *result, char *pass, char *clientfirstmessagebare, cha
char ClientProof[SHA_DIGEST_LENGTH];
unsigned char clientproof_b64[50];
char *preppasswd;
int rc = sasl_saslprep(pass, 0, &preppasswd);
if (rc) {
result = NULL;
return;
}
/*client-final-message */
if (debug)
hydra_report(stderr, "DEBUG S: %s\n", serverfirstmessage);
//r=hydra28Bo7kduPpAZLzhRQiLxc8Y9tiwgw+yP,s=ldDgevctH+Kg7b8RnnA3qA==,i=4096
if (strstr(serverfirstmessage, "r=") == NULL) {
hydra_report(stderr, "Error: Can't understand server message\n");
@ -657,7 +563,6 @@ void sasl_scram_sha1(char *result, char *pass, char *clientfirstmessagebare, cha
//continue to search from the previous successful call
salt = strtok(NULL, ",");
ic = strtok(NULL, ",");
iter = atoi(ic + 2);
if (iter == 0) {
hydra_report(stderr, "Error: Can't understand server response\n");
@ -665,7 +570,6 @@ void sasl_scram_sha1(char *result, char *pass, char *clientfirstmessagebare, cha
result = NULL;
return;
}
if ((nonce != NULL) && (strlen(nonce) > 2))
snprintf(clientfinalmessagewithoutproof, sizeof(clientfinalmessagewithoutproof), "c=biws,%s", nonce);
else {
@ -674,7 +578,6 @@ void sasl_scram_sha1(char *result, char *pass, char *clientfirstmessagebare, cha
result = NULL;
return;
}
if ((salt != NULL) && (strlen(salt) > 2) && (strlen(salt) <= sizeof(buffer)))
//s=ghgIAfLl1+yUy/Xl1WD5Tw== remove the header s=
strcpy(buffer, salt + 2);
@ -684,32 +587,25 @@ void sasl_scram_sha1(char *result, char *pass, char *clientfirstmessagebare, cha
result = NULL;
return;
}
/* SaltedPassword := Hi(Normalize(password), salt, i) */
saltlen = from64tobits((char *) salt, buffer);
if (PKCS5_PBKDF2_HMAC_SHA1(preppasswd, strlen(preppasswd), (unsigned char *) salt, saltlen, iter, SHA_DIGEST_LENGTH, SaltedPassword) != 1) {
hydra_report(stderr, "Error: Failed to generate PBKDF2\n");
free(preppasswd);
result = NULL;
return;
}
/* ClientKey := HMAC(SaltedPassword, "Client Key") */
#define CLIENT_KEY "Client Key"
HMAC(EVP_sha1(), SaltedPassword, SHA_DIGEST_LENGTH, (const unsigned char *) CLIENT_KEY, strlen(CLIENT_KEY), ClientKey, &resultlen);
/* StoredKey := H(ClientKey) */
SHA1((const unsigned char *) ClientKey, SHA_DIGEST_LENGTH, StoredKey);
/* ClientSignature := HMAC(StoredKey, AuthMessage) */
snprintf(AuthMessage, 500, "%s,%s,%s", clientfirstmessagebare, serverfirstmessage, clientfinalmessagewithoutproof);
HMAC(EVP_sha1(), StoredKey, SHA_DIGEST_LENGTH, (const unsigned char *) AuthMessage, strlen(AuthMessage), ClientSignature, &resultlen);
/* ClientProof := ClientKey XOR ClientSignature */
xor(ClientProof, (char *) ClientKey, (char *) ClientSignature, 20);
to64frombits(clientproof_b64, (const unsigned char *) ClientProof, 20);
snprintf(result, 500, "%s,p=%s", clientfinalmessagewithoutproof, clientproof_b64);
if (debug)
hydra_report(stderr, "DEBUG C: %s\n", result);