File: hydra-redis.c

package info (click to toggle)
hydra 9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 4,008 kB
  • sloc: ansic: 21,638; sh: 2,166; makefile: 110
file content (185 lines) | stat: -rw-r--r-- 6,031 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include "hydra-mod.h"

extern char *HYDRA_EXIT;
char *buf;

int32_t start_redis(int32_t s, char *ip, int32_t port, unsigned char options, char *miscptr, FILE * fp) {
  char *pass, buffer[510];
  char *empty = "";

  if (strlen(pass = hydra_get_next_password()) == 0)
    pass = empty;

  char pass_num[50];
  int32_t pass_len = strlen(pass);
  snprintf(pass_num, 50, "%d", pass_len);

  memset(buffer, 0, sizeof(buffer));
  sprintf(buffer, "*2\r\n$4\r\nAUTH\r\n$%.50s\r\n%.250s\r\n", pass_num, pass);

  if (debug)
    hydra_report(stderr, "[DEBUG] Auth:\n %s\n", buffer);

  if (hydra_send(s, buffer, strlen(buffer), 0) < 0) {
    return 1;
  }
  buf = hydra_receive_line(s);
  if (buf[0] == '+') {
    hydra_report_found_host(port, ip, "redis", fp);
    hydra_completed_pair_found();
    free(buf);
    if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
      return 4;
    return 1;
  }

  if (buf[0] == '-') {
    if (verbose > 1)
      hydra_report(stderr, "[VERBOSE] Authentication failed for password %s\n", pass);
    hydra_completed_pair();
    free(buf);
    if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
      return 4;
    return 2;
  } else {
    hydra_report(stderr, "[ERROR] Redis service shutdown.\n");
    free(buf);
    return 3;
  }

  /* not reached */
  return 1;
}

void service_redis_core(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE * fp, int32_t port, char *hostname, int32_t tls) {
  int32_t run = 1, next_run = 1, sock = -1;
  int32_t myport = PORT_REDIS, mysslport = PORT_REDIS_SSL;

  hydra_register_socket(sp);
  if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
    hydra_child_exit(0);

  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;
      } else {
        if (port != 0)
          mysslport = port;
        sock = hydra_connect_ssl(ip, mysslport, hostname);
        port = mysslport;
      }
      if (sock < 0) {
        if (verbose || debug)
          hydra_report(stderr, "[ERROR] Child with pid %d terminating, can not connect\n", (int32_t) getpid());
        hydra_child_exit(1);
      }
      usleepn(250);
      next_run = 2;
      break;
    case 2:                    /* run the cracking function */
      next_run = start_redis(sock, ip, port, options, miscptr, fp);
      break;
    case 3:                    /* error exit */
      if (sock >= 0)
        sock = hydra_disconnect(sock);
      hydra_child_exit(2);
      break;
    case 4:                    /* clean exit */
      if (sock >= 0)
        sock = hydra_disconnect(sock);
      hydra_child_exit(0);
    default:
      hydra_report(stderr, "[ERROR] Caught unknown return code, exiting!\n");
      hydra_child_exit(2);
    }
    run = next_run;
  }
}

void service_redis(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE * fp, int32_t port, char *hostname) {
  service_redis_core(ip, sp, options, miscptr, fp, port, hostname, 0);
}

/* 
* Initial password authentication test and response test for the redis server,
* added by Petar Kaleychev <petar.kaleychev@gmail.com>
* The service_redis_init function is generating ping request as redis-cli (command line interface). 
* You can use redis-cli to connect with Redis. After start of the redis-server in another terminal the following:
*    % ./redis-cli
*    redis> ping
*    when the server does not require password, leads to:
*    PONG
*    when the server requires password, leads to:
*    (error) NOAUTH Authentication required.
*    or
*    (error) ERR operation not permitted      (for older redis versions)
* That is used for initial password authentication and redis server response tests in service_redis_init
*/
int32_t service_redis_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE * fp, int32_t port, char *hostname) {
  // 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.
  // return codes:
  // 0 - when the server is redis and it requires password
  // 1 - when the server is not redis or when the server does not require password

  int32_t sock = -1;
  int32_t myport = PORT_REDIS, mysslport = PORT_REDIS_SSL;
  char buffer[] = "*1\r\n$4\r\nping\r\n";

  hydra_register_socket(sp);
  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 (verbose)
    printf("[VERBOSE] Initial redis password authentication test and response test ...\n");
  if (sock < 0) {
    hydra_report(stderr, "[ERROR] Can not connect to port %d on the target\n", myport);
    hydra_child_exit(1);
  }
  // generating ping request as redis-cli
  if (debug)
    printf("[DEBUG] buffer = %s\n", buffer);
    //    [debug mode]: buffer is:
    //    *1
    //    $4
    //    ping
  if (hydra_send(sock, buffer, strlen(buffer), 0) < 0) {
    return 1;
  }
  buf = hydra_receive_line(sock);
  if (debug)
    printf("[DEBUG] buf = %s\n", buf);
  // authentication test
  if (strstr(buf, "+PONG") != NULL) { // the server does not require password
    hydra_report(stderr, "[!] The server does not require password.\n");
    free(buf);
    return 1;
  }
  // server response test
  if (strstr(buf, "-NOAUTH Authentication required") == NULL && strstr(buf, "-ERR operation not permitted") == NULL) {
    hydra_report(stderr, "[ERROR] The server is not redis, exit.\n");
    free(buf);
    return 1;
  }
  if (verbose)
    printf("[VERBOSE] The redis server requires password.\n");
  free(buf);
  sock = hydra_disconnect(sock);
  return 0;
}