What's a good forum script that's actually secure?

Discussion in 'Webmastering & Programming' started by Red Squirrel, Aug 29, 2014.

  1. Red Squirrel

    Red Squirrel [H]ardForum Junkie

    Messages:
    9,211
    Joined:
    Nov 29, 2009
    I was going through my server logs and saw some pretty scary stuff, one of my forums running phpbb2 has some SERIOUS flaws. A specially crafted URL was able to pull up all the information from the database on a specified user (in my case the admin account). I don't know exactly how it's even coded in such a way that it allows this, but basically it produces a print_r export of the specified user's database row.

    I am looking at remaking all my forums into one single forum and I was looking into phpbb3, but I'm starting to wonder if I should perhaps look in other directions. It seems there's not that many choices these days in terms of free forum systems. There's phpbb, SMF (not a huge fan, I HATE their PM layout for one) and there's YABB. Anything else I may be missing?

    Since I'll be modding this I can't be constantly updating it so I need something that is already secure out of the box.

    Also can someone explain to me how this exploit even works, here is a sample URL, I changed some info because this is actually an exploit digging right into my database:

    Code:
    http://www.domain.com/forum/profile.php?mode=register&agreed=true+[PLM=0][R]+GET+http://www.domain.com/forum/profile.php?mode=register&agreed=true+[0,22775,73872]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24840,72900]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24786,73546]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24790,73924]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24787,71358]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24792,68993]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24810,71620]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24780,72478]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24780,73294]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24794,70450]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24788,72995]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24798,74102]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24770,74439]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,25043,72787]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24778,73611]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24784,74963]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24819,71517]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24783,73370]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24788,73592]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24794,72943]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,25024,72774]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24798,73530]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24791,69749]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,24803,73392]+-%3E+[R]+POST+http://www.domain.com/forum/profile.php+[0,0,27325]+-%3E+[N]+GET+http://www.domain.com/forum/viewtopic.php?t=6478+[12329,0,42900]
    
    Somehow that URL pointed towards a phpbb forum will print out all the info for the admin account. I'm not sure where in the URL they specified the userID but I see lot of numbers and stuff guessing it has to do with that.

    What exactly is all the square bracket stuff going on and the plus signs? I've never seen a URL like this before nor know how php would interpret or what it does with it.
     
  2. Grentz

    Grentz [H]ard as it Gets

    Messages:
    17,118
    Joined:
    May 5, 2006
    vBulletin and SMF, possibly buddy press.

    Never been a fan of phpbb...
     
  3. Red Squirrel

    Red Squirrel [H]ardForum Junkie

    Messages:
    9,211
    Joined:
    Nov 29, 2009
    vB is nice, but don't want to pay anything, especially not what they're asking. :eek: Never head of buddy press though, I'll have to give it a try, and give SMF a second go as well.

    Do you know how that URL hack works? This is new to me. It looks like some form of injection but really not sure hot it works. What does the [PLM=0][R] stuff do? I also see a GET in there, is this actually exploiting the web server itself?
     
  4. Grentz

    Grentz [H]ard as it Gets

    Messages:
    17,118
    Joined:
    May 5, 2006
    I don't know for sure, but every site I have ever setup with phpbb in the last 10yrs, no matter how many security mods and fixes, has eventually been compromised.

    SMF I have never had an issue with.
     
  5. x3sphere

    x3sphere 2[H]4U

    Messages:
    2,626
    Joined:
    Dec 8, 2007
    What about Xenforo? Not free, but reasonably priced I think. It's made by former developers of vB and has a very good track record as far as security goes.

    vB is complete trash these days if you ask me. Went downhill after the jump to 4.0, which is around the time the old devs left and created XenForo a few years later. There's a reason this forum still runs on 3.8 ;)
     
  6. Red Squirrel

    Red Squirrel [H]ardForum Junkie

    Messages:
    9,211
    Joined:
    Nov 29, 2009
    Hmm I suppose it's worth looking into, never liked the idea of paying but really 150 is not THAT much provided there's not some weird license agreement issues that would limit what I can do with it such as have a dev/test/prod environments (3 installs). I'll have to look into it.

    I'm currently playing around with SMF. The thing I did not like about it is the PM interface, ti's just hard to follow because it just dumps all the PMs together instead of the typical setup where you see just the titles and click to view individual ones, but that is actually changeable in the user settings, so I can easily just change those defaults. PhpBB 3.0 is really nice too though but not sure what their security track record is for that particular version, everything I read in general about phpbb says it's a hacker magnet.

    I'm still trying to figure out how that URL hack works though, because I want to ensure that the code I write myself can't be exploited with that type of technique.

    Also I may end up having to fix that exploit on my phpbb 2 board because that board is an archive so I may want to keep it as is. Though I may also be able to do some kind of tweak to make the database read only and the file structure read only so that any kind of hack can't change anything anyway.
     
  7. StoleMyOwnCar

    StoleMyOwnCar 2[H]4U

    Messages:
    2,151
    Joined:
    Sep 30, 2013
    Well first thing's first. What's the source code of profile.php?

    Second of all, actually try passing that URL into it yourself and try putting log points at various steps within the script. For instance, do a print_r of the $_GET with that passed in. That's a start.

    Finally there's a lot of stuff going on in that. For instance I think + signs in the URL get translated to spaces. All of the square bracket things become arrays. Though I'm not even sure how that works, because if they're after what's considered a space, they would be... anonymous arrays?

    Yeah, you need to do a print_r of the $_GET with that passed in. I suggest something like exec("echo \"". print_r($_GET) ."\" >> LOGFILEOFCHOICE.LOG") and then show us what happens. It's hard getting to the bottom of this just staring at a URL, unless someone in here is very knowledgeable in URL encoding and decoding standards for PHP... but again the script source can affect that anyway.
     
  8. Red Squirrel

    Red Squirrel [H]ardForum Junkie

    Messages:
    9,211
    Joined:
    Nov 29, 2009
    This is profile.php:

    Yes it's an old forum script but that's beside the point, I want to learn how this type of URL manipulation exploit works so I can write code that can't be exploited by it when I code my own stuff or fix existing stuff.

    Code:
    <?php
    /***************************************************************************
     *                                profile.php
     *                            -------------------
     *   begin                : Saturday, Feb 13, 2001
     *   copyright            : (C) 2001 The phpBB Group
     *   email                : support@phpbb.com
     *
     *   $Id: profile.php,v 1.193.2.7 2006/04/09 16:17:27 grahamje Exp $
     *
     *
     ***************************************************************************/
    
    /***************************************************************************
     *
     *   This program is free software; you can redistribute it and/or modify
     *   it under the terms of the GNU General Public License as published by
     *   the Free Software Foundation; either version 2 of the License, or
     *   (at your option) any later version.
     *
     ***************************************************************************/
    
     
     echo("GET:".print_r($_GET)."<br><br>POST:".print_r($_POST));//TEST CODE
     
    define('IN_PHPBB', true);
    $phpbb_root_path = './';
    include($phpbb_root_path . 'extension.inc');
    include($phpbb_root_path . 'common.'.$phpEx);
    
    //
    // Start session management
    //
    $userdata = session_pagestart($user_ip, PAGE_PROFILE);
    init_userprefs($userdata);
    
    //
    // End session management
    //
    
    // session id check
    if (!empty($HTTP_POST_VARS['sid']) || !empty($HTTP_GET_VARS['sid']))
    {
    	$sid = (!empty($HTTP_POST_VARS['sid'])) ? $HTTP_POST_VARS['sid'] : $HTTP_GET_VARS['sid'];
    }
    else
    {
    	$sid = '';
    }
    
    //
    // Set default email variables
    //
    $script_name = preg_replace('/^\/?(.*?)\/?$/', '\1', trim($board_config['script_path']));
    $script_name = ( $script_name != '' ) ? $script_name . '/profile.'.$phpEx : 'profile.'.$phpEx;
    $server_name = trim($board_config['server_name']);
    $server_protocol = ( $board_config['cookie_secure'] ) ? 'https://' : 'http://';
    $server_port = ( $board_config['server_port'] <> 80 ) ? ':' . trim($board_config['server_port']) . '/' : '/';
    
    $server_url = $server_protocol . $server_name . $server_port . $script_name;
    
    // -----------------------
    // Page specific functions
    //
    function gen_rand_string($hash)
    {
    	$rand_str = dss_rand();
    
    	return ( $hash ) ? md5($rand_str) : substr($rand_str, 0, 8);
    }
    //
    // End page specific functions
    // ---------------------------
    
    //
    // Start of program proper
    //
    if ( isset($HTTP_GET_VARS['mode']) || isset($HTTP_POST_VARS['mode']) )
    {
    	$mode = ( isset($HTTP_GET_VARS['mode']) ) ? $HTTP_GET_VARS['mode'] : $HTTP_POST_VARS['mode'];
    	$mode = htmlspecialchars($mode);
    
    	if ( $mode == 'viewprofile' )
    	{
    		include($phpbb_root_path . 'includes/usercp_viewprofile.'.$phpEx);
    		exit;
    	}
    	else if ( $mode == 'editprofile' || $mode == 'register' )
    	{
    		if ( !$userdata['session_logged_in'] && $mode == 'editprofile' )
    		{
    			redirect(append_sid("login.$phpEx?redirect=profile.$phpEx&mode=editprofile", true));
    		}
    
    		include($phpbb_root_path . 'includes/usercp_register.'.$phpEx);
    		exit;
    	}
    	else if ( $mode == 'confirm' )
    	{
    		// Visual Confirmation
    		if ( $userdata['session_logged_in'] )
    		{
    			exit;
    		}
    
    		include($phpbb_root_path . 'includes/usercp_confirm.'.$phpEx);
    		exit;
    	}
    	else if ( $mode == 'sendpassword' )
    	{
    		include($phpbb_root_path . 'includes/usercp_sendpasswd.'.$phpEx);
    		exit;
    	}
    	else if ( $mode == 'activate' )
    	{
    		include($phpbb_root_path . 'includes/usercp_activate.'.$phpEx);
    		exit;
    	}
    	else if ( $mode == 'email' )
    	{
    		include($phpbb_root_path . 'includes/usercp_email.'.$phpEx);
    		exit;
    	}
    }
    
    
    
    
    
    redirect(append_sid("index.$phpEx", true));
    
    ?>

    And here is the output:

    Code:
    Array ( [mode] => register [agreed] => true [0,22775,73872] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24840,72900] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24786,73546] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24790,73924] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24787,71358] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24792,68993] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24810,71620] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24780,72478] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24780,73294] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24794,70450] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24788,72995] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24798,74102] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24770,74439] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,25043,72787] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24778,73611] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24784,74963] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24819,71517] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24783,73370] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24788,73592] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24794,72943] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,25024,72774] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24798,73530] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24791,69749] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,24803,73392] -> [R] POST http://uovalor.com.d.appdev.loc/forum/profile.php [0,0,27325] -> [N] GET http://uovalor.com.d.appdev.loc/forum/viewtopic.php?t=6478 [12329,0,42900] ) GET:1
    
    POST:1 
    
    What I'm confused about is how is this putting variables into $_GET without actually using a query string in the url and how is it performing a HTTP POST via URL and not an actual POST request to the server?


    Oh and another thing, the original print_r output that the exploit produced was actually triggering an old debug point and that is something I had added myself and since removed. So not actually sure what this exploit is aiming to do or if it even did exploit anything after all, but it's obviously doing something if it was able to get to that point in the code.
     
    Last edited: Sep 4, 2014
  9. Tawnos

    Tawnos 2[H]4U

    Messages:
    3,807
    Joined:
    Sep 9, 2001

    It _is_ putting stuff into $_GET - everything following the first ? becomes GET variables. There are two of them, "mode=register" and "agreed=true [PLM=0]... " (the plus signs represent spaces, the %3E represents '>').

    I'll take a look at it in a bit, probably a known exploit (this is phpBB 2.0.21?), but it would be fun to read through it and figure it out.
     
  10. Red Squirrel

    Red Squirrel [H]ardForum Junkie

    Messages:
    9,211
    Joined:
    Nov 29, 2009
    What is the significance of adding stuff after a boolean value though, it's either true, or it's false no? Unless the code is extremly badly written where it's taking that literal value and trusting it. I checked and it seems to just use isset to see if it's been set or not so it's value should not be significant.

    Though is there any reason to use $HTTP_GET_VARS over $_GET? That's what they use in their code.

    Or are the -> and [] andn spaces doing something weird and php actually does not take it as literal text string and does something weird with it?
     
  11. Tawnos

    Tawnos 2[H]4U

    Messages:
    3,807
    Joined:
    Sep 9, 2001
    If you look at the files, you'll see that $HTTP_GET_VARS is an alias for $_GET:

    Code:
    common.php:
    	$HTTP_GET_VARS = $_GET;
    
    In php, -> is dereference, and [] is an array. Not sure the point of the [R] and such, unless it is an attack that actually goes after apache's mod_rewrite or similar.
     
  12. Red Squirrel

    Red Squirrel [H]ardForum Junkie

    Messages:
    9,211
    Joined:
    Nov 29, 2009
    Only thing I don't understand though, shouldn't that string just be treated as a regular string anyway? Or is there an exploit in php where it starts to actually parse stuff in it instead of treating it literally?
     
  13. Red Squirrel

    Red Squirrel [H]ardForum Junkie

    Messages:
    9,211
    Joined:
    Nov 29, 2009
    Back to the original topic, SMF's permission system is GARBAGE. It's way too complicated and restrictive, and it's hard to know what's going on,there's no easy way to know who has permission to what, it's just a jumbled up mess and have to jump through all sorts of hoops to set permissions and nothing is in one spot or easy to overview. What a mess.

    I may have to go back to phpbb just for this reason alone. Once I can figure out how these type of URL exploits work I'll just have to audit the whole code and fix them.
     
  14. StoleMyOwnCar

    StoleMyOwnCar 2[H]4U

    Messages:
    2,151
    Joined:
    Sep 30, 2013
    Well how do you even know that the hackers actually did get in? Do you have some kind of tracking mechanism in place?

    Or what, you tried that URL and then you saw the print_r yourself?

    Anyway this is a bit of a shot in the dark, but maybe see what happens when you start shortening the URL. It has a pretty repetitive pattern, so maybe try taking off a chunk at a time and see what results it's outputting. You might get it down to a pattern that shows what's going on.
     
  15. Red Squirrel

    Red Squirrel [H]ardForum Junkie

    Messages:
    9,211
    Joined:
    Nov 29, 2009
    Well it was a false alarm as that print_r was actually some debug code I had added at one point and forgot to remove and it only showed the details on the currently logged in user. Though obviously that url is trying to do something, so I'm still wondering how it works and whether or not php is treating the stuff as plain text or if it somehow interprets it.
     
  16. Uncle Humjaba

    Uncle Humjaba Limp Gawd

    Messages:
    408
    Joined:
    May 6, 2006
    mybb is another message board to consider. we use it for our car forum and haven't had any problems with it in the last 4 years or so. pretty active community, nice features. we had some problems with human spam but after implementing some creative registration requirements ("what car is in our banner?" those have mostly been solved.
     
  17. Thuleman

    Thuleman [H]ardness Supreme

    Messages:
    5,834
    Joined:
    Apr 13, 2004
    I am running IP.Board and if I had to launch a new forum today I'd buy IP.Board again.

    I do have a Xenforo license and it's just too meh at this point. I wouldn't put Xenforo into production. Of course the XF fanbois will point out that there are forums with millions of posts that run on XF, but you have to consider that those forums have dedicated staff that can monkey with it all day and make it fit their every need.

    If you are just one guy who has to have something running with decent mod support out of the box then XF is not the right choice at this time.
     
  18. Tawnos

    Tawnos 2[H]4U

    Messages:
    3,807
    Joined:
    Sep 9, 2001
    It's showing you stuff from the database. Of course PHP is executing it - you were directly printing unsanitized variables. At this point, I'm guessing it's spam that is looking for some old exploit, not sure what. The particular string format seems to appear a bit around the net. E.g. the spam on this message board: http://www.womanicer.nl/page8.php?category=1&post=1&messagepage=33&messagePage=44
     
  19. Red Squirrel

    Red Squirrel [H]ardForum Junkie

    Messages:
    9,211
    Joined:
    Nov 29, 2009
    So php will actually execute variables and not just treat as text? So could somebody change any internal variable value through the url using special strings? Like something like "?[special percent string]$internalvar=value" so php will actually execute that and not just treat it as plain text? This sounds like a serious php flaw if yes.

    It may be possible that particular string was trying to bypass the captcha too because I used to get TONS of spam on that forum till I put 3 separate captchas just to throw off bots. Now registrations are closed altogether as it's just an archive forum.

    After lot of aggravation I figured out the SMF permission system, it's really weirdly designed but come to think of it it's not like I'll be in there all the time so once I have it working how I want I probably wont need to go in that often. So think I'll probably end up sticking with SMF.
     
  20. Tawnos

    Tawnos 2[H]4U

    Messages:
    3,807
    Joined:
    Sep 9, 2001
    I'm guessing it's your code doing the expansion (not execution) of variables. If you were calling "print" somewhere, it will expand the variables in the string. For example:

    Code:
    $foo = "test";
    $testGet = array("test" => urldecode("true+$foo"));
    print(print_r($testGet));
    
    will produce

    Array
    (
    [test] => true test
    )
     
  21. talk2troy

    talk2troy [H]ardness Supreme

    Messages:
    5,440
    Joined:
    Jun 10, 2004
    I'm looking at myBB right now, but smf v2 looks much better than the last time I used it and phpBB was a hack magnet...

    I'd like to hear more about IP.board please!
     
  22. Red Squirrel

    Red Squirrel [H]ardForum Junkie

    Messages:
    9,211
    Joined:
    Nov 29, 2009
    I ended up sticking with SMF. Got it mostly setup how I want short of making a custom skin, now I just have to merge my other forums into it and make sure the old URLs will still work. Basically merging a bunch of forums I manage into one for easier maintenance. Should be a nice fun project.
     
  23. zerodamage

    zerodamage Limp Gawd

    Messages:
    171
    Joined:
    May 18, 2007
    Good call I think. I've always liked SMF myself and the easy updating from within the admin panel. I always grabbed a free SSL cert from StartSSL.com and used them on all of my forums too. You can use the repair_settings.php file to correct URL related issues after applying the SSL cert then remove it. Do it at the first stages or you can compromise your forums with that repair settings file.
     
  24. Red Squirrel

    Red Squirrel [H]ardForum Junkie

    Messages:
    9,211
    Joined:
    Nov 29, 2009
    Good to know there are free SSL certs. I'll have to check that out. I've never really bothered to use SSL for my forums but been thinking it may be a good idea.