hydra-ssh.c 6.47 KB
Newer Older
Mati's avatar
Mati committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*

libssh is available at http://www.libssh.org
If you want support for ssh v1 protocol, you
have to add option -DWITH_SSH1=On in the cmake

*/

#include "hydra-mod.h"
#ifndef LIBSSH
void dummy_ssh() {
  printf("\n");
}
#else

#include <libssh/libssh.h>

#if LIBSSH_VERSION_MAJOR == 0 && LIBSSH_VERSION_MINOR >= 4

ssh_session session = NULL;

extern char *HYDRA_EXIT;
23
int32_t new_session = 1;
Mati's avatar
Mati committed
24

25
int32_t start_ssh(int32_t s, char *ip, int32_t port, unsigned char options, char *miscptr, FILE * fp) {
Mati's avatar
Mati committed
26 27
  char *empty = "";
  char *login, *pass, keep_login[300];
28
  int32_t auth_state = 0, rc = 0, i = 0;
Mati's avatar
Mati committed
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

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

  if (new_session) {
    if (session) {
      ssh_disconnect(session);
      ssh_finalize();
      ssh_free(session);
    }

    session = ssh_new();
    ssh_options_set(session, SSH_OPTIONS_PORT, &port);
    ssh_options_set(session, SSH_OPTIONS_HOST, hydra_address2string(ip));
    ssh_options_set(session, SSH_OPTIONS_USER, login);
    ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "none");
    ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "none");
    if (ssh_connect(session) != 0) {
      //if the connection was drop, exit and let hydra main handle it
      if (verbose)
51
        hydra_report(stderr, "[ERROR] could not connect to target port %d: %s\n", port, ssh_get_error(session));
Mati's avatar
Mati committed
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
      return 3;
    }

    if ((rc = ssh_userauth_none(session, NULL)) == SSH_AUTH_ERROR) {
      return 3;
    } else if (rc == SSH_AUTH_SUCCESS) {
      hydra_report_found_host(port, ip, "ssh", fp);
      hydra_completed_pair_found();
      if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
        return 2;
      else
        return 1;
    }
  } else
    new_session = 1;

  auth_state = ssh_auth_list(session);
  if ((auth_state & SSH_AUTH_METHOD_PASSWORD) > 0) {
    auth_state = ssh_userauth_password(session, NULL, pass);
  } else if ((auth_state & SSH_AUTH_METHOD_INTERACTIVE) > 0) {
    auth_state = ssh_userauth_kbdint(session, NULL, NULL);
    while (auth_state == SSH_AUTH_INFO) {
      rc = ssh_userauth_kbdint_getnprompts(session);
      for (i = 0; i < rc; i++)
        ssh_userauth_kbdint_setanswer(session, i, pass);
      auth_state = ssh_userauth_kbdint(session, NULL, NULL);
    }
  } else {
    return 4;
  }

83
  if (auth_state == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
Mati's avatar
Mati committed
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
    new_session = 1;
    return 1;
  }

  if (auth_state == SSH_AUTH_SUCCESS || auth_state == SSH_AUTH_PARTIAL) {
    hydra_report_found_host(port, ip, "ssh", fp);
    hydra_completed_pair_found();
    if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
      return 2;
    return 1;
  } else {
    strncpy(keep_login, login, sizeof(keep_login) - 1);
    keep_login[sizeof(keep_login) - 1] = '\0';
    hydra_completed_pair();
    if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
      return 2;
    login = hydra_get_next_login();
    if (strcmp(login, keep_login) == 0)
      new_session = 0;
    return 1;
  }

  /* not reached */
  return 1;
}

110 111
void service_ssh(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE * fp, int32_t port, char *hostname) {
  int32_t run = 1, next_run = 1, sock = -1;
Mati's avatar
Mati committed
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129

  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 */
      next_run = start_ssh(sock, ip, port, options, miscptr, fp);
      break;
    case 2:
      ssh_disconnect(session);
      ssh_finalize();
      ssh_free(session);
      hydra_child_exit(0);
    case 3:
      ssh_disconnect(session);
      ssh_finalize();
      ssh_free(session);
Mati's avatar
Mati committed
130 131
      if (verbose)
        fprintf(stderr, "[ERROR] ssh protocol error\n");
Mati's avatar
Mati committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
      hydra_child_exit(2);
    case 4:
      ssh_disconnect(session);
      ssh_finalize();
      ssh_free(session);
      fprintf(stderr, "[ERROR] ssh target does not support password auth\n");
      hydra_child_exit(2);
    default:
      ssh_disconnect(session);
      ssh_finalize();
      ssh_free(session);
      hydra_report(stderr, "[ERROR] Caught unknown return code, exiting!\n");
      hydra_child_exit(2);
    }
    run = next_run;
  }
}
#else
#error "You are not using v0.4.x. Download from http://www.libssh.org and add -DWITH_SSH1=On in cmake to enable SSH v1 support"
#endif
#endif

154 155 156 157 158
//
// dirty workaround here: miscptr is the ptr to the logins, and the first one is used
// to test if password authentication is enabled!!
//
int32_t service_ssh_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE * fp, int32_t port, char *hostname) {
Mati's avatar
Mati committed
159 160 161 162 163 164 165 166
  // 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
Mati's avatar
Mati committed
167 168 169 170
  //   1 skip target without generating an error
  //   2 skip target because of protocol problems
  //   3 skip target because its unreachable
#ifdef LIBSSH
171
  int32_t rc, method;
Mati's avatar
Mati committed
172 173 174
  ssh_session session = ssh_new();
  
  if (verbose || debug)
175
    printf("[INFO] Testing if password authentication is supported by ssh://%s@%s:%d\n", miscptr == NULL ? "hydra" : miscptr, hydra_address2string_beautiful(ip), port);
Mati's avatar
Mati committed
176 177
  ssh_options_set(session, SSH_OPTIONS_PORT, &port);
  ssh_options_set(session, SSH_OPTIONS_HOST, hydra_address2string(ip));
178 179 180 181
  if (miscptr == NULL)
    ssh_options_set(session, SSH_OPTIONS_USER, "hydra");
  else
    ssh_options_set(session, SSH_OPTIONS_USER, miscptr);
Mati's avatar
Mati committed
182 183 184
  ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "none");
  ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "none");
  if (ssh_connect(session) != 0) {
185
    fprintf(stderr, "[ERROR] could not connect to ssh://%s:%d - %s\n", hydra_address2string_beautiful(ip), port, ssh_get_error(session));
Mati's avatar
Mati committed
186 187 188 189 190 191 192 193 194 195
    return 2;
  } 
  rc = ssh_userauth_none(session, NULL);
  method = ssh_userauth_list(session, NULL); 
  ssh_disconnect(session);
  ssh_finalize();
  ssh_free(session);

  if ((method & SSH_AUTH_METHOD_INTERACTIVE) || (method & SSH_AUTH_METHOD_PASSWORD)) {
    if (verbose || debug)
196
      printf("[INFO] Successful, password authentication is supported by ssh://%s:%d\n", hydra_address2string_beautiful(ip), port);
Mati's avatar
Mati committed
197 198
    return 0;
  }
Mati's avatar
Mati committed
199

200
  fprintf(stderr, "[ERROR] target ssh://%s:%d/ does not support password authentication.\n", hydra_address2string_beautiful(ip), port);
Mati's avatar
Mati committed
201 202
  return 1;
#else
Mati's avatar
Mati committed
203
  return 0;
Mati's avatar
Mati committed
204
#endif
Mati's avatar
Mati committed
205
}