PDA

Bekijk Volledige Versie : phpBB 2.0.8a and lower - IP spoofing vulnerability



Ready Response
20/04/04, 03:05
################################################## ###################

Advisory Name : phpBB 2.0.8a and lower - IP spoofing vulnerability
Release Date : Apr 18, 2004
Application : phpBB
Version : phpBB 2.0.8a and previous versions
Platform : PHP
Vendor URL : http://www.phpbb.com/
Author : Wang / SRR Project Group of Ready Response (srr@readyresponse.org)

################################################## ###################

Overview

A vulnerability has been reported to exist in the software that may allow a remote user to spoof/forge their IP address, therefore making the phpBB/Administrator believe that users/posts are coming from a false IP. The problem reportedly exists in the cod
e to obtain the users IP address in the common.php script. This issue is caused by blind trust of the X-Forwarded-For HTTP header. A remote attacker may exploit this issue to hide their IP address, or appear under the IP address of another user. It can al
so be used to bypass any ban restrictions that an administrator has placed on an IP via the PHPBB system.

------------------------------------------------

Discussion

There is code in common.php that starts:

//
// Obtain and encode users IP
//
if( getenv('HTTP_X_FORWARDED_FOR') != '' )
{
$client_ip = ( !empty($HTTP_SERVER_VARS['REMOTE_ADDR']) ) ? $HTTP_SERVER_VARS['REMOTE_ADDR'] : ( ( !empty($HTTP_ENV_VARS['REMOTE_ADDR']) ) ? $HTTP_ENV_VARS['REMOTE_ADDR'] : $REMOTE_ADDR );

This code is used to obtain the users/posters IP address. However, if the X-Forwarded-For HTTP header is present, it will take the IP address from the header and blindly trust it to be the users/posters IP address. The problem is of course that the X-Forw
arded-For HTTP header is easily forgable via a number of methods.

To take a trivial example...if a user were to spoof their X-Forwarded-For header to contain the information:

X-Forwarded-For: 1.3.3.7

When they post on a phpBB board - it blindly trusts that "1.3.3.7" is the users real IP address, and will present this IP address to the phpBB administrator if they choose to check the posters IP via the phpBB. Not only does this make it a pain for the ph
pBB administrator to then have to track down the users real IP via httpd server logs (if this is possible, which is not always the case) - it also makes it possible for a user to forge/spoof their IP to that of another user in a possible attempt to masque
rade as them.

In addition, this makes phpBB's IP ban feature close to useless because anyone can change their IP and evade the ban within seconds by changing their X-Forwarded-For header to an IP that is not banned (no need for a proxy).

In my opinion, since phpBB handles getting a users IP address in this way...it is a security glitch, as it means that IP's can't be trusted by a phpBB administrator, and bans can be evaded with ease.


------------------------------------------------

Solution

No official response/solution has been recieved from the phpBB group. A possible solution would be to not trust the X-Forwarded-For HTTP header when wishing to obtain a valid IP address by which to reference a user/poster.


In common.php find the following code around line 126:

//
// Obtain and encode users IP
//
if( getenv('HTTP_X_FORWARDED_FOR') != '' )
{
$client_ip = ( !empty($HTTP_SERVER_VARS['REMOTE_ADDR']) ) ? $HTTP_SERVER_VARS['REMOTE_ADDR'] : ( ( !empty($HTTP_ENV_VARS['REMOTE_ADDR']) ) ? $HTTP_ENV_VARS['REMOTE_ADDR'] : $REMOTE_ADDR );

$entries = explode(',', getenv('HTTP_X_FORWARDED_FOR'));
reset($entries);
while (list(, $entry) = each($entries))
{
$entry = trim($entry);
if ( preg_match("/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/", $entry, $ip_list) )
{
$private_ip = array('/^0\./', '/^127\.0\.0\.1/', '/^192\.168\..*/', '/^172\.((1[6-9])|(2[0-9])|(3[0-1]))\..*/', '/^10\..*/', '/^224\..*/', '/^240\..*/');
$found_ip = preg_replace($private_ip, $client_ip, $ip_list[1]);

if ($client_ip != $found_ip)
{
$client_ip = $found_ip;
break;
}
}
}
}
else
{
$client_ip = ( !empty($HTTP_SERVER_VARS['REMOTE_ADDR']) ) ? $HTTP_SERVER_VARS['REMOTE_ADDR'] : ( ( !empty($HTTP_ENV_VARS['REMOTE_ADDR']) ) ? $HTTP_ENV_VARS['REMOTE_ADDR'] : $REMOTE_ADDR );
}
$user_ip = encode_ip($client_ip);


Replace the above code with:


//
// Obtain and encode users IP
//
$client_ip = ( !empty($HTTP_SERVER_VARS['REMOTE_ADDR']) ) ? $HTTP_SERVER_VARS['REMOTE_ADDR'] : ( ( !empty($HTTP_ENV_VARS['REMOTE_ADDR']) ) ? $HTTP_ENV_VARS['REMOTE_ADDR'] : $REMOTE_ADDR );
$user_ip = encode_ip($client_ip);


This will remove the code that tries to obtain the posters IP via X-Forwarded-For.

------------------------------------------------

Credit

Discovery of this issue is credited to Wang & the SRR project group of Ready Response <srr@readyresponse.org>

Shaun Colley
20/04/04, 03:45
--- Ready Response <wang@mod-x.co.uk> wrote: >
>
>
>
################################################## ###################
>
> Advisory Name : phpBB 2.0.8a and lower - IP spoofing
> vulnerability
> Release Date : Apr 18, 2004
> Application : phpBB
> Version : phpBB 2.0.8a and previous versions
> Platform : PHP
> Vendor URL : http://www.phpbb.com/
> Author : Wang / SRR Project Group of Ready Response
> (srr@readyresponse.org)
>

Good work guys ;)

I have put together a patch using the quick-fix Wang &
SRR Project Group suggested, which I hope will make
your job easier when fixing this issue in your board.


Here's the patch file:


---
--- common.orig.php 2003-07-20 11:42:24.000000000
-0400
+++ common.php 2004-04-19 15:45:52.038688056 -0400
@@ -126,32 +126,19 @@
//
// Obtain and encode users IP
//
-if( getenv('HTTP_X_FORWARDED_FOR') != '' )
-{
- $client_ip = (
!empty($HTTP_SERVER_VARS['REMOTE_ADDR']) ) ?
$HTTP_SERVER_VARS['REMOTE_ADDR'] : ( (
!empty($HTTP_ENV_VARS['REMOTE_ADDR']) ) ?
$HTTP_ENV_VARS['REMOTE_ADDR'] : $REMOTE_ADDR );
-
- $entries = explode(',',
getenv('HTTP_X_FORWARDED_FOR'));
- reset($entries);
- while (list(, $entry) = each($entries))
- {
- $entry = trim($entry);
- if (
preg_match("/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/",
$entry, $ip_list) )
- {
- $private_ip = array('/^0\./', '/^127\.0\.0\.1/',
'/^192\.168\..*/',
'/^172\.((1[6-9])|(2[0-9])|(3[0-1]))\..*/',
'/^10\..*/', '/^224\..*/', '/^240\..*/');
- $found_ip = preg_replace($private_ip, $client_ip,
$ip_list[1]);
-
- if ($client_ip != $found_ip)
- {
- $client_ip = $found_ip;
- break;
- }
- }
- }
-}
-else
-{
+// -=-=-=-
+// I have removed the offending code which attempted
to assume a user's IP
+// address based on the contents of the
X-Forwarded-For HTTP header, if one
+// existed. I could've commented the code out,
instead of simply removing it,
+// but that would make this patch bigger than
necessary.
+// This quick workaround will do for now, until phpBB
release a security
+// update.
+//
+// -shaun2k2
+// http://www.nettwerked.co.uk
+// -=-=-=-
+//
$client_ip = (
!empty($HTTP_SERVER_VARS['REMOTE_ADDR']) ) ?
$HTTP_SERVER_VARS['REMOTE_ADDR'] : ( (
!empty($HTTP_ENV_VARS['REMOTE_ADDR']) ) ?
$HTTP_ENV_VARS['REMOTE_ADDR'] : $REMOTE_ADDR );
-}
$user_ip = encode_ip($client_ip);

//
@@ -184,4 +171,4 @@
message_die(GENERAL_MESSAGE, 'Board_disable',
'Information');
}

-?>
\ No newline at end of file
+?>
---


If my mail client obfuscates the patch, the patch is
available here:
<http://www.nettwerked.co.uk/code/phpbb-ipspoof.patch>.

The patch applies cleanly to phpBB2 2.0.8, 2.0.8a and
perhaps earlier versions.

Hope this helps is some way.



Thank you for your time.
Shaun.





__________________________________________________ __________
Yahoo! Messenger - Communicate instantly..."Ping"
your friends today! Download Messenger Now
http://uk.messenger.yahoo.com/download/index.html

3APA3A
21/04/04, 02:45
Dear Ready Response,

--Monday, April 19, 2004, 4:01:29 AM, you wrote to bugtraq@securityfocus.com:

RR> the users IP address in the common.php script. This issue is caused
RR> by blind trust of the X-Forwarded-For HTTP header. A remote attacker

This issue is very common for different BBs (for example Iconboard has
same problem), in addition to IP spoofing it's usually possible to cause
crossite scripting by inserting script into forgery X-Forwarded-For
header.

--
~/ZARAZA
Íî âåäü êîìó óãîäíî ìîãóò ïðèéòè â ãîëîâó ÿéöà, ïÿòêè è åïèñêîïû. (Ëåì)

Xin LI
21/04/04, 20:35
--T4sUOijqQbZv57TR
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Tue, Apr 20, 2004 at 04:15:48PM +0400, 3APA3A wrote:
> --Monday, April 19, 2004, 4:01:29 AM, you wrote to bugtraq@securityfocus.=
com:
>=20
> RR> the users IP address in the common.php script. This issue is caused
> RR> by blind trust of the X-Forwarded-For HTTP header. A remote attacker
>=20
> This issue is very common for different BBs (for example Iconboard has
> same problem), in addition to IP spoofing it's usually possible to cause
> crossite scripting by inserting script into forgery X-Forwarded-For
> header.
>=20
> --=20

The situation turns out to be more serious because phpBB (up to and
including 2.0.8a) is affected by another potential resource exhaustion
attack, by exploiting the limitation on the sessions table.

I have a preliminary patch as followed. It was sent to security@phpbb.com
a month ago and I received no response from them (also, the description
of the vulnerablity, of course):

Index: includes/sessions.php
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D
RCS file: /cvsroot/phpbb/phpBB2/includes/Attic/sessions.php,v
retrieving revision 1.58.2.10
diff -u -r1.58.2.10 sessions.php
--- includes/sessions.php 5 Apr 2003 12:04:33 -0000 1.58.2.10
+++ includes/sessions.php 17 Apr 2004 07:48:20 -0000
@@ -147,7 +147,7 @@
$sql =3D "INSERT INTO " . SESSIONS_TABLE . "
(session_id, session_user_id, session_start, session_time, session_ip, =
session_page, session_logged_in)
VALUES ('$session_id', $user_id, $current_time, $current_time, '$user_i=
p', $page_id, $login)";
- if ( !$db->sql_query($sql) )
+ if ( $user_id !=3D ANONYMOUS && !$db->sql_query($sql) )
{
message_die(CRITICAL_ERROR, 'Error creating new session', '', __LINE__,=
__FILE__, $sql);
}
@@ -380,4 +380,4 @@
return $url;
}
=20
-?>
\ No newline at end of file
+?>

The concept here is simple. We do not really need to store sessions for
anonymous users.

Remote attackers can attack a forum without Wang's patch by exploiting
this vulnerablity and result in a Denial of Service attack by fooling
the forum to store many anonymous 'visitors' in sessions table.

This vulnerablity does not affect the development version of phpBB.

--=20
Xin LI <delphij frontfree net> http://www.delphij.net/
See complete headers for GPG key and other information.


--T4sUOijqQbZv57TR
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (FreeBSD)

iD8DBQFAhcofOfuToMruuMARAkuxAJsEpYiauE5KU7I/tPuXm9nhjb2N2gCeKJ1O
O+9KfC/rF3Ct2TiZrv9n9Ac=
=QPEN
-----END PGP SIGNATURE-----

--T4sUOijqQbZv57TR--

BlueRaven
29/04/04, 03:35
On Wed, Apr 21, 2004 at 09:10:55AM +0800, Xin LI wrote:

Hi Xin, I think there's an error in your patch:

> - if ( !$db->sql_query($sql) )
> + if ( $user_id != ANONYMOUS && !$db->sql_query($sql) )

This does NOT prevent execution of the query, only effects output of the
message:

> {
> message_die(CRITICAL_ERROR, 'Error creating new session', '', __LINE__, __FILE__, $sql);
> }

I think it should read as follows:

if ( $user_id != ANONYMOUS ) {
if ( !$db->sql_query($sql) {
message_die(CRITICAL_ERROR, 'Error creating new session', '', __LINE__, __FILE__, $sql);
}
}

I'm not great PHP programmer, though, so please correct me if I'm wrong.
Cheers! :-)

--
#include <best/regards.h>

BlueRaven

Did you know that if you play a Windows 2000 CD backwards, you will hear
the voice of Satan? That's nothing!
If you play it forward, it'll install Windows 2000.

Xin LI
29/04/04, 20:55
--OgqxwSJOaUobr8KG
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Wed, Apr 28, 2004 at 11:03:26AM +0200, BlueRaven wrote:
> On Wed, Apr 21, 2004 at 09:10:55AM +0800, Xin LI wrote:
>=20
> Hi Xin, I think there's an error in your patch:
>=20
> > - if ( !$db->sql_query($sql) )
> > + if ( $user_id !=3D ANONYMOUS && !$db->sql_query($sql) )
>=20
> This does NOT prevent execution of the query, only effects output of the
> message:
>=20
> > {
> > message_die(CRITICAL_ERROR, 'Error creating new session', '', __LIN=
E__, __FILE__, $sql);
> > }
>=20
> I think it should read as follows:
>=20
> if ( $user_id !=3D ANONYMOUS ) {
> if ( !$db->sql_query($sql) {
> message_die(CRITICAL_ERROR, 'Error creating new sessio=
n', '', __LINE__, __FILE__, $sql);
> }
> }
>=20
> I'm not great PHP programmer, though, so please correct me if I'm wrong.

Well... I don't think so. When a expression evulates to false before a
&& operator, the rest of things which are after && should be "short-
circuit" instead of being evaluated. This is default behavior in most
programming languages, and I believe that this is the behavior of PHP,
too.

Let me proof my assumption with the following code:

----------snip-------------
<?
$i =3D false;

function f()
{
echo "f() called";
return 1;
}

echo "before f()<br />";

f();
echo "<br />after f()";
echo "<br />";

if( ($i) && (f() > 0)) {
// do nothing
}

echo "end";
?>
----------snip-------------

And I get the following output:

----------snip-------------
before f()
f() called
after f()
end
----------snip-------------

As you can see, f() is called only once by explicitly calling it.
The second call, because $i =3D=3D false, is short-circuited and not
evaluated.

I have runned the patch on one of servers I maintains for some
months and it has been proven that the anonymous session denial
of service problem has been addressed (at least worked around).

To complain phpBB.com developing team:

Not sure why phpBB.com did not respond to my submission after I
privately submit this to them nearly two months ago and this
BugTraq post. They respond me nothing - no admissions, no
rejections, I am re-thinking about whether to handle phpBB problems
I found... Submitting to security@phpbb.com as they desired seems
to be inefficient. Maybe they don't consider the session resource
exhaustion as a problem, but they did not replyed me, I don't
think that's a good practise.

Cheers,
--=20
Xin LI <delphij frontfree net> http://www.delphij.net/
See complete headers for GPG key and other information.


--OgqxwSJOaUobr8KG
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (FreeBSD)

iD8DBQFAkGWCOfuToMruuMARApwdAJ9ePCXMyNtKB7l+2GXRrF F3Bj9q5gCePB5E
NcFLr8I2D3jGx4KDRn0r7N8=
=DI9w
-----END PGP SIGNATURE-----

--OgqxwSJOaUobr8KG--