1. WPLMS 플러그인 (WordPress Learning Management System)
- WordPress를 사용해 LMS를 구축할 수 있도록 돕는 플러그인
※ Learning Management System : 학습 관리 시스템, 온라인으로 학생들의 학습을 관리할 수 있게 해주는 소프트웨어
2. 취약점
2.1 CVE-2024-56046 [2][3]
- WPLMS에서 발생하는 파일 업로드 취약점 (CVSS: 10.0)
영향받는 버전 : WPLMS <= 1.9.9
- includes/vibe-shortcodes/shortcodes.php의 wplms_form_uploader_plupload()에 취약점 존재
> Line9 : $_REQUEST["name"] 값을 우선적으로 $fileName에 할당하며, 해당 값이 없을 경우 $_FILES["file"]["name"] 값을 사용
> Line17 : $fileName은 파일 저장 경로를 결정하는데 사용됨
- name 파라미터는 사용자 요청으로부터 추출 (Line9)
> 해당 값에 대한 검증 없이 사용하여 악의적인 파일(Ex. "../../../attack.php")을 사용해 파일을 업로드할 수 있음
- $fileName을 기반으로 서버의 특정 경로에 저장
> 해당 값에 대한 검증이 없어 임의 디렉터리에 악의적인 파일을 업로드할 수 있음
includes/vibe-shortcodes/shortcodes.php, function wplms_form_uploader_plupload()
1 function wplms_form_uploader_plupload(){
2 check_ajax_referer('wplms_form_uploader_plupload');
3
4 if (empty($_FILES) || $_FILES['file']['error']) {
5 die('{"OK": 0, "info": "Failed to move uploaded file."}');
6 }
7 $chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;
8 $chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 0;
9 $fileName = isset($_REQUEST["name"]) ? $_REQUEST["name"] : $_FILES["file"]["name"];
10
11 $upload_dir_base = wp_upload_dir();
12 $folderPath = $upload_dir_base['basedir']."/wplms_form_uploader";
13 if(function_exists('is_dir') && !is_dir($folderPath)){
14 if(function_exists('mkdir'))
15 mkdir($folderPath, 0755, true) || chmod($folderPath, 0755);
16 }
17 $filePath = $folderPath."/$fileName";
18
19 // Open temp file
20 if($chunk == 0)
21 $perm = "wb" ;
22 else
23 $perm = "ab";
24
25 $out = @fopen("{$filePath}.part",$perm );
26
27 if ($out) {
28 // Read binary input stream and append it to temp file
29 $in = @fopen($_FILES['file']['tmp_name'], "rb");
30
31 if ($in) {
32 while ($buff = fread($in, 4096))
33 fwrite($out, $buff);
34 } else
35 die('{"OK": 0, "info": "Failed to open input stream."}');
36
37 @fclose($in);
38 @fclose($out);
39
40 @unlink($_FILES['file']['tmp_name']);
41 } else
42 die('{"OK": 0, "info": "Failed to open output stream."}');
43
44 // Check if file has been uploaded
45 if (!$chunks || $chunk == $chunks - 1) {
46 // Strip the temp .part suffix off
47 rename("{$filePath}.part", $filePath);
48
49 }
50 die('{"OK": 1, "info": "Upload successful."}');
51 exit;
52 }
2.2 CVE-2024-56050 [4][5]
- WPLMS에서 발생하는 파일 업로드 취약점 (CVSS: 9.9)
영향받는 버전 : WPLMS < 1.9.9.5.3
- includes/vibe-shortcodes/upload_handler.php의 wp_ajax_zip_upload()에 취약점 존재
> Line4 ~ Line8 : 사용자 요청에서 값을 추출해 변수 할당
> Line18 ~ Line19 : Zip 파일 내 다른 파일이 있는 경우 extractZip()을 통해 파일 내 모든 내용을 추출
> 사용자 요청에서 추출한 값을 검증없이 사용하여 취약점 발생
- extractZip()
> Line6 : extractTo()를 사용해 Zip 파일내 모든 파일을 $target 디렉터리에 추출
> 파일에 대한 검증없이 추출되어 취약점 발생
> attack.php 등의 악의적 파일을 포함한 Zip 파일을 업로드할 수 있는 문제 발생
includes/vibe-shortcodes/upload_handler.php, function wp_ajax_zip_upload()
1 function wp_ajax_zip_upload(){
2 $arr = array();
3
4 $file = $_FILES['uploadedfile']['tmp_name'];
5 $dir = explode(".",$_FILES['uploadedfile']['name']);
6 $dir[0] = str_replace(" ","_",$dir[0]);
7 $target = $this->getUploadsPath().$dir[0];
8 $index = count($dir) -1;
9
10 if (!isset($dir[$index]) || $dir[$index] != "zip")
11 $arr[0] = __('The Upload file must be zip archive','wplms');
12 else{
13 while(file_exists($target)){
14 $r = rand(1,10);
15 $target .= $r;
16 $dir[0] .= $r;
17 }
18 if (!empty($file))
19 $arr = $this->extractZip($file,$target,$dir[0]);
20 else
21 $arr[0] = __('File too big','wplms');
22 }
23 echo json_encode($arr);
24 die();
25 }
includes/vibe-shortcodes/upload_handler.php, function extractZip()
1 function extractZip($fileName,$target,$dir){
2 $arr = array();
3 $zip = new ZipArchive;
4 $res = $zip->open($fileName);
5 if ($res === TRUE) {
6 $zip->extractTo($target);
7 $zip->close();
8 $file = $this->getFile($target);
9 ;
10 if($file){
11 $arr[0] = 'uploaded';
12 $arr[1] = $this->getUploadsUrl().$dir."/".$file;
13 $arr[2] = $dir;
14 $arr[3] =$file;
15 $arr[4] = $this->getUploadsPath().$dir;
16 }else{
17 $arr[0] = __('Please upload zip file, Index.html file not found in package','wplms').$target.print_r($file);
18 $this->rrmdir($target);
19 }
20 }else{
21 $arr[0] = __('Upload failed !','wplms');;
22 }
23 return $arr;
24 }
2.3 CVE-2024-56052 [6][7]
- WPLMS에서 발생하는 파일 업로드 취약점 (CVSS: 9.9)
영향받는 버전 : WPLMS < 1.9.9.5.3
- includes/assignments/assignments.php의 wplms_assignment_plupload()에 취약점 존재
> Line2 ~ Line4 : WordPress 내에서 생성된 요청인지와 로그인 유무를 검증
> Line18 : $user_id 및 $assignment_id를 기반으로 $folderPath 생성
- $assignment_id에 대한 유효성 검증이 없어 임의 디렉터리에 악의적인 파일을 업로드할 수 있음
includes/assignments/assignments.php, function wplms_assignment_plupload()
1 function wplms_assignment_plupload(){
2 check_ajax_referer('wplms_assignment_plupload');
3 if(!is_user_logged_in())
4 die('user not logged in');
5
6 $user_id = get_current_user_id();
7
8 if (empty($_FILES) || $_FILES['file']['error']) {
9 die('{"OK": 0, "info": "Failed to move uploaded file."}');
10 }
11
12 $chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;
13 $chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 0;
14 $fileName = isset($_REQUEST["name"]) ? $_REQUEST["name"] : $_FILES["file"]["name"];
15
16 $upload_dir_base = wp_upload_dir();
17 $assignment_id = $_POST['assignment_id'];
18 $folderPath = $upload_dir_base['basedir']."/wplms_assignments_folder/".$user_id.'/'.$assignment_id;
19 if(function_exists('is_dir') && !is_dir($folderPath)){
20 if(function_exists('mkdir'))
21 mkdir($folderPath, 0755, true) || chmod($folderPath, 0755);
22 }
23
24
25 $filePath = $folderPath."/$fileName";
26 /*if(function_exists('file_exists') && file_exists($filePath)){
27 echo __(' Chunks upload error ','wplms'). $fileName.__(' already exists.Please rename your file and try again ','wplms');
28 die();
29 }*/
30 // Open temp file
31 if($chunk == 0) $perm = "wb" ;
32 else $perm = "ab";
33
34 $out = @fopen("{$filePath}.part",$perm );
35
36 if ($out) {
37 // Read binary input stream and append it to temp file
38 $in = @fopen($_FILES['file']['tmp_name'], "rb");
39
40 if ($in) {
41 while ($buff = fread($in, 4096))
42 fwrite($out, $buff);
43 } else
44 die('{"OK": 0, "info": "Failed to open input stream."}');
45
46 @fclose($in);
47 @fclose($out);
48
49 @unlink($_FILES['file']['tmp_name']);
50 } else
51 die('{"OK": 0, "info": "Failed to open output stream."}');
52
53
54 // Check if file has been uploaded
55 if (!$chunks || $chunk == $chunks - 1) {
56 // Strip the temp .part suffix off
57 rename("{$filePath}.part", $filePath);
58
59 }
60 die('{"OK": 1, "info": "Upload successful."}');
61 exit;
62 }
3. 대응방안
- 벤더사 제공 업데이트 적용 [8][9]
> WPLMS Plugin 1.9.9.5.3
> 파일 이름과 유형을 확인하여 업로드할 수 있는 파일을 제한하는 패치 적용
> 영향을 받는 기능에 대한 추가 권한 확인을 구현하거나 영향을 받는 코드 제거
4. 참고
[1] https://patchstack.com/articles/multiple-critical-vulnerabilities-patched-in-wplms-and-vibebp-plugins/
[2] https://nvd.nist.gov/vuln/detail/CVE-2024-56046
[3] https://patchstack.com/database/wordpress/plugin/wplms-plugin/vulnerability/wordpress-wplms-plugin-1-9-9-unauthenticated-arbitrary-file-upload-vulnerability
[4] https://nvd.nist.gov/vuln/detail/CVE-2024-56050
[5] https://patchstack.com/database/wordpress/plugin/wplms-plugin/vulnerability/wordpress-wplms-plugin-1-9-9-5-3-subscriber-arbitrary-file-upload-vulnerability
[6] https://nvd.nist.gov/vuln/detail/CVE-2024-56052
[7] https://patchstack.com/database/wordpress/plugin/wplms-plugin/vulnerability/wordpress-wplms-plugin-1-9-9-5-2-student-arbitrary-file-upload-vulnerability
[8] https://wplms.io/support/knowledge-base/vibebp-1-9-9-7-7-wplms-plugin-1-9-9-5-2/
[9] https://asec.ahnlab.com/ko/85311/
'취약점 > File Up&Download, Inclusion' 카테고리의 다른 글
Apache Struts 임의 파일 업로드 취약점 (CVE-2024-53677) (0) | 2024.12.19 |
---|---|
Cleo 제품 임의 파일 읽기/쓰기 취약점 (CVE-2024-50623) (0) | 2024.12.15 |
Apache Struts 파일 업로드 취약점 (CVE-2023-50164)_내용추가 (1) | 2023.12.18 |
이니텍 INISAFE CrossWeb EX V3 파일 다운로드 취약점 (0) | 2023.03.31 |
VMware vCenter Server 파일 업로드 취약점 (CVE-2021-21972) (0) | 2023.01.15 |