Suggestion: SSHD pseudo/fake mode. Source available.

Daniel Kastenholz daniel.kastenholz at in.tum.de
Sat Feb 26 04:50:22 EST 2005


Hi,

- context: yesterday I suggested a command line option for sshd that 
turns the daemon into a fake (or pseudo) daemon to listen on port 22 
while denying all logins even if the provided passwords are right. The 
reason for this suggestion was the increasing number of brute force 
attacks against SSH daemons and the wish to provide intruders a 
playground where they can waste their time while being monitored and 
without the chance to actually break anything.

I received a couple of replies and there seems to be interest in such an 
option. As requested, I have now run a diff against the modified sources 
(originally 3.9p1). The whole patch needs about 30 lines including 
comments. It adds a command line option '-T' to sshd for enabling the 
trap mode. The output of the diff follows at the end of this message. 
Hope this helps.

If you have any further remarks, suggestions, questions ... just drop me 
a line. I assume the patch could be modified to use even less lines, but 
it works like this.

Do I have to file this diff anywhere else to make the patch request 
official?

Regards,

Daniel

--------------------

diff --context=3 openssh-3.9p1/auth.h modified/auth.h
*** openssh-3.9p1/auth.h    Mon May 24 02:36:23 2004
--- modified/auth.h    Wed Feb 23 16:41:51 2005
***************
*** 50,55 ****
--- 50,56 ----
      int         success;
      int         postponed;    /* authentication needs another step */
      int         valid;        /* user exists and is allowed to login */
+     int         trap;        /* enforces login denial in trap mode */
      int         attempt;
      int         failures;
      int         force_pwchange;
diff --context=3 openssh-3.9p1/auth1.c modified/auth1.c
*** openssh-3.9p1/auth1.c    Thu Aug 12 14:40:25 2004
--- modified/auth1.c    Wed Feb 23 16:35:22 2005
***************
*** 74,80 ****
          authctxt->valid ? "" : "invalid user ", authctxt->user);
 
      /* If the user has no password, accept authentication immediately. */
!     if (options.password_authentication &&
  #ifdef KRB5
          (!options.kerberos_authentication || 
options.kerberos_or_local_passwd) &&
  #endif
--- 74,80 ----
          authctxt->valid ? "" : "invalid user ", authctxt->user);
 
      /* If the user has no password, accept authentication immediately. */
!     if (authctxt->trap==0 && options.password_authentication &&
  #ifdef KRB5
          (!options.kerberos_authentication || 
options.kerberos_or_local_passwd) &&
  #endif
***************
*** 142,148 ****
                      BN_num_bits(client_host_key->rsa->n), bits);
              packet_check_eom();
 
!             authenticated = auth_rhosts_rsa(authctxt, client_user,
                  client_host_key);
              key_free(client_host_key);
 
--- 142,148 ----
                      BN_num_bits(client_host_key->rsa->n), bits);
              packet_check_eom();
 
!             authenticated = (authctxt->trap==0) && 
auth_rhosts_rsa(authctxt, client_user,
                  client_host_key);
              key_free(client_host_key);
 
***************
*** 159,165 ****
                  fatal("do_authloop: BN_new failed");
              packet_get_bignum(n);
              packet_check_eom();
!             authenticated = auth_rsa(authctxt, n);
              BN_clear_free(n);
              break;
 
--- 159,165 ----
                  fatal("do_authloop: BN_new failed");
              packet_get_bignum(n);
              packet_check_eom();
!             authenticated = (authctxt->trap==0) && auth_rsa(authctxt, n);
              BN_clear_free(n);
              break;
 
***************
*** 177,183 ****
              packet_check_eom();
 
              /* Try authentication with the password. */
!             authenticated = PRIVSEP(auth_password(authctxt, password));
 
              memset(password, 0, strlen(password));
              xfree(password);
--- 177,183 ----
              packet_check_eom();
 
              /* Try authentication with the password. */
!             authenticated = (authctxt->trap==0) && 
PRIVSEP(auth_password(authctxt, password));
 
              memset(password, 0, strlen(password));
              xfree(password);
***************
*** 203,209 ****
              if (options.challenge_response_authentication == 1) {
                  char *response = packet_get_string(&dlen);
                  packet_check_eom();
!                 authenticated = verify_response(authctxt, response);
                  memset(response, 'r', dlen);
                  xfree(response);
              }
--- 203,209 ----
              if (options.challenge_response_authentication == 1) {
                  char *response = packet_get_string(&dlen);
                  packet_check_eom();
!                 authenticated = (authctxt->trap==0) && 
verify_response(authctxt, response);
                  memset(response, 'r', dlen);
                  xfree(response);
              }
diff --context=3 openssh-3.9p1/auth2.c modified/auth2.c
*** openssh-3.9p1/auth2.c    Thu Aug 12 14:40:25 2004
--- modified/auth2.c    Wed Feb 23 16:35:23 2005
***************
*** 210,215 ****
--- 210,218 ----
          fatal("INTERNAL ERROR: authenticated invalid user %s",
              authctxt->user);
 
+     /* Deny login if in trap mode */
+     if (authctxt->trap!=0) authenticated = 0;
+
      /* Special handling for root */
      if (authenticated && authctxt->pw->pw_uid == 0 &&
          !auth_root_allowed(method))
Common subdirectories: openssh-3.9p1/contrib and modified/contrib
Common subdirectories: openssh-3.9p1/openbsd-compat and 
modified/openbsd-compat
Common subdirectories: openssh-3.9p1/regress and modified/regress
Common subdirectories: openssh-3.9p1/scard and modified/scard
diff --context=3 openssh-3.9p1/sshd.c modified/sshd.c
*** openssh-3.9p1/sshd.c    Thu Aug 12 15:08:15 2004
--- modified/sshd.c    Wed Feb 23 17:14:34 2005
***************
*** 125,130 ****
--- 125,137 ----
   */
  int debug_flag = 0;
 
+ /*
+  * Trap mode flag. In this mode, the entire authentication procedure
+  * takes place, but the login always fails. The purpose of this flag
+  * is to enable the setup of fake servers for intrusion detection.
+  */
+ int trap_flag = 0;
+
  /* Flag indicating that the daemon should only test the configuration 
and keys. */
  int test_flag = 0;
 
***************
*** 776,782 ****
      fprintf(stderr, "%s, %s\n",
          SSH_VERSION, SSLeay_version(SSLEAY_VERSION));
      fprintf(stderr,
! "usage: sshd [-46Ddeiqt] [-b bits] [-f config_file] [-g 
login_grace_time]\n"
  "            [-h host_key_file] [-k key_gen_time] [-o option] [-p 
port] [-u len]\n"
      );
      exit(1);
--- 783,789 ----
      fprintf(stderr, "%s, %s\n",
          SSH_VERSION, SSLeay_version(SSLEAY_VERSION));
      fprintf(stderr,
! "usage: sshd [-46DdeiqtT] [-b bits] [-f config_file] [-g 
login_grace_time]\n"
  "            [-h host_key_file] [-k key_gen_time] [-o option] [-p 
port] [-u len]\n"
      );
      exit(1);
***************
*** 918,924 ****
      initialize_server_options(&options);
 
      /* Parse command-line arguments. */
!     while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:dDeiqrtQR46")) != -1) {
          switch (opt) {
          case '4':
              IPv4or6 = AF_INET;
--- 925,931 ----
      initialize_server_options(&options);
 
      /* Parse command-line arguments. */
!     while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:dDeiqrtQR46T")) != -1) {
          switch (opt) {
          case '4':
              IPv4or6 = AF_INET;
***************
*** 929,934 ****
--- 936,944 ----
          case 'f':
              config_file_name = optarg;
              break;
+         case 'T':
+             trap_flag = 1;
+             break;
          case 'd':
              if (debug_flag == 0) {
                  debug_flag = 1;
***************
*** 1675,1680 ****
--- 1685,1693 ----
      authctxt = xmalloc(sizeof(*authctxt));
      memset(authctxt, 0, sizeof(*authctxt));
 
+     /* set trap indicator if in trap mode */
+     if (trap_flag != 0) authctxt->trap = 1;
+
      /* XXX global for cleanup, access from other modules */
      the_authctxt = authctxt;
 




More information about the openssh-unix-dev mailing list