Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

DotClear文件上传漏洞分析

0
0
DotClear 文件上传漏洞

影响版本:<=2.11.2

官网链接: http://dotclear.org

漏洞分析

文件上传出现在 /admin/media.php 第250行

if ($dir && !empty($_FILES['upfile'])) { // only one file per request : @see option singleFileUploads in admin/js/jsUpload/jquery.fileupload $upfile = array('name' => $_FILES['upfile']['name'][0], 'type' => $_FILES['upfile']['type'][0], 'tmp_name' => $_FILES['upfile']['tmp_name'][0], 'error' => $_FILES['upfile']['error'][0], 'size' => $_FILES['upfile']['size'][0] ); if (!empty($_SERVER['HTTP_X_REQUESTED_WITH'])) { header('Content-type: application/json'); $message = array(); try { files::uploadStatus($upfile); $new_file_id = $core->media->uploadFile($upfile['tmp_name'], $upfile['name']); $message['files'][] = array( 'name' => $upfile['name'], 'size' => $upfile['size'], 'html' => mediaItemLine($core->media->getFile($new_file_id),1,$query) ); } catch (Exception $e) { $message['files'][] = array('name' => $upfile['name'], 'size' => $upfile['size'], 'error' => $e->getMessage() ); } echo json_encode($message); exit(); } else { try { files::uploadStatus($upfile); $f_title = (isset($_POST['upfiletitle']) ? html::escapeHTML($_POST['upfiletitle']) : ''); $f_private = (isset($_POST['upfilepriv']) ? $_POST['upfilepriv'] : false); $core->media->uploadFile($upfile['tmp_name'],$upfile['name'],$f_title,$f_private); dcPage::addSuccessNotice(__('Files have been successfully uploaded.')); $core->adminurl->redirect('admin.media',$page_url_params); } catch (Exception $e) { $core->error->add($e->getMessage()); } } }

然后,我们跟踪到第265行

$new_file_id = $core->media->uploadFile($upfile['tmp_name'], $upfile['name']);

在 /inc/core/class.dc.media.php 中定义了函数 uploadFile

public function uploadFile($tmp,$name,$title=null,$private=false,$overwrite=false) { if (!$this->core->auth->check('media,media_admin',$this->core->blog->id)) { throw new Exception(__('Permission denied.')); } $name = files::tidyFileName($name); parent::uploadFile($tmp,$name,$overwrite); return $this->createFile($name,$title,$private); }

最后调用了 /inc/libs/clearbricks/filemanager/class.filemanager.php 中的 uploadFile 函数

public function uploadFile($tmp,$dest,$overwrite=false) { $dest = $this->pwd.'/'.path::clean($dest); if ($this->isFileExclude($dest)) { throw new Exception(__('Uploading this file is not allowed.')); } if (!$this->inJail(dirname($dest))) { throw new Exception(__('Destination directory is not in jail.')); } if (!$overwrite && file_exists($dest)) { throw new Exception(__('File already exists.')); } if (!is_writable(dirname($dest))) { throw new Exception(__('Cannot write in this directory.')); } if (@move_uploaded_file($tmp,$dest) === false) { throw new Exception(__('An error occurred while writing the file.')); } files::inheritChmod($dest); return path::real($dest); }

在304行用 isFileExclude 函数判断了文件的合法性

protected function isFileExclude($f) { if (!$this->exclude_pattern) { return false; } return preg_match($this->exclude_pattern,$f); }

回到 /inc/core/class.dc.media.php ,第94行定义了正则表达式:

$this->exclude_pattern = $core->blog->settings->system->media_exclusion;

它其实是从数据库里面取出来的正则表达式,在安装CMS的时候就已经将配置文件写进了数据库;配置在 /inc/core/class.dc.core.php 第1405行

'/\.(phps?|pht(ml)?|phl|s?html?|js|htaccess)[0-9]*$/i'

好了,到此为止差不多已经理清楚了这一套流程,问题就出在这个正则表达式上面。

windows 系统下面,文件名末尾的 点 和 空格 会在创建或者重命名的时候自动删除,也就是说,我们只要创建 evil.php.... 之类的文件,就可以绕过此正则表达式。

此漏洞的重点不在于上传,而是正则表达式出现了问题,其它文件重命名的地方也会有此类问题出现。


Viewing all articles
Browse latest Browse all 12749