WordPress File-manager 任意文件上传漏洞分析

  • A+
所属分类:安全文章
Wordpress File-manager 任意文件上传漏洞分析


漏洞分析



分析环境:

  • wordpress 5.5.1

  • file manager 6.0

  • win10 phpstudy php 7.0.9


漏洞点位于file manager的connector.minimal.php文件,具体路径在wordpresswp-contentpluginswp-file-managerlibphpconnector.minimal.php

Wordpress File-manager 任意文件上传漏洞分析

首先实例化一个elFinderConnector对象,然后调用它的run()方法,跟进run();

Wordpress File-manager 任意文件上传漏洞分析

如果HTTP请求的方法是POST,会把POSTGET请求的数据保存到$src,然后判断POST传的参数。如果不传入targets,就不会进入前几个判断,之后会把POST请求传的cmd变量赋给$cmd,然后调用commandExists()检测传入的$cmd是否存在。

Wordpress File-manager 任意文件上传漏洞分析

然后利用commandArgsList()函数获取$cmd对应的命令参数列表,漏洞利用需要上传文件,这里只关注$cmdupload的情况。

public function commandArgsList($cmd){        if ($this->commandExists($cmd)) {            $list = $this->commands[$cmd];            $list['reqid'] = false;        } else {            $list = array();        }        return $list;}/*upload对应的数组如下:'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)    */


循环遍历,将POST传入的参数保存到$args数组中,然后调用input_filter()函数对$args进行简单的过滤,

Wordpress File-manager 任意文件上传漏洞分析

替换掉%00,并且做stripslashes()处理。然后将通过表单上传的文件$_FILES存到$args['FILE']中。然后调用exec()函数,跟进

Wordpress File-manager 任意文件上传漏洞分析

前面会进行一些判断,最后进入到$this->$cmd($args)调用upload()函数,跟进

Wordpress File-manager 任意文件上传漏洞分析

首先将POST传入的target赋给$target变量,然后调用volume()函数,

Wordpress File-manager 任意文件上传漏洞分析

可以看到$this->volume数组含有两项,一项是l1_,一项是t1_volume()函数定义如果传入的$hashl1_t1_开头,返回$this->volume数组对应的值,否则返回false。在upload函数中会检测$volume,如果其为false,程序会报错结束,所以POST传入的target必须以它们两个为前缀。继续分析upload()函数。依次取出$args数组中的值赋给相应的变量,这里要求$args['FILES']['upload']也就是$_FILES['upload']为数组,才能将其赋给$files变量,这就需要上传文件时上传一个文件数组。接下来其他的如html、upload_path、chunk、cid、mtime等参数可以不传。之后遍历$files['name']也就是$_FILES['upload']['name'],如果文件上传成功,将$_FILES['upload']['name']赋给$tmpname,然后调用fopen()打开上传的临时文件,将指针保存在$fp。在不传入upload_path$thash等于$target,所以$_target$target为我们POST传入的target变量。之后调用了$volume->upload()函数,第一个参数为之前打开文件的指针,第二个参数为POST传入的target变量,第三个参数为上传的文件名,第四个参数为空的数组。跟进elFinderVolumeDriverupload()

public function upload($fp, $dst, $name, $tmpname, $hashes = array()){        if ($this->commandDisabled('upload')) {            return $this->setError(elFinder::ERROR_PERM_DENIED);        }
if (($dir = $this->dir($dst)) == false) { return $this->setError(elFinder::ERROR_TRGDIR_NOT_FOUND, '#' . $dst); }
if (empty($dir['write'])) { return $this->setError(elFinder::ERROR_PERM_DENIED); }
if (!$this->nameAccepted($name, false)) { return $this->setError(elFinder::ERROR_INVALID_NAME); }
$mimeByName = ''; if ($this->mimeDetect === 'internal') { $mime = $this->mimetype($tmpname, $name); } else { $mime = $this->mimetype($tmpname, $name); $mimeByName = $this->mimetype($name, true); if ($mime === 'unknown') { $mime = $mimeByName; } }
if (!$this->allowPutMime($mime) || ($mimeByName && !$this->allowPutMime($mimeByName))) { return $this->setError(elFinder::ERROR_UPLOAD_FILE_MIME, '(' . $mime . ')'); }
$tmpsize = (int)sprintf('%u', filesize($tmpname)); if ($this->uploadMaxSize > 0 && $tmpsize > $this->uploadMaxSize) { return $this->setError(elFinder::ERROR_UPLOAD_FILE_SIZE); }
$dstpath = $this->decode($dst); if (isset($hashes[$name])) { $test = $this->decode($hashes[$name]); $file = $this->stat($test); } else { $test = $this->joinPathCE($dstpath, $name); $file = $this->isNameExists($test); }
$this->clearcache();
if ($file && $file['name'] === $name) { // file exists and check filename for item ID based filesystem if ($this->uploadOverwrite) { if (!$file['write']) { return $this->setError(elFinder::ERROR_PERM_DENIED); } elseif ($file['mime'] == 'directory') { return $this->setError(elFinder::ERROR_NOT_REPLACE, $name); } $this->remove($test); } else { $name = $this->uniqueName($dstpath, $name, '-', false); } }
$stat = array( 'mime' => $mime, 'width' => 0, 'height' => 0, 'size' => $tmpsize);
// $w = $h = 0; if (strpos($mime, 'image') === 0 && ($s = getimagesize($tmpname))) { $stat['width'] = $s[0]; $stat['height'] = $s[1]; } // $this->clearcache(); if (($path = $this->saveCE($fp, $dstpath, $name, $stat)) == false) { return false; }
$stat = $this->stat($path); // Try get URL if (empty($stat['url']) && ($url = $this->getContentUrl($stat['hash']))) { $stat['url'] = $url; }
return $stat;}


首先进入commandDisabled()函数,返回false。

Wordpress File-manager 任意文件上传漏洞分析

然后进入dir()函数,参数为$dstPOST传入的target值。

Wordpress File-manager 任意文件上传漏洞分析

调用了file函数,

Wordpress File-manager 任意文件上传漏洞分析

跟进decode()函数

Wordpress File-manager 任意文件上传漏洞分析

Wordpress File-manager 任意文件上传漏洞分析

decode()函数首先判断是否以$this->id开头,然后截取出l1_后面的内容,之后进行base64解密,uncrypt函数如上,未作操作。然后更换分隔符,之后调用abspathCE()函数,从注释中可以看出,abspathCE()函数会先判断$path是否等于分隔符,如果等于,返回$this->root,否则返回$this->root拼接$path。看下对应的abspathCE()函数。

Wordpress File-manager 任意文件上传漏洞分析

Wordpress File-manager 任意文件上传漏洞分析

Wordpress File-manager 任意文件上传漏洞分析

ps:POST传入target前缀不同的区别

  • 前缀为l1_时,$this->root 为C:Usersadminphpstudy_proWWWwordpresswp-contentpluginswp-file-managerlibfiles

Wordpress File-manager 任意文件上传漏洞分析

  • 前缀为t1_时,$this->disabled[]包含upload,程序会报错结束,$this->root 为C:Usersadminphpstudy_proWWWwordpresswp-contentpluginswp-file-managerlibfiles.trash

Wordpress File-manager 任意文件上传漏洞分析

继续分析程序流程,decode()函数会返回C:Usersadminphpstudy_proWWWwordpresswp-contentpluginswp-file-managerlibfiles,然后调用stat()函数。

Wordpress File-manager 任意文件上传漏洞分析

Wordpress File-manager 任意文件上传漏洞分析

stat()函数返回的$ret

Array(    [isowner] =>    [ts] => 1589423646    [mime] => directory    [read] => 1    [write] => 1    [size] => 0    [hash] => l1_Lw    [name] => files    [rootRev] =>    [options] => Array        (            [path] =>            
=> /wordpress/wp-content/plugins/wp-file-manager/lib/php/../files/
[tmbUrl] => /wordpress/wp-content/plugins/wp-file-manager/lib/php/../files/.tmb/ [disabled] => Array ( [0] => chmod )
[separator] => [copyOverwrite] => 1 [uploadOverwrite] => 1 [uploadMaxSize] => 9223372036854775807 [uploadMaxConn] => 3 [uploadMime] => Array ( [firstOrder] => deny [allow] => Array ( [0] => all )
[deny] => Array ( [0] => all )
)
[dispInlineRegex] => ^(?:(?:video|audio)|image/(?!.++xml)|application/(?:ogg|x-mpegURL|dash+xml)|(?:text/plain|application/pdf)$) [jpgQuality] => 100 [archivers] => Array ( [create] => Array ( [0] => application/x-tar [1] => application/zip )
[extract] => Array ( [0] => application/x-tar [1] => application/zip )
[createext] => Array ( [application/x-tar] => tar [application/zip] => zip )
)
[uiCmdMap] => Array ( )
[syncChkAsTs] => 1 [syncMinMs] => 10000 [i18nFolderName] => 0 [tmbCrop] => 1 [tmbReqCustomData] => [substituteImg] => 1 [onetimeUrl] => 1 [trashHash] => t1_Lw [csscls] => elfinder-navbar-root-local )
[volumeid] => l1_ [locked] => 1 [isroot] => 1 [phash] =>)


返回dir()函数,然后在返回到upload()函数,将返回值赋给upload()函数中的$dir变量,

Wordpress File-manager 任意文件上传漏洞分析

然后进行mime的判断,程序识别上传的php脚本的mimetext/x-php,跟进allowPutMime()函数,

Wordpress File-manager 任意文件上传漏洞分析

从程序自带的注释中可以看出如果uploadOrder数组为array('deny','allow'),则默认允许上传$mime类型的文件。然后获取文件的大小,若文件大小不合法报错结束程序,之后decode()处理$dst(POST传入的target)返回结果赋给$dstpath,因为$hash为空数组,所以会调用joinPathCE()$dstpath$name(上传文件的文件名)拼接,然后检查文件是否存在。

Wordpress File-manager 任意文件上传漏洞分析

最后调用$this->saveCE()

Wordpress File-manager 任意文件上传漏洞分析

跟进_save()

Wordpress File-manager 任意文件上传漏洞分析

本地是利用Windows系统分析,$pathC:Usersadminphpstudy_proWWWwordpresswp-contentpluginswp-file-managerlibfilesshell.php;$uriC:Windowsphpxxxx.tmp,最后会调用copy()将上传的文件复制到wordpresswp-contentpluginswp-file-managerlibfilesshell.php,即完成了任意文件上传。

Wordpress File-manager 任意文件上传漏洞分析

 

漏洞利用



利用burp发包

Wordpress File-manager 任意文件上传漏洞分析

访问http://192.168.43.44/wordpress/wp-content/plugins/wp-file-manager/lib/files/shell.php

Wordpress File-manager 任意文件上传漏洞分析


漏洞修复



影响范围

file manager 6.0至6.8

官方修复删除了connector.minimal.php和connector.minimal.php-dist文件。

Wordpress File-manager 任意文件上传漏洞分析

增加了.htaccess。

Wordpress File-manager 任意文件上传漏洞分析

Wordpress File-manager 任意文件上传漏洞分析


- End -

精彩推荐

数据中心巨头Equinix遭遇勒索软件攻击,被勒索450万美元

快报!英国纽卡斯尔大学遭受DoppelPaymer勒索软件攻击,导致大量数据发生泄漏

设备指纹指南

一键 Shell,我的 OSWE 之旅

Wordpress File-manager 任意文件上传漏洞分析

Wordpress File-manager 任意文件上传漏洞分析


戳“阅读原文”查看更多内容

发表评论

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