Hi, After reading Shaun Clowes' "A Study In Scarlet" (http://www.securereality.com.au/studyinscarlet.txt) I decided to take a peek at how php / phplib create the session ids. I just had a quick peek so the following 'information' is based on first impressions and is probably full of errors. I hope this could stir up some discussion about session id generation / using timeofday as random seed/value etc. (or could somebody point me to some references). --------- php-4.0.6 session generation --------- Here's a snippet from php-4.0.6 session.c (_php_create_id): gettimeofday(&tv, NULL); PHP_MD5Init(&context); sprintf(buf, "%ld%ld%0.8f", tv.tv_sec, tv.tv_usec, php_combined_lcg() *\ 10); PHP_MD5Update(&context, buf, strlen(buf)); if (PS(entropy_length) > 0) { int fd; fd = VCWD_OPEN((PS(entropy_file), O_RDONLY)); if (fd >= 0) { char *p; int n; p = emalloc(PS(entropy_length)); n = read(fd, p, PS(entropy_length)); if (n > 0) { PHP_MD5Update(&context, p, n); } efree(p); close(fd); } } PHP_MD5Final(digest, &context); From this it looks like if you don't have entropy_file/entropy_length defined(in php.ini) the created session id is not very random: md5hash of timeofday and php_combined_lcg (I assume that ...lcg is just a simple pseudorandom gen). Using /dev/{u,a}random as entropy_file should make the session id quite hard to guess. --------- php-4.0.6 lcg function --------- Here's the code snippet for the lcg (lcg.c): double php_combined_lcg(void) { long q; long z; LCGLS_FETCH(); MODMULT(53668,40014,12211,2147483563L, LCG(s1)); MODMULT(52774,40692,3791, 2147483399L, LCG(s2)); z = LCG(s1) - LCG(s2); if(z < 1) { z += 2147483562; } return z * 4.656613e-10; } static void lcg_init_globals(LCGLS_D) { LCG(s1) = 1; #ifdef ZTS LCG(s2) = (long) tsrm_thread_id(); #else LCG(s2) = (long) getpid(); #endif } If I understand the code somewhat right it uses getpid() and 1 as the initial values. Getpid is probably not that hard to obtain/guess: If you have local access or you know the server is eg. default redhat-xx box with only apache running --> guess/test what pid (range of pids) apache can get. --------- phplib-7.2c session generation --------- Here's a snippet from phplib-7.2c session.inc (get_id): if ( "" == $id ) { $newid=true; $id = $this->that->ac_newid(md5(uniqid($this->magic)), $this->name); } Here the session id is md5hash of uniqid($this->magic)). php's uniqid creates a string from (uniqid.c): gettimeofday((struct timeval *) &tv, (struct timezone *) NULL); sec = (int) tv.tv_sec; usec = (int) (tv.tv_usec % 1000000); /* The max value usec can have is 0xF423F, so we use only five hex * digits for usecs. */ if (MORE_ENTROPY) { sprintf(uniqid, "%s%08x%05x%.8f", (*prefix)->value.str.val, sec, usec, php_combined_lcg() * 10); } else { sprintf(uniqid, "%s%08x%05x", (*prefix)->value.str.val, sec, use c); } RETURN_STRING(uniqid,1); So from this it appears that phplib creates the session id from a $this->magic and timeofday. (Phplib doesn't use the more entropy parameter when calling uniqid). So if you know the second when session id was created and $this->magic then there're only 1000000 possible values. I would think that with timing and (since some computers don't have usec timers) there would be a lot less? than million values to try. Has anyone done more research on this ? If I remember correctly using timeofday as 'random' (seed?) was one of the reasons why netscape's ssl and kerberos4 keys were cracked ? And for the phplib's session id generation: Why not read some extra entropy from entropy_file (if defined in php.ini) and create the session id as md5(uniqid(...) . $entropy_from_file) ? What methods could attacker use to determine the time on the server ? Use ntp if the server has ntp-server... What about tcp-timestamps could they be used for determining the time ? -Jarno -- Jarno Huuskonen <Jarno.Huuskonenat_private>
This archive was generated by hypermail 2b30 : Thu Jul 05 2001 - 08:13:21 PDT