漏洞位置在index.php 279行左右,这里对删除的文件名没有任何限制,导致了可以进行目录跳转,从而删除其他目录的文件,即任意文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
private static function deleteFileThemePluginAction() { if (! wCMS::$loggedIn) { return; } if (isset($_REQUEST['deleteFile']) || isset($_REQUEST['deleteTheme']) || isset($_REQUEST['deletePlugin']) && isset($_REQUEST['token'])) { if (hash_equals($_REQUEST['token'], wCMS::generateToken())) { $deleteList = [ [__DIR__.'/files', 'deleteFile'], [__DIR__.'/themes', 'deleteTheme'], [__DIR__.'/plugins', 'deletePlugin'], ]; foreach($deleteList as $entry) { list($folder, $request) = $entry; $filename = isset($_REQUEST[$request]) ? trim($_REQUEST[$request]) : false; if (!$filename || empty($filename)) { continue; } if ($filename == wCMS::get('config', 'theme')) { wCMS::alert('danger', 'Cannot delete currently active theme.'); wCMS::redirect(); continue; } if (file_exists("{$folder}/{$filename}")) { wCMS::recursiveDelete("{$folder}/{$filename}"); wCMS::alert('success', "Deleted {$filename}."); wCMS::redirect(); } } } } } |
这里filename直接进行request,并且没有任何限制,因此可以使用../来进行目录的跳转
后面跟进recursiveDelete这个函数,位于index.php 585行
1 2 3 4 5 6 7 8 9 10 11 12 |
private static function recursiveDelete($file) { if (is_dir($file)) { $list = glob($file . '*', GLOB_MARK); foreach ($list as $dir) { wCMS::recursiveDelete($dir); } rmdir($file); } elseif (is_file($file)) { unlink($file); } } |
这里的file既可以是目录,也可以是单独的文件,这里都有判断,但是页面功能为删除file目录下的文件,通过修改文件名这个参数,从而可以达到任意文件删除
下面给出利用过程(poc)
1.这是cms给出的文件上传功能,所有上传文件都在这个file目录下
2.然后我们点击这个删除的按钮,并进行抓包
问题就出在这个deleteFile参数没有任何限制,导致可以跨目录删除
这里我新建了一个test.txt文件用作测试,将上面的deleteFile参数改为../test.txt,然后抓包放行
3.这里就可以看到文件已经被删除,甚至还可以删除整个目录!