2019 高校运维 ezcms 复现

发表于 2020 年 1 月 13 日

之前高校运维碰到的题目, 当时就我一个人输出 web + 自己太菜了, 就没做出来 _(:3」∠)_, 寒假有时间看看, 复现一下题目.

题目非常良心的给了 docker-compose.yml, 所以搭建环境很简单. 把 install.lock 删掉重新装一遍就 ok. 经过一段时间审计, 可以发现 application/collection/controller/collection_content.class.phpcollection_test 等函数, 实际上未经任何过滤就将 URL 传给了 collection::get_content.

 1/**
 2* 添加采集节点
 3*/
 4public function add() {
 5    if (isset($_POST['dosubmit'])) {
 6        if (!$_POST['urlpage']) showmsg('网址配置不能为空!');
 7        $res = D('collection_node')->insert($_POST);
 8        if ($res) {
 9            showmsg(L('operation_success'), U('init'), 1);
10        } else {
11            showmsg(L('operation_failure'));
12        }
13    } else {
14        include $this->admin_tpl('collection_node_add');
15    }
16}
17
18public function collection_test() {
19    $id = isset($_GET['id']) ? intval($_GET['id']) : 0;
20    if (!$id) showmsg(L('lose_parameters'));
21    $data = D('collection_node')->where(array('nodeid' => $id))->find();
22    if ($data['urlpage'] == '') showmsg('网址配置不能为空!', 'stop');
23
24    //目标网址
25    if ($data['sourcetype'] == 1) {
26        $url = str_replace('(*)', $data['pagesize_start'], $data['urlpage']);
27    } else {
28        $url = $data['urlpage'];
29    }
30
31    //定义采集列表区间
32    $url_start = $data['url_start'];
33    $url_end = $data['url_end'];
34
35    if ($url_start == '' || $url_end == '') showmsg('列表区域配置不能为空!', 'stop');
36
37    $content = collection::get_content($url);
 1public static function get_content($url) {
 2    self::$url = $url;
 3
 4    $content = '';
 5    if (extension_loaded('curl')) {
 6        $ch = curl_init();
 7        curl_setopt($ch, CURLOPT_URL, $url);
 8        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 9        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
10        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
11        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
12        curl_setopt($ch, CURLOPT_HEADER, 0);
13        $content = curl_exec($ch);
14        curl_close($ch);
15    } else {
16        $content = @file_get_contents($url);
17    }
18    return trim($content);
19}

很明显的 SSRF, 再结合 nginx 配置.

1location ~ \.php$ {
2    include snippets/fastcgi-php.conf;
3
4    # With php-fpm (or other unix sockets):
5#	fastcgi_pass unix:/run/php/php7.3-fpm.sock;
6    # With php-cgi (or other tcp sockets):
7    fastcgi_pass 127.0.0.1:9000;
8}

明显就是 gopher 打 fastcgi 了.

根据 view 里的文字, 可以猜出是采集功能. 用默认账号密码 yzmcms 登录进后台之后在模块管理里面就能找到, 拿 gopherus 一把梭就可以.

然后我去看了眼最新代码 https://github.com/yzmcms/yzmcms. 仍然没有修复, 怪不得 wp 还没出来 (逃