MyBB Board Hacked ... Again

Discussion in 'Security' started by cscott5288, May 20, 2009.

  1. #1
    Hello, I just recently purchased a myBB forum and I have had incessant problems with an ex-administrator who has been able to unban himself and set himself to administrator, despite the fact that he had already been IP banned.

    MyBB version: 1.4.6, MySQL 5.0.67

    I suspect he created tables or something ... but I just don't know where to look! I am not fluent in PHP or MySQL, so I would really appreciate some advice.
     
    cscott5288, May 20, 2009 IP
  2. vagrant

    vagrant Peon

    Messages:
    2,284
    Likes Received:
    181
    Best Answers:
    0
    Trophy Points:
    0
    #2
    doh !!

    myBB if free... delete all admin accounts that are not you.
    change mysql password as well.

    Change YOUR password and move to a different web host as well to be safe.
     
    vagrant, May 20, 2009 IP
  3. cscott5288

    cscott5288 Active Member

    Messages:
    912
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    60
    #3
    The following plugin was installed by the user:

    <?php
    /**
     * FastRep 1.0
     *
     * Copyright © 2009 iarspider
     * Website: none
     * License: GPL v3
     *
     */
    
    // Disallow direct access to this file for security reasons
    if(!defined("IN_MYBB"))
    {
    	die("Direct initialization of this file is not allowed.<br /><br />Please make sure IN_MYBB is defined.");
    }
    
    require_once ("inc/functions.php");
    
    $plugins->add_hook("xmlhttp", "fastrep_xmlhttp");
    $plugins->add_hook("postbit", "fastrep_postbit");
    
    function fastrep_info()
    {
    	global $lang;
    	$lang->load("fastrep", false, true);
    
    	/**
    	 * Array of information about the plugin.
    	 * name: The name of the plugin
    	 * description: Description of what the plugin does
    	 * website: The website the plugin is maintained at (Optional)
    	 * author: The name of the author of the plugin
    	 * authorsite: The URL to the website of the author (Optional)
    	 * version: The version number of the plugin
    	 * guid: Unique ID issued by the MyBB Mods site for version checking
    	 * compatibility: A CSV list of MyBB versions supported. Ex, "121,123", "12*". Wildcards supported.
    	 */
    	return array(
    		"name"			=> "Fast way to change reputation",
    		"description"	=> $lang->fastrep_plugin_desc,
    		"website"		=> "",
    		"author"		=> "iarspider",
    		"authorsite"	=> "",
    		"version"		=> "1.3.1",
    		"guid" 			=> "",
    		"compatibility" => "*"
    	);
    }
    
    function fastrep_find_replace_templatesets_re($title, $find, $replace, $autocreate=1, $limit=-1)
    {
    	global $db;
    	if($autocreate != 0)
    	{
    		$query = $db->simple_select("templates", "*", "title='$title' AND sid='-2'");
    		$master = $db->fetch_array($query);
    		$oldmaster = $master['template'];
    		$master['template'] = preg_replace($find, $replace, $master['template'], $limit);
    		if($oldmaster == $master['template'])
    		{
    			return false;
    		}
    		$master['template'] = $db->escape_string($master['template']);
    	}
    	$query = $db->query("
    		SELECT s.sid, t.template, t.tid
    		FROM ".TABLE_PREFIX."templatesets s
    		LEFT JOIN ".TABLE_PREFIX."templates t ON (t.title='$title' AND t.sid=s.sid)
    	");
    	while($template = $db->fetch_array($query))
    	{
    		if($template['template']) // Custom template exists for this group
    		{
    			if(!preg_match($find, $template['template']))
    			{
    				return false;
    			}
    			$newtemplate = preg_replace($find, $replace, $template['template'], $limit);
    			$template['template'] = $newtemplate;
    			$update[] = $template;
    		}
    		elseif($autocreate != 0) // No template exists, create it based off master
    		{
    			$newtemp = array(
    				"title" => $title,
    				"template" => $master['template'],
    				"sid" => $template['sid']
    			);
    			$db->insert_query("templates", $newtemp);
    		}
    	}
    
    	if(is_array($update))
    	{
    		foreach($update as $template)
    		{
    			$updatetemp = array("template" => $db->escape_string($template['template']), "dateline" => TIME_NOW);
    			$db->update_query("templates", $updatetemp, "tid='".$template['tid']."'");
    		}
    	}
    	return true;
    }
    
    function fastrep_find_replace_templatesets($title, $find, $replace, $autocreate=1)
    {
    	global $db;
    	if($autocreate != 0)
    	{
    		$query = $db->simple_select("templates", "*", "title='$title' AND sid='-2'");
    		$master = $db->fetch_array($query);
    		$oldmaster = $master['template'];
    		$master['template'] = str_replace($find, $replace, $master['template']);
    		if($oldmaster == $master['template'])
    		{
    			return false;
    		}
    		$master['template'] = $db->escape_string($master['template']);
    	}
    	$query = $db->query("
    		SELECT s.sid, t.template, t.tid
    		FROM ".TABLE_PREFIX."templatesets s
    		LEFT JOIN ".TABLE_PREFIX."templates t ON (t.title='$title' AND t.sid=s.sid)
    	");
    	while($template = $db->fetch_array($query))
    	{
    		if($template['template']) // Custom template exists for this group
    		{
    			if(!strpos($template['template'], $find))
    			{
    				return false;
    			}
    			$newtemplate = str_replace($find, $replace, $template['template']);
    			$template['template'] = $newtemplate;
    			$update[] = $template;
    		}
    		elseif($autocreate != 0) // No template exists, create it based off master
    		{
    			$newtemp = array(
    				"title" => $title,
    				"template" => $master['template'],
    				"sid" => $template['sid']
    			);
    			$db->insert_query("templates", $newtemp);
    		}
    	}
    
    	if(is_array($update))
    	{
    		foreach($update as $template)
    		{
    			$updatetemp = array("template" => $db->escape_string($template['template']), "dateline" => TIME_NOW);
    			$db->update_query("templates", $updatetemp, "tid='".$template['tid']."'");
    		}
    	}
    	return true;
    }
    
    function fastrep_install()
    {
    	global $db, $lang;
    
    	$db->query("ALTER TABLE `".TABLE_PREFIX."reputation` ADD `pid` INT( 10 ) DEFAULT '-1' NOT NULL AFTER `adduid` ");
    
    	$lang->load("fastrep", false, true);
    
    	$settings_gid = $db->insert_query('settinggroups', array(
    		'name' => 'fastrep',
    		'title' => $lang->fastrep_settings,
    		'disporder' => 51,
    	));
    
    	$db->insert_query('settings', array(
    		'name' => 'fastrep_negimg',
    		'optionscode' => 'text',
    		'value' => './images/icons/thumbsdown.gif',
    		'title' => $lang->fastrep_settings_negimg,
    		//'description' => $lang->fastrep_settings_negimg_desc,
    		'disporder' => 1,
    		'gid' => $settings_gid
    	));
    
    	$db->insert_query('settings', array(
    		'name' => 'fastrep_posimg',
    		'optionscode' => 'text',
    		'value' => './images/icons/thumbsup.gif',
    		'title' => $lang->fastrep_settings_posimg,
    		//'description' => $lang->fastrep_settings_posimg_desc,
    		'disporder' => 2,
    		'gid' => $settings_gid
    	));
    
    	$db->insert_query('settings', array(
    		'name' => 'fastrep_max',
    		'optionscode' => 'text',
    		'value' => 5,
    		'title' => $lang->fastrep_settings_maxdispvote,
    		'description' => $lang->fastrep_settings_maxdispvote_desc,
    		'disporder' => 3,
    		'gid' => $settings_gid
    	));
    
    	rebuildsettings();
    }
    
    function fastrep_activate()
    {
    	fastrep_find_replace_templatesets('postbit_reputation', '{$lang->postbit_reputation}', '{$lang->postbit_reputation} <img alt="-" title="-" onclick="javascript:negrep({$post[\'pid\']})" src="{$mybb->settings[\'fastrep_negimg\']}"/> <span id="postrep_{$post[\'pid\']}">', 1);
    	fastrep_find_replace_templatesets('postbit_reputation', '{$post[\'userreputation\']}', '{$post[\'userreputation\']}</span> <img alt="+" title="+" onclick="posrep({$post[\'pid\']})" src="{$mybb->settings[\'fastrep_posimg\']}"/>', 1);
    	fastrep_find_replace_templatesets('headerinclude', '{$stylesheets}', '<script type="text/javascript" src="{$mybb->settings[\'bburl\']}/jscripts/fastrep.js"></script>'."\n".'{$stylesheets}', 1);
    //	fastrep_find_replace_templatesets("postbit", '{$post[\'button_find\']}', '{$post[\'button_find\']}{$post[\'fr_votes\']}', 1);
    //	fastrep_find_replace_templatesets("postbit_classic", '{$post[\'iplogged\']}', '{$post[\'iplogged\']}{$post[\'fr_votes\']}', 1);
    //	fastrep_find_replace_templatesets("postbit", '{$post[\'iplogged\']}', '{$post[\'iplogged\']}{$post[\'fr_votes\']}', 1);
    	fastrep_find_replace_templatesets_re("postbit", '#[\t]*\<tr\>[\n\r\t]*\<td class\="trow1 post_buttons#', '{$post[\'fr_votes\']}'."\n".'$0', 1, 1);
    	fastrep_find_replace_templatesets_re("postbit_classic", '#[\t]*\<tr\>[\t\n\r]*\<td class\="\{\$altbg\}" style\="white-space\: nowrap; text-align\: center; vertical-align\: middle;"\>\<span class\="smalltext"\>\{\$post\[\'postdate\'\]\} \{\$post\[\'posttime\'\]\}\</span\>\</td\>#', '{$post[\'fr_votes_c\']}'."\n".'$0', 1, 1);
    }
    
    function fastrep_deactivate()
    {
    	fastrep_find_replace_templatesets('postbit_reputation', '{$lang->postbit_reputation} <img alt="-" title="-" onclick="javascript:negrep({$post[\'pid\']})" src="{$mybb->settings[\'fastrep_negimg\']}"/> <span id="postrep_{$post[\'pid\']}">', '{$lang->postbit_reputation} ', 0);
    	fastrep_find_replace_templatesets('postbit_reputation', '{$post[\'userreputation\']}</span> <img alt="+" title="+" onclick="posrep({$post[\'pid\']})" src="{$mybb->settings[\'fastrep_posimg\']}"/>', '{$post[\'userreputation\']}', 0);
    	fastrep_find_replace_templatesets('headerinclude', '<script type="text/javascript" src="{$mybb->settings[\'bburl\']}/jscripts/fastrep.js"></script>'."\n", '', 0);
    	fastrep_find_replace_templatesets("postbit_classic", '{$post[\'fr_votes_c\']}'."\n", '', 0);
    	fastrep_find_replace_templatesets("postbit", '{$post[\'fr_votes\']}'."\n", '', 0);
    }
    
    function fastrep_uninstall()
    {
    	global $db;
    
    	$db->delete_query("settings", "name IN('fastrep_negimg', 'fastrep_posimg', 'fastrep_max')");
    	$db->delete_query("settinggroups", "name = 'fastrep'");
    
    	$db->query("ALTER TABLE `mybb_reputation` DROP `pid`");
    	rebuildsettings();
    }
    
    function fastrep_is_installed()
    {
    	global $db;
    
    	$query = $db->simple_select("settings", "name", "name='fastrep_max'", array('limit' => 1));
    	if($db->fetch_field($query, "name"))
    	{
    		return true;
    	}
    
    	return false;
    }
    
    function fastrep_xmlhttp() //Heavily based on reputation.php
    {
    	global $mybb, $pid, $db, $lang;
    	$lang->load("fastrep", false, true);
    
    	if($mybb->input['action'] == "negrep")
    	{
    		$pid = intval($_GET['pid']);
    
    		$check_query = $db->simple_select("posts", "uid, tid", "pid='".$pid."'");
    		$check = $db->num_rows($check_query);
    		if($check == 0) //no such post
    		{
    			return;
    		}
    
    		$uid = $mybb->user['uid'];
    		$user_permissions = user_permissions($uid);
    		$row = $db->fetch_array($check_query);
    
    		//Check if:
    		//a) This is self-voting
    		//b) Vote is cast by a guest
    		//c) Poster can't give reputation
    		//d) Poster can't use reputation system
    		if (($uid == $row['uid']) ||  ($uid == 0) || ($mybb->usergroup['cangivereputations'] != 1) || ($user_permissions['usereputationsystem'] != 1))
    		{
    			$currep = $db->simple_select("users", "reputation", "uid='".$row['uid']."'");
    			print get_reputation($db->fetch_field($currep, 'reputation'), $mybb->user['uid']);
    			return;
    		}
    
    		//OK, seems like everything's fine => cast the vote!
    		$threadinfo = $db->query("SELECT subject FROM ".TABLE_PREFIX."threads WHERE tid='".$row['tid']."';");
    		$threadrow = $db->fetch_array($threadinfo);
    
    		$query = $db->simple_select("reputation", "*", "adduid='".$mybb->user['uid']."' AND uid='".$row['uid']."' AND pid='".$pid."'");
    		$existing_reputation = $db->fetch_array($query);
    
    		$uid = $row['uid'];
    
    		$url = $mybb->settings['bburl']."/showthread.php?pid=".$pid."#".$pid;
    		$subject = $threadrow['subject'];
    
    		$comments = str_replace("@url", $url, $lang->fastrep_useless);
    		$comments = str_replace("@subj", $subject, $comments);
    
    		$reputation = array(
    			"uid" => $row['uid'],
    			"adduid" => $mybb->user['uid'],
    			"pid" => $pid,
    			"reputation" => -1*intval($mybb->usergroup['reputationpower']),
    			"dateline" => TIME_NOW,
    			"comments" => $comments
    		);
    
    		// Updating an existing reputation
    		if($existing_reputation['uid'])
    		{
    			$db->update_query("reputation", $reputation, "rid='".$existing_reputation['rid']."'");
    
    			// Recount the reputation of this user - keep it in sync.
    			$query = $db->simple_select("reputation", "SUM(reputation) AS reputation_count", "uid='{$uid}'");
    			$reputation_value = $db->fetch_field($query, "reputation_count");
    
    			$db->update_query("users", array('reputation' => intval($reputation_value)), "uid='{$uid}'");
    		}
    		// Insert a new reputation
    		else
    		{
    			$db->insert_query("reputation", $reputation);
    
    			// Recount the reputation of this user - keep it in sync.
    			$query = $db->simple_select("reputation", "SUM(reputation) AS reputation_count", "uid='{$uid}'");
    			$reputation_value = $db->fetch_field($query, "reputation_count");
    
    			$db->update_query("users", array('reputation' => intval($reputation_value)), "uid='{$uid}'");
    		}
    
    		$reptext = get_reputation($reputation_value, $row['uid']);
    		print $reptext;
    	}
    
    	if($mybb->input['action'] == "posrep")  //much like negrep, just different lang string
    	{
    		$pid = intval($_GET['pid']);
    
    		$check_query = $db->simple_select("posts", "uid, tid", "pid='".$pid."'");
    		$check = $db->num_rows($check_query);
    		if($check == 0) //no such post
    		{
    			return;
    		}
    
    		$uid = $mybb->user['uid'];
    		$user_permissions = user_permissions($uid);
    		$row = $db->fetch_array($check_query);
    
    		//Check if:
    		//a) This is self-voting
    		//b) Vote is cast by a guest
    		//c) Poster can't give reputation
    		//d) Poster can't use reputation system
    		if (($uid == $row['uid']) || ($uid == 0) || ($mybb->usergroup['cangivereputations'] != 1) || ($user_permissions['usereputationsystem'] != 1))
    		{
    			$currep = $db->simple_select("users", "reputation", "uid='".$row['uid']."'");
    			print get_reputation($db->fetch_field($currep, 'reputation'), $mybb->user['uid']);
    			return;
    		}
    
    		//OK, seems like everything's fine => cast the vote!
    		$threadinfo = $db->query("SELECT subject FROM ".TABLE_PREFIX."threads WHERE tid='".$row['tid']."';");
    		$threadrow = $db->fetch_array($threadinfo);
    
    		$query = $db->simple_select("reputation", "*", "adduid='".$mybb->user['uid']."' AND uid='".$row['uid']."' AND pid='".$pid."'");
    		$existing_reputation = $db->fetch_array($query);
    
    		$uid = $row['uid'];
    
    		$url = $mybb->settings['bburl']."/showthread.php?pid=".$pid."#".$pid;
    		$subject = $threadrow['subject'];
    
    		$comments = str_replace("@url", $url, $lang->fastrep_useful);
    		$comments = str_replace("@subj", $subject, $comments);
    
    		$reputation = array(
    			"uid" => $row['uid'],
    			"adduid" => $mybb->user['uid'],
    			"pid" => $pid,
    			"reputation" => intval($mybb->usergroup['reputationpower']),
    			"dateline" => TIME_NOW,
    			"comments" => $comments
    		);
    
    		// Updating an existing reputation
    		if($existing_reputation['uid'])
    		{
    			$db->update_query("reputation", $reputation, "rid='".$existing_reputation['rid']."'");
    
    			// Recount the reputation of this user - keep it in sync.
    			$query = $db->simple_select("reputation", "SUM(reputation) AS reputation_count", "uid='{$uid}'");
    			$reputation_value = $db->fetch_field($query, "reputation_count");
    
    			$db->update_query("users", array('reputation' => intval($reputation_value)), "uid='{$uid}'");
    		}
    		// Insert a new reputation
    		else
    		{
    			$db->insert_query("reputation", $reputation);
    
    			// Recount the reputation of this user - keep it in sync.
    			$query = $db->simple_select("reputation", "SUM(reputation) AS reputation_count", "uid='{$uid}'");
    			$reputation_value = $db->fetch_field($query, "reputation_count");
    
    			$db->update_query("users", array('reputation' => intval($reputation_value)), "uid='{$uid}'");
    		}
    
    		$reptext = get_reputation($reputation_value, $row['uid']);
    		print $reptext;
    	}
    
    	if ($mybb->input['action'] == "showrep")
    	{
    		print read_entries($mybb->input['pid']);
    	}
    }
    
    function fastrep_postbit($post)
    {
    	$post['fr_votes'] = build_votelist($post['pid'], 'h');
    	$post['fr_votes_c'] = build_votelist($post['pid'], 'c');
    }
    
    function build_votelist($pid=0, $postbit_type)
    {
    	global $post, $altbg, $lang;
    	$entries = read_entries($pid, $postbit_type);
    	$lang->load("fastrep", false, true);
    
    	if(!$entries)
    	{
    		$css_display = "display:none;";
    	}
    	else
    	{
    		$css_display = "";
    	}
    
    	//$display = "<div valign=\"bottom;\" style=\"{$css_display}float:left\" id=\"fr_votes_{$post['pid']}\">{$entries}</div>";
    	$display = "{$entries}";
    	if ($postbit_type == 'h') //'new' or 'horizontal' postbit
    	{
    		$display = '<tr style="'.$css_display.'" id="fr_votes_'.$pid.'_r"><td class="trow1"><span class="smalltext">'.$lang->fastrep_votes.': </span><span id="fr_votes_'.$pid.'">'.$display.'</span></td></tr>';
    	}
    	else //'classic' or 'vertical' postbit
    	{
    		$display = '<tr style="'.$css_display.'" id="fr_votes_'.$pid.'_r"><td class="'.$altbg.'" style="text-align: center;"><span class="smalltext">'.$lang->fastrep_votes.': </span></td><td class="'.$altbg.'" id="fr_votes_'.$pid.'">'.$display.'</td></tr>';
    	}
    
    	return $display;
    }
    
    function read_entries($pid=0)
    {
    	global $db, $entries, $mybb, $showall, $additional, $lang;
    
    	$lang->load("fastrep", false, true);
    
    	$entries = "";
    	$entries2 = "";
    	$query = $db->simple_select('reputation', 'adduid, reputation', "pid='$pid'", array('order_by' => 'dateline', 'order_dir' => 'DESC'));
    
    	$counter = 0;
    	while($vote = $db->fetch_array($query))
    	{
    		$dbuser = get_user($vote['adduid']);
    		if ($vote['reputation'] > 0)
    		{
    			$color = "green";
    			$score = "+".$vote['reputation'];
    		}
    		else
    		{
    			$color="red";
    			$score = $vote['reputation'];
    		}
    
    		$link = '<a href="'.get_profile_link($vote['adduid']).'" style="color: '.$color.'">'.$dbuser['username'].'</a>';
    
    		if($counter < $mybb->settings['fastrep_max'])
    		{
    			$entries .= $r1comma."<span style='color: $color'>".$link." ($score)</span>";
    		}
    
    		else
    		{
    			$entries2 .= $r2comma."<span style='color: $color'>".$link." ($score)</span>";
    			$r2comma =", ";
    		}
    		$r1comma =", ";
    		$counter++;
    	}
    	if($entries2 == "" && $entries != "")
    	{
    		$entries = "<span class=\"smalltext\">{$entries}</span>";
    		return $entries;
    	}
    	elseif($entries2 != "" && $entries != "")
    	{
    		$additional = "<br /><div style=\"display:none;\" id=\"fr_votes_{$pid}_a\"><div style=\"float:left\">{$entries2}&nbsp;&nbsp;<span style=\"font-size:8px\"><a style=\"text-decoration:none;\" href=\"javascript:hideAllVotes('fr_votes_{$pid}_a');\">[<i>x</i>] </a></span></div>";
    		$entrieslist = "<div style=\"float:left\"><span class=\"smalltext\">{$entries}&nbsp;<a href=\"javascript:getAllVotes('fr_votes_{$pid}_a');\">....</a></div>{$additional}";
    		return $entrieslist;
    	}
    	else
    	{
    		$entries = ""; // just to make sure
    		return $entries;
    	}
    
    }
    
    ?>
    PHP:
    could this have been the exploit?
     
    cscott5288, May 21, 2009 IP
  4. StevieHotstuff

    StevieHotstuff Peon

    Messages:
    28
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #4
    no thats not it

    try checking for an email address in functions.php
     
    StevieHotstuff, May 24, 2009 IP
  5. events

    events Active Member

    Messages:
    391
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    73
    #5
    Set additional layers of security on the admin panel... you can allow only your ip address to access the admin panel.
     
    events, May 25, 2009 IP
  6. NodeGeek

    NodeGeek Banned

    Messages:
    213
    Likes Received:
    10
    Best Answers:
    0
    Trophy Points:
    0
    #6
    NodeGeek, May 25, 2009 IP
  7. 123addme

    123addme Active Member

    Messages:
    171
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    58
    #7
    Set password protect folder phpmyadmin
     
    123addme, Jun 16, 2009 IP
  8. cscott5288

    cscott5288 Active Member

    Messages:
    912
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    60
    #8
    Thanks everyone for the advice. This is very old and I have found a solution a while back.
     
    cscott5288, Jun 16, 2009 IP