15/04/2014

PHP Source Code Chunks of Insanity (Logout Pages) Part 2

Intro 

This post is going to talk about source code reviewing PHP and demonstrate how a relatively small chunk of code can cause you lots of problems.

The Code

In this article we are going to analyze the code displayed below. The code displayed below might seem innocent for some , but obviously is not. We are going to assume that is used by some web site to de-validate the user credentials and allow the users to logout securely.

1:  <?php  
2:  require_once 'common.php';  
3:  if (isset($_SESSION['username']))//Insecure source  
4:  {  
5:  session_unset();// In properly destroyed session.  
6:  }  
7:  header('Location: index.php'); ?>  


I you look carefully the code you will se that the code is vulnerable to the following issues:
  1. NULL De-­Authentication Bypass    
  2. No Proper Session Termination    
Think this is not accurate , think better.

NULL De-­Authentication Bypass 

Exploitation:

An adversary may on purpose exploit this vulnerability possibly without the need of developing any costume tools (but needs a good understanding of PHP design flaws). More specifically an adversary can manipulate the cookie parameter and de-­‐validate the logout process by injecting a NULL value in the begging of the username (after the authentication). This would result into maintaining the user Web resources available for the specific session-­‐id even after the logout is performed. 

Vulnerable Code:    
if (isset($_SESSION['username']))// Malicious de-­validation cancel  
Assuming that the target username is user12 potential malicious payloads that could exploit the vulnerability displayed above would be user[space]12 , %4e%55%4c%4c,user12, user12[space], %20user12, [space] [space]user12 [space],user12 , user12, user12,, user12NULL NULLuser12 etc. This is applicable due to the fact that if multiple parameters are supplied then the isset will return TRUE only if all of the parameters are set. Evaluation goes from left to right and stops as soon as an unset variable is encountered. The attack should occur after the user successfully authenticates her self.

Note1: At this point it should be noted that when on, register_globals (which is on by default in PHP < 5.3.0), will allow an adversary to populate the cookie username variable from various user input such request variables from HTML hidden form fields, Web Application URL’s etc. which translates into working as a vulnerability amplifier! Also this might lead into allowing POST to GET interchanges, promoting CSRF like attacks (e.g. the web app does not distinguish POST from GET).

Note2: This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0. 

Remedial Code:
1:  //the filter makes sure the username has no spaces. if (strpos($username, " ") !== false){  
2:  // De-­‐validate the session  
3:  }  

2nd Code Chunk:
1:  trim("^$", $username)//Not recommended to process malicious payloads, only identify.  

Note: The NULL value translates into an empty string when validations come. 

No Proper Session Termination

An adversary may on purpose exploit this vulnerability without the need of developing any costume tools. This attack might be used to perform vertical/horizontal user escalation (e.g. the cookie session-­‐ id is assigned to a new user, and the new user automatically gains access to previous user Web resources, assuming that the Web Apps makes access control decisions by using only the session-­‐id. Another attack scenario would be that the session is leaked though a blog post and the adversary makes use of the non de-­‐validated leaked session to gain access to the Web Application user resources etc.).

Vulnerable Code: 
1:  session_unset(); // Improper handling of the session.  
Note1: The function shown above does not properly de-­‐validate the session. The session_unset function just clears the $_SESSION variable. It’s equivalent to doing $_SESSION = array(); So this does only affect the local $_SESSION variable instance, but not the session data in the session storage, everything else remains unchanged (including the session identifier). In this occasion the session_unset is used to destroy/reset the session instead of the session_destroy function in the logout page. The session_destroy() function destroys all of the data associated with the current session.

Note2: The variable session_unset is considered to be deprecated code that does not use $_SESSION.

Remedial Code: 
1:  function destroySession() {  
2:  $params = session_get_cookie_params(); setcookie(session_name(), '', time() -­‐ 42000,  
3:  $params["path"], $params["domain"],  
4:  ... );  
5:  session_destroy(); }  




References:

1. http://php.net/manual/en/security.globals.php
2. https://www.owasp.org/index.php/Unvalidated_Input
3. http://php.net/manual/en/function.isset.php
4. http://php.net/manual/en/function.trim.php