WellCMS 2.0 Beta3 后台任意文件上傳


一、概述

WellCMS是一款開源、傾向移動端的輕量級CMS,高負載CMS,億萬級CMS,是大數據量、高並發訪問網站最佳選擇的輕CMS。登陸該CMS后台,某圖片上傳處,由於上傳文件類型可控,可修改上傳文件類型獲取webshell。

二、復現

這個漏洞來自一次偶然的測試,一次幸運的測試,那就直接寫出我的測試過程。

第一步,登陸該CMS后台:

第二步,進入“后台管理“,定位利用點,點擊下圖紅框中圖片進行上傳:

上傳並抓取數據包:

第三步,修改post包中“filetype”參數類型為“php”;經分析 “data”參數為base64加密,這里我們將測試數據“<?php phpinfo();?>”經過base64加密等構造,形成“data”參數的數據:data%3Aimage%2Fjpeg%3Bbase64%2CPD9waHAgcGhwaW5mbygpOz8%2B,最后數據包放行,返回成功上傳為php文件的路徑:

最后,嘗試訪問,成功:

三、大致分析

根據漏洞定位代碼文件:route/attach.php,代碼如下:

if ($action == 'create') {
    // hook attach_create_start.php
    user_login_check();
    // hook attach_create_check_after.php
    $backstage = param(2, 0);
    $width = param('width', 0);
    $height = param('height', 0);
    $is_image = param('is_image', 0); // 圖片
    $name = param('name');
    $data = param_base64('data');
    $mode = param('mode', 0); // 上傳類型 1主圖
    $filetype = param('filetype'); // 壓縮圖片后綴jpeg jpg png等
    $convert = param('convert', 0); // 圖片轉換壓縮 = 1
    $n = param('n', 0); // 對應主圖賦值
    $type = param('type', 0); // type = 0則按照SESSION數組附件數量統計,type = 1則按照傳入的n數值
    // hook attach_create_before.php
    // 允許的文件后綴名
    //$types = include _include(APP_PATH.'conf/attach.conf.php');
    //$allowtypes = $types['all'];
    empty($group['allowattach']) AND $gid != 1 AND message(2, '您無權上傳');
    // hook attach_create_center.php
    empty($data) AND message(1, lang('data_is_empty'));
    //$data = base64_decode_file_data($data);
    $size = strlen($data);
    $size > 20480000 AND message(1, lang('filesize_too_large', array('maxsize' => '20M', 'size' => $size)));
    // hook attach_create_file_ext_start.php
    // 獲取文件后綴名 111.php.shtmll
    $ext = file_ext($name, 7);
    $filetypes = include APP_PATH . 'conf/attach.conf.php';
    // hook attach_create_file_ext_before.php
    //主圖必須為圖片
    if ($is_image == 1 && $mode == 1 && !in_array($ext, $filetypes['image'])) message(1, lang('well_up_picture_error'));

    // hook attach_create_file_ext_center.php

    // 如果文件后綴不在規定范圍內 改變后綴名
    //!in_array($ext, $filetypes['all']) AND $ext = '_' . $ext;
    if (!in_array($ext, $filetypes['all'])) {
        $ext = '_' . $ext;
    } else {
        // CMS上傳圖片
        $t == 1 AND $convert == 1 AND $is_image == 1 AND $ext = $filetype;
    }
    // hook attach_create_file_ext_after.php
    $tmpanme = $uid . '_' . xn_rand(15) . '.' . $ext;
    // hook attach_create_tmpanme_after.php
    $tmpfile = $conf['upload_path'] . 'tmp/' . $tmpanme;
    // hook attach_create_tmpfile_after.php
    $tmpurl = $conf['upload_url'] . 'tmp/' . $tmpanme;
    // hook attach_create_tmpurl_after.php
    $filetype = attach_type($name, $filetypes);
    // hook attach_create_save_before.php
    file_put_contents($tmpfile, $data) OR message(1, lang('write_to_file_failed'));
    // hook attach_create_save_after.php
    // 保存到 session,發帖成功以后,關聯到帖子。
    // save attach information to session, associate to post after create thread.
    // 拋棄之前的 $_SESSION 數據,重新啟動 session,降低 session 並發寫入的問題
    // Discard the previous $_SESSION data, restart the session, reduce the problem of concurrent session write
    sess_restart();
    empty($t) AND empty($_SESSION['tmp_files']) AND $_SESSION['tmp_files'] = array();
    $t == 1 AND empty($_SESSION['tmp_website_files']) AND $_SESSION['tmp_website_files'] = array();

    // hook attach_create_after.php
    // type = 0則按照SESSION數組附件數量統計,type = 1則按照傳入的n數值
    empty($type) AND $n = ($t == 1) ? count($_SESSION['tmp_website_files']) : count($_SESSION['tmp_files']);
    $filesize = filesize($tmpfile);
    $attach = array(
        'backstage' => $backstage, // 0前台 1后台
        'url' => $backstage ? '../' . $tmpurl : '' . $tmpurl,
        'path' => $tmpfile,
        'orgfilename' => $name,
        'filetype' => $filetype,
        'filesize' => $filesize,
        'width' => $width,
        'height' => $height,
        'isimage' => $is_image,
        'downloads' => 0,
        'aid' => '_' . $n
    );
    // hook attach_create_array_after.php
    if ($mode == 1) {
        // hook attach_create_thumbnail_beofre.php
        $_SESSION['tmp_thumbnail'] = $attach;
        // hook attach_create_thumbnail_after.php
    } else {
        // hook attach_create_website_files_beofre.php
        // 0 BBS 1 CMS
        $t == 1 ? $_SESSION['tmp_website_files'][$n] = $attach : $_SESSION['tmp_files'][$n] = $attach;
        // hook attach_create_website_files_after.php
    }
    // hook attach_create_session_after.php
    unset($attach['path']);
    // hook attach_create_end.php
    message(0, $attach);
}

大致流程:
1、 首先,接受相關參數,將filetype自行設置成“php”:

$data = param_base64('data');
$filetype = param('filetype'); /

2、 進行邏輯判斷:

if (!in_array($ext, $filetypes['all'])) {
        $ext = '_' . $ext;
    } else {
        // CMS上傳圖片
        $t == 1 AND $convert == 1 AND $is_image == 1 AND $ext = $filetype;
    }

3、 最后成功寫入:

$tmpanme = $uid . '_' . xn_rand(15) . '.' . $ext;
    // hook attach_create_tmpanme_after.php
    $tmpfile = $conf['upload_path'] . 'tmp/' . $tmpanme;
    // hook attach_create_tmpfile_after.php
    $tmpurl = $conf['upload_url'] . 'tmp/' . $tmpanme;
    // hook attach_create_tmpurl_after.php
    $filetype = attach_type($name, $filetypes);
    // hook attach_create_save_before.php
    file_put_contents($tmpfile, $data) OR message(1, lang('write_to_file_failed'));


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM