Buggy debug output from nrpe since 2.1

Andreas Ericsson ae at op5.se
Fri Feb 24 11:38:46 CET 2006


sean finney wrote:
> hi guys,
> 
> On Thu, Feb 23, 2006 at 09:21:16PM +0100, Gerhard Lausser wrote:
> 
>>Ethan, you applied my nrpe-2.3-allow_weak_random_seed patch to the 2.4
>>branch. Would you be so kind and add another line, which came to my mind
>>later? The results of the rand() calls in the last fallback might be
>>predictable, so seeding with the current time is necessary.
>>It's just a "srand(time(NULL));" after the syslog call. I attached a patch
>>file for the 1.42
> 
> 
> i'd like to advise against this, and maybe comment on a bit
> more on the use of random bits in nrpe.  
> 
> srand should really only be called once, and with a value that is as
> unpredictable as possible.  instead of calling srand(time(NULL)), i
> might suggest something like the following:
> 
>        seed=(int)time(NULL)*311-getpid()*359+getppid()*383;
> 
> which makes remote attacks on the prng more or less impossible, and local
> ones difficult at best.  i'm not sure why you would need to call it
> multiple times.
> 

Unfortunately it doesn't. It's possible to determine what a hosts system 
clock is set to by either watching ntp traffic to/from the host (with 
great accuracy), or by watching arbitrary packets sent from the host 
(with less precision, but still accurate enough for a time() seeding). 
Since the constants are known the integer overflowing is irrelevant for 
all practical purposes.

For cracking the above seeding, one can take a wild guess that ppid is 
one less than pid and do something like this:
guessed_seed = (sniffed_time - 1) * 42761567;

Multiplication takes precedence, remember?
If your omitting of parentheses was a mistake it makes the thing a bit 
more computationally expensive, but not so much it's impossible using 
any reasonably modern computer.

> also, nrpe currently reads a random byte from /dev/urandom for seeding
> it the first time.  i'd like to point out that this means that the prng
> is seeded with a value that is strictly between 0 and 255 inclusive.
> that's not a very large search space for someone trying to crack
> something.
> 

True. It would be far better to read a full int. For time-seeding it's 
preferrable to xor-fold a timeval-struct into an int, like so:

gettimeofday(&tv);
sec = (int)(tv.tv_sec ^ tv.tv_sec >> (__WORDSIZE - 32));
usec = (int)(tv.tv_usec ^ tv.tv_usec >> (__WORDSIZE - 32));
seed = sec ^ usec;

It might be useful to throw in a clock() count there as well, since 
those aren't so easily determined remotely.

> it also drains precious entropy from the system by reading from the
> random device.

You would have to read an exceedingly large data-set from the random 
devices to drain it of entropy. The PRNG (in Linux at least) loops after 
2^64 bytes unless the state is continuously and additively seeded (which 
it is).

However, considering we're not transmitting passwords or anything people 
would usually like to bend over backwards to keep secret, I'd say random 
seeding isn't something to spend a lot of time on.

-- 
Andreas Ericsson                   andreas.ericsson at op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231


-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642




More information about the Developers mailing list