6358704 2001-04-12 08:44 -0400 /100 rader/ Peter W <peterw@USA.NET> Sänt av: joel@lysator.liu.se Importerad: 2001-04-12 22:26 av Brevbäraren Extern mottagare: BUGTRAQ@SECURITYFOCUS.COM Externa svar till: peterw@USA.NET Mottagare: Bugtraq (import) <16497> Ärende: Re: flaw in RH ``mkpasswd'' command (importance of seeds & ------------------------------------------------------------ algorithms) From: Peter W <peterw@USA.NET> To: BUGTRAQ@SECURITYFOCUS.COM Message-ID: <20010412084426.A8850@usa.net> On Wed, Apr 11, 2001 at 04:32:38PM +0100, Shez wrote: > The mkpasswd password generator that ships in the ``expect'' package of (at > least RedHat 6.2) generates only a relatively small number (2^15 for the > default password length) of passwords. Presumably this is a result of trying > to apply too many rules of what is a ``good'' password to the generation > process. The 'man' page suggests it should be more like 2^46 in default mode. In default mode you have >= 2 lowercase chars (26**2), >= 2 uppercase chars (26**2), >= 2 digits (10**2), and three others (62**3), for 10891017612800 possible passwords. It would probably be nice to make the script support characters like ~!@#$%^&*()-+, for serious use, don't you think? I expect (sorry!) this, like PalmOS/Strip, is a seeding/PRNG problem at its core. 'mkpasswd' is basically a Tcl script, right? Let's take a look: set _ran [pid] proc rand {m} { global _ran set period 259200 set _ran [expr ($_ran*7141 + 54773) % $period] expr int($m*($_ran/double($period))) } The seed is the process ID, so naturally the number of passwords is limited to the size of your process table (and even worse, is highly predictable). Use this code for better results: proc srand {} { global _ran set seedsource /dev/urandom ;# faster ;#set seedsource /dev/random ;# better ;# 'od' is used as an easy way of converting ;# /dev/random data to decimal numbers; suggestions welcome if {[file readable $seedsource] && [file executable /usr/bin/od]} { set _ran 1 ;# 5 iterations is enough for 2130706432 possibilities, and ;# srand() cannot handle a seed larger than the largest ;# integer, which is 2147483647 on x86 set modval 127 for {set i 0} {$i < 5} {incr i} { regsub {^0*} [lindex [exec od -N 1 -t d2 $seedsource] 1] {} bval if {[string length $bval] == 0} {set bval 0} set bval [expr ( $bval % $modval ) + 1] set _ran [expr $_ran * $bval] set modval 64 } } else { puts stderr "Error: unable to get good random seed!" exit 1 } expr srand($_ran) } ;#srand ;# if we only wanted to seed once proc rand {m} { srand ;# re-seed every time for more random passwords return [expr int($m * rand())] } This requires Tcl 8, since I'm using its rand() function. Tcl 8 defaults to using the system clock for the seed of its PRNG, which is why I'd go to the trouble of getting a better seed. Still, with srand() only accepting some 2.1e9 seed values, there are at most "only" 2.1e9 possible passwords if you use the Tcl 8 rand() function and only seed it once. But testing suggests that seeding only once is a bad idea... How effective is the code? Using /dev/urandom and a single seeding, in 120000 invocations I had some 88,000+ unique passwords w/ mkpasswd's default mode; clearly breaking the 2^15 barrier, but a large number of duplicates. With /dev/random things move much more slowly, but after some 22000 runs, it's showing about as many dupes as it did after 22000 runs with /dev/urandom. So the rand() routine in Tcl 8.x seems not very desirable for security applications, not that this is a big surprise.[0] On the other hand, with the faster but "weaker" /dev/urandom as the random source but re-seeding with every use of the rand function (as shown above), I've made over 45000 passwords with no duplication. In any case, this is yet another nice study of the importance of both good seeding *and* good PRNG algorithms for security applications. -Peter [0] The algorithm used in Red Hat's mkpasswd looks like one I first encountered in Brent Welch's book, and was an attempt to add a PRNG to Tcl 7.6. In that routine, you can clearly see that the size of $period limits the number of possible random values. Tcl is mostly a string-based language, so it's not surprising that we run into trouble getting strongly random numbers out of it; though it's also a language that it easily extended via DLL/so libraries, so it's not a fatal problem. But it is important to understand if you're writing security-related applications, or running a casino. (6358704) /Peter W <peterw@USA.NET>/------(Ombruten) 6358782 2001-04-12 13:18 +0100 /32 rader/ Shez <shez@MOLIONS.COM> Sänt av: joel@lysator.liu.se Importerad: 2001-04-12 22:44 av Brevbäraren Extern mottagare: BUGTRAQ@SECURITYFOCUS.COM Externa svar till: shez@MOLIONS.COM Mottagare: Bugtraq (import) <16500> Kommentar till text 6358602 av Lee Howard <faxguy@DEANOX.COM> Ärende: Re: flaw in RH ``mkpasswd'' command ------------------------------------------------------------ From: Shez <shez@MOLIONS.COM> To: BUGTRAQ@SECURITYFOCUS.COM Message-ID: <01041213184501.00669@kara> Hi, PeterW@usa.net pointed out to me that if the man page for mkpasswd is correct then this shouldn't be the problem, and that it may be a seeding problem. The code appears to seed of pid and uses its own generator: set _ran [pid] proc rand {m} { global _ran set period 259200 set _ran [expr ($_ran*7141 + 54773) % $period] expr int($m*($_ran/double($period))) } Anyhow, writing a perl/any language replacement would be a good move for anyone who's been using this command. Cheers Shez On Thursday 12 April 2001 00:55, you wrote: > Although I wonder if they're not outweighing the risk of dropping some of > those rules over the risk of having fewer possible passwords. (Not to say > that I agree with that, though.) > > Lee. (6358782) /Shez <shez@MOLIONS.COM>/-------(Ombruten)