PHP2Shell: Aviso Crítico CVE-2026-109618 & CVE-2026-109619 e Matriz de Versões
PHP2Shell: Aviso Crítico CVE-2026-109618 & CVE-2026-109619 e Matriz de Versões
<time datetime="2026-10-23">Verificado em 23 de outubro de 2026</time> · Fontes: php.net, GitHub Security Advisories GHSA-w8hw-w9fx-j79w / GHSA-6wmf-4rv5-p3rp
Em 21 de outubro de 2026, a equipe do core do PHP e diversos pesquisadores de segurança publicaram duas vulnerabilidades críticas conhecidas coletivamente como PHP2Shell: CVE-2026-109618 e CVE-2026-109619. A pontuação CVSS v4.0 é 9,2 (Critical). Um atacante não autenticado pode executar comandos arbitrários do sistema operacional no contexto do worker do servidor web ou do PHP-FPM (www-data, nginx, apache). O ponto decisivo: o defeito está no núcleo C da engine PHP, na manipulação de uploads multipart RFC1867 e no tratamento de erros do Zend Memory Manager (ZMM). Middleware de framework, validação de entrada e a maioria das regras de WAF agem tarde demais ou não agem.
1. Matriz de vulnerabilidades e fatos confirmados
| Característica | CVE-2026-109618 | CVE-2026-109619 |
|---|---|---|
| Classe | Corrupção de estado de memória no caminho OOM | Estado global residual / Use-After-Free (UAF) |
| CVSS v4.0 | 9,2 (Critical) | 9,2 (Critical) |
| Autenticação | Nenhuma (não autenticado) | Nenhuma (não autenticado) |
| Exposição padrão | session.upload_progress ativo por padrão | session.upload_progress ativo por padrão |
| Momento do gatilho | Parsing do corpo da requisição (antes do código do usuário) | Parsing e teardown da sessão |
| Ambientes afetados | PHP-FPM, Apache mod_php, FrankenPHP, LiteSpeed | PHP-FPM, Apache mod_php, FrankenPHP, LiteSpeed |
| Versões afetadas | PHP 5.4–8.5 | PHP 5.4–8.5 |
A faixa afetada é PHP 5.4 a 8.5. Resumos que citam 5.x–8.4 estão errados: o ramo 8.5 também é vulnerável antes da 8.5.12. Como session.upload_progress está On por padrão desde o PHP 5.4, praticamente todos os runtimes de produção não explicitamente endurecidos estão na superfície de ataque — independentemente de a aplicação usar sessões.
2. Ciclo de vida do ataque: comprometimento antes da execução da aplicação
O perigo central do PHP2Shell é o momento em que o código C vulnerável executa. Ele roda durante o streaming HTTP, antes que index.php, roteadores de framework ou regras de WAF em nível de aplicação entrem em ação.
[ REQUISIÇÃO HTTP POST ENTRANTE ]
(qualquer caminho: /index.php, /login, /404 inexistente)
│
▼
┌─────────────────────────────────────────────────────────┐
│ Camada SAPI da engine PHP (núcleo C) │
│ - lê headers, Content-Type: multipart/form-data │
└───────────────────────────┬─────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ ext/session/session.c :: php_session_rfc1867_callback() │
│ - detecta PHP_SESSION_UPLOAD_PROGRESS │
│ - cacheia ponteiro bruto: cached_post_bytes │
│ - [FALHA CRÍTICA] OOM / reset de sessão ocorre │
│ - memória FREED -> ponteiro se torna DANGLING │
└───────────────────────────┬─────────────────────────────┘
┌────────────────┴────────────────┐
▼ ▼
[ requisições normais ] [ exploit PHP2Shell ]
código da aplicação roda spray de fake zval
(Laravel, WordPress) hijack de vtable -> system()
▼ ▼
resposta normal [ RCE ALCANÇADO ]
(antes do código do usuário rodar!)
Consequências diretas:
- Gatilho pré-execução: o callback dispara durante o parsing, não após o roteamento.
- Sem formulário de upload necessário: qualquer endpoint acessível — inclusive um handler 404 — basta.
- Sessões irrelevantes: mesmo que a aplicação nunca chame
session_start(), o caminho fica ativo enquanto a opção estiver globalmente ligada.
3. Causa raiz: cached_post_bytes, longjmp e ZMM
Em ext/session/session.c, durante o progresso de upload, ponteiros zval brutos da HashTable de sessão são copiados para variáveis estáticas de processo.
/* ext/session/session.c — modelo simplificado */
static zval *cached_post_bytes;
static zval *cached_file_bytes;
static int php_session_rfc1867_callback(unsigned int event,
void *event_data,
void **extra)
{
switch (event) {
case MULTIPART_EVENT_START: {
zval *progress = php_session_get_progress_entry();
ZVAL_LONG(&progress->value.bytes_processed, 0);
/* FALHA: endereço bruto de zval interno cacheado globalmente */
cached_post_bytes = &progress->value.bytes_processed;
cached_file_bytes = &progress->value.files[0].bytes_processed;
break;
}
case MULTIPART_EVENT_FILE_DATA:
Z_LVAL_P(cached_post_bytes) += chunk_len;
break;
}
return SUCCESS;
}
Quando a sessão é recarregada (session_reread()) ou a entrada é substituída via zend_hash_update(), zval_ptr_dtor devolve o chunk ao Zend Memory Manager. Os ponteiros globais, porém, não são invalidados. O próximo chunk escreve em memória liberada:
*cached_post_bytes += chunk_len; /* write UAF clássico */
CVE-2026-109618 chega ao mesmo destino por outro caminho, através do tratamento de erros de exaustão de memória. Quando memory_limit é excedido, o PHP executa um bailout baseado em longjmp(). Se um OOM ocorrer no meio do streaming RFC1867, antes que as estruturas intermediárias estejam totalmente inicializadas, a rotina de cleanup processa objetos parcialmente inicializados. Os metadados dos bins do ZMM ficam inconsistentes; alocações subsequentes podem receber chunks sobrepostos. Ambas as CVE resultam em um caminho de escrita válido em memória liberada, diferindo apenas no gatilho.
4. Versões oficiais corrigidas e ramos EOL
| Ramo PHP | Vulnerável | Primeira versão segura | Ação |
|---|---|---|---|
| PHP 8.5 | < 8.5.12 | 8.5.12 | atualizar imediatamente |
| PHP 8.4 | < 8.4.27 | 8.4.27 | atualizar imediatamente |
| PHP 8.3 | < 8.3.36 | 8.3.36 | atualizar imediatamente |
| PHP 8.2 | < 8.2.35 | 8.2.35 | atualizar no suporte de segurança |
| PHP 8.1 / 8.0 / 7.4 e anteriores | todas | sem release upstream | backport da distribuição ou workaround |
Para PHP 8.1 e anteriores não há mais releases upstream. Use backports do Ubuntu Pro, Debian LTS, CloudLinux ou RHEL, ou aplique a mitigação temporária até lá.
5. Ações imediatas para operadores
5.1 Verificar runtime e pacotes
php -v
php-fpm -v
dpkg -l | grep -E '^ii\s+php[0-9.]*-(fpm|cli|common)'
rpm -qa | grep -i '^php'
zgrep -E "CVE-2026-10961[89]" /usr/share/doc/php*/changelog* 2>/dev/null
php-fpm -t
5.2 Mitigação imediata sem downtime
; /etc/php/8.x/fpm/php.ini
session.upload_progress.enabled = Off
; /etc/php/8.x/fpm/pool.d/www.conf
php_admin_flag[session.upload_progress.enabled] = off
sudo systemctl reload php8.3-fpm
sudo kill -USR2 "$(cat /var/run/php-fpm.pid)"
php -r 'echo "upload_progress=", ini_get("session.upload_progress.enabled"), PHP_EOL;'
Essa opção desativa apenas o callback legado de barra de progresso. Uploads normais via $_FILES, move_uploaded_file() e APIs modernas do navegador funcionam inalterados.
5.3 Indicadores de comprometimento
find /var/www -type f -mtime -2 -ls 2>/dev/null | head -50
ps -eo pid,user,lstart,cmd | awk '$2=="www-data"||$2=="nginx"'
ss -tpn | grep ESTAB | grep -E 'www-data|php-fpm'
6. Perguntas frequentes
P: session.upload_progress.enabled = Off quebra uploads normais?
Não. A diretiva controla apenas o callback de progresso introduzido no PHP 5.4. Armazenamento de arquivos, caminhos temporários e $_FILES não são afetados.
P: Um WAF é suficiente? Não. Payloads reais frequentemente ficam abaixo de 500 bytes, escapando de limites de tamanho. Além disso, a requisição é parseada antes que roteamento e regras de WAF em nível de aplicação tenham efeito. A única solução robusta é o patch ou a desativação no nível da engine.
P: O que muda em 8.5.12? A vida útil dos ponteiros globais RFC1867 e a ordem das rotinas de cleanup no bailout OOM foram corrigidas. 8.4.27, 8.3.36 e 8.2.35 contêm a mesma correção como backport.
7. Referências
- php.net Security Releases de 21 de outubro de 2026
- GitHub Security Advisory GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
- GitHub Security Advisory GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
- Ubuntu Security Tracker, Debian Security Tracker, Red Hat CVE Database
- Ferramenta de diagnóstico:
https://php2shell.run/checker/
Este documento serve exclusivamente à defesa e remediação. Código de exploit não é fornecido. Alterações em produção devem seguir change management controlado.