CVE-2022-0951: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: File Upload Restriction Bypass leading to Stored XSS Vulnerability in GitHub repository star7th/showdoc prior to 2.10.4.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2022-03-15T09:15Z
Repository: https://github.com/star7th/showdoc
Language: PHP
Files changed: server/Application/Api/Controller/AttachmentController.class.php, server/Application/Api/Model/AttachmentModel.class.php
Commit date: 2022-03-14 17:46:33 +0800
Commit message: file upload bug

Diff: diff --git a/server/Application/Api/Controller/AttachmentController.class.php b/server/Application/Api/Controller/AttachmentController.class.php
index d0a67616a..3afc91152 100644
--- a/server/Application/Api/Controller/AttachmentController.class.php
+++ b/server/Application/Api/Controller/AttachmentController.class.php
@@ -77,11 +77,13 @@ class AttachmentController extends BaseController {
         
         if (!$_FILES['editormd-image-file']) {
            return false;
         }
 
-        if(D("Attachment")->isDangerFilename($_FILES['editormd-image-file']['name'])){
+        if(!D("Attachment")->isAllowedFilename($_FILES['editormd-image-file']['name'])){
+            $message = "不支持上传该文件类型。如有需要请联系网站管理员" ;
+            echo json_encode(array("message"=>$message,"success"=>0));
             return false;
         }
 
         $url = D("Attachment")->upload($_FILES , 'editormd-image-file' , $login_user['uid'] , $item_id , $page_id ) ;
         if ($url) {
@@ -107,12 +109,12 @@ class AttachmentController extends BaseController {
         
         if (!$uploadFile) {
            return false;
         }
 
-        if(D("Attachment")->isDangerFilename($uploadFile['name'])){
-            $this->sendError(10100,'不支持此文件类型');
+        if(!D("Attachment")->isAllowedFilename($uploadFile['name'])){
+            $this->sendError(10101,'不支持上传该文件类型。如有需要请联系网站管理员');
             return false;
         }
 
         $url = D("Attachment")->upload($_FILES , 'file' , $login_user['uid'] , $item_id , $page_id ) ;
         if ($url) {
diff --git a/server/Application/Api/Model/AttachmentModel.class.php b/server/Application/Api/Model/AttachmentModel.class.php
index f7781533d..7f69b3cba 100644
--- a/server/Application/Api/Model/AttachmentModel.class.php
+++ b/server/Application/Api/Model/AttachmentModel.class.php
@@ -55,11 +55,11 @@ class AttachmentModel extends BaseModel {
 
 	//上传文件，返回url
 	public function upload($_files , $file_key , $uid , $item_id = 0  , $page_id = 0  ){
 		$uploadFile = $_files[$file_key] ;
 
-		if($this->isDangerFilename($uploadFile['name'])){
+		if( !$this->isAllowedFilename($_files[$file_key]['name']) ){
 			return false;
 		}
 
 		$oss_open = D("Options")->get("oss_open" ) ;
 		if ($oss_open) {
@@ -286,10 +286,11 @@ class AttachmentModel extends BaseModel {
 		}
 
 	}
 
 	// 判断文件名是否包含危险的扩展名
+	// 准备弃用。因为一个个ban太麻烦了。准备改用白名单机制
 	public function isDangerFilename($filename){
 
 		$isDangerStr = function ($filename , $keyword){
 			if(strstr(strip_tags(strtolower( $filename )), $keyword) ){
 				return true ;
@@ -317,8 +318,26 @@ class AttachmentModel extends BaseModel {
 		}
 	
 		return false;
 	}
 
-
+	// 判断上传的文件扩展名是否处于白名单内
+	public function isAllowedFilename($filename){
+		$allow_array = array(
+			'.jpg','.jpeg','.png','.bmp','.gif','.ico','.webp',
+			'.mp3','.wav','.m4a','.ogg','.webma','.mp4','.flv',
+			'.mov','.webmv','.m3u8a','.flac','.mkv',
+			'.zip','.tar','.gz','.tgz','.ipa','.apk','.rar','.iso','.bz2','.epub',
+			'.pdf','.ofd','.swf','.epub','.xps',
+			'.doc','.docx','.odt','.rtf','.docm','.dotm','.dot','.dotx','.wps','.wpt',
+			'.ppt','.pptx','.xls','.xlsx','.txt','.md','.psd','.csv',
+			'.cer','.ppt','.pub','.properties','.json','.css',
+			) ;
+
+		$ext = strtolower(substr($filename,strripos($filename,'.')) ); //获取文件扩展名（转为小写后）
+		if(in_array( $ext , $allow_array ) ){
+			return true ;
+		}
+		return false;
+	}
 
 }

Vulnerable code:         if(D("Attachment")->isDangerFilename($_FILES['editormd-image-file']['name'])){
        if(D("Attachment")->isDangerFilename($uploadFile['name'])){
            $this->sendError(10100,'不支持此文件类型');
		if($this->isDangerFilename($uploadFile['name'])){

Fixed code:         if(!D("Attachment")->isAllowedFilename($_FILES['editormd-image-file']['name'])){
            $message = "不支持上传该文件类型。如有需要请联系网站管理员" ;
            echo json_encode(array("message"=>$message,"success"=>0));
        if(!D("Attachment")->isAllowedFilename($uploadFile['name'])){
            $this->sendError(10101,'不支持上传该文件类型。如有需要请联系网站管理员');
		if( !$this->isAllowedFilename($_files[$file_key]['name']) ){
	// 准备弃用。因为一个个ban太麻烦了。准备改用白名单机制
	// 判断上传的文件扩展名是否处于白名单内
	public function isAllowedFilename($filename){
		$allow_array = array(
			'.jpg','.jpeg','.png','.bmp','.gif','.ico','.webp',
			'.mp3','.wav','.m4a','.ogg','.webma','.mp4','.flv',
			'.mov','.webmv','.m3u8a','.flac','.mkv',
			'.zip','.tar','.gz','.tgz','.ipa','.apk','.rar','.iso','.bz2','.epub',
			'.pdf','.ofd','.swf','.epub','.xps',
			'.doc','.docx','.odt','.rtf','.docm','.dotm','.dot','.dotx','.wps','.wpt',
			'.ppt','.pptx','.xls','.xlsx','.txt','.md','.psd','.csv',
			'.cer','.ppt','.pub','.properties','.json','.css',
			) ;

		$ext = strtolower(substr($filename,strripos($filename,'.')) ); //获取文件扩展名（转为小写后）
		if(in_array( $ext , $allow_array ) ){
			return true ;
		}
		return false;
	}