> O PHP agendou release de segurança para **21/10/2026 às 14:00 UTC (11:00 BRT)** corrigindo **CVE-2026-109618** e **CVE-2026-109619** (CVSS 9.2, RCE pré-autenticação).
> Este documento é **paliativo, não correção**. Pacotes de distro e painel (Sury, Remi, EA4, CloudLinux alt-php, Plesk) chegam horas ou dias depois do release oficial. Mantenha a mitigação até o pacote corrigido estar instalado **e** o PHP-FPM/LSAPI reiniciado.
## 1. O que se sabe (e o que não se sabe)
- **Componente apontado:** handler de `session.upload_progress` (`php_session_rfc1867_callback`, `ext/session/session.c`), use-after-free no heap, disparado por POST `multipart/form-data` contendo o campo `PHP_SESSION_UPLOAD_PROGRESS`. O recurso vem **ligado por padrão** desde o PHP 5.4.
- **O PHP não confirmou oficialmente** o componente. A ligação com `upload_progress` vem de vazamento e análise de pesquisadores.
- Um pesquisador afirma que são **dois caminhos**: um no `upload_progress` e outro no próprio parser multipart, que roda em qualquer POST multipart independente desta configuração. Ou seja, **desligar `upload_progress` pode fechar só um dos dois**.
- **Versões corrigidas** segundo pesquisadores (confirmar no anúncio do php.net): **8.2.35, 8.3.36, 8.4.27, 8.5.12**.
- **8.1 e anteriores são EOL**: sem correção oficial do PHP.
php -i | grep -i session.use_only_cookies # deve ser 1 (padrão)
php --ini # quais arquivos ini foram carregados
### 3.2 Inventário de todas as versões instaladas
for bin in /usr/bin/php /usr/bin/php[0-9]* /usr/local/bin/php \
printf '%-45s %-8s upload_progress=%s\n' "$bin" \
"$("$bin" -r 'echo PHP_VERSION;' 2>/dev/null)" \
"$("$bin" -r 'var_export(ini_get("session.upload_progress.enabled"));' 2>/dev/null)"
Leitura: `'1'` = ligado; `'0'` ou `''` = desligado; `false` = diretiva inexistente (PHP /dev/null | grep -i '^session.upload_progress.enabled'
Ajuste os caminhos de docroot ao seu ambiente (addon domains no cPanel podem ficar fora de `public_html`; Plesk fica em `/var/www/vhosts`).
grep -rIl --include='*.php' --include='*.js' --include='*.html' --include='*.tpl' --include='*.twig' \
-e 'PHP_SESSION_UPLOAD_PROGRESS' -e 'upload_progress' \
/ /*/public_html /var/www 2>/dev/null | head -50
Hits em `vendor/` ou variáveis com nome genérico podem ser falso positivo. Se nada relevante aparecer, desligar não tem impacto funcional.
### 3.4 Overrides de cliente que religariam o recurso
--include='.user.ini' --include='.htaccess' --include='php.ini' \
Overrides específicos de painel estão nas seções 5 e 6.
## Variável usada em todos os blocos abaixo
Defina uma vez no shell antes de rodar os comandos das seções 4 a 6:
CONF='; php2shell (CVE-2026-109618/109619) - mitigacao temporaria, reavaliar apos patch
O prefixo `zz-`/`99-zz-` no nome do arquivo garante que ele seja lido por último no diretório de scan e vença qualquer ini anterior.
### 4.1 Debian/Ubuntu (pacotes da distro ou ondrej/sury)
for d in /etc/php/*/{fpm,apache2,cgi,cli}/conf.d; do
[ -d "$d" ] && printf '%s' "$CONF" > "$d/99-zz-php2shell.ini"
php-fpm"$ver" -t && systemctl reload "php$ver-fpm"
systemctl reload apache2 2>/dev/null # só se usar mod_php (libapache2-mod-php)
printf '%s' "$CONF" > /etc/php.d/99-zz-php2shell.ini
systemctl reload httpd 2>/dev/null # só se usar mod_php
printf '%s' "$CONF" > "$d/99-zz-php2shell.ini"
### 4.3 Travar contra override do cliente (recomendado em multi-tenant)
for f in /etc/php/*/fpm/pool.d/*.conf /etc/php-fpm.d/*.conf /etc/opt/remi/php*/php-fpm.d/*.conf; do
grep -q 'session.upload_progress.enabled' "$f" && continue
cp -a "$f" "$f.bak-php2shell" # .bak não termina em .conf => não é carregado
echo 'php_admin_flag[session.upload_progress.enabled] = off' >> "$f"
⚠️ O `echo >>` cai na **última** seção `[pool]` do arquivo. Se um arquivo tiver vários pools, adicione a linha manualmente em cada um. Depois rode `php-fpmX.Y -t` e recarregue o FPM.
**mod_php (Apache):** crie um conf global (Debian: `/etc/apache2/conf-available/zz-php2shell.conf` + `a2enconf zz-php2shell`; RHEL: `/etc/httpd/conf.d/zz-php2shell.conf`):
php_admin_flag session.upload_progress.enabled off
php_admin_flag session.upload_progress.enabled off
`apachectl -t && systemctl reload apache2` (ou `httpd`).
### 4.4 Containers (imagem oficial `php`)
Drop-in em `/usr/local/etc/php/conf.d/zz-php2shell.ini` via Dockerfile ou bind-mount, depois rebuild/restart do container. `docker exec php -i | grep upload_progress` para conferir.
Via WHM: **MultiPHP INI Editor → Editor Mode →** cada versão → adicionar `session.upload_progress.enabled = 0`.
Ou por drop-in (não pertence a nenhum RPM, sobrevive a update e é lido depois do `php.ini`):
for d in /opt/cpanel/ea-php*/root/etc/php.d; do
printf '%s' "$CONF" > "$d/zz-php2shell.ini"
### 5.2 Travar no PHP-FPM (padrão do cPanel)
Y=/var/cpanel/ApachePHPFPM/system_pool_defaults.yaml
if [ -f "$Y" ]; then cp -a "$Y" "$Y.bak-php2shell"; else echo '---' > "$Y"; fi
grep -q 'session.upload_progress.enabled' "$Y" || \
echo "php_admin_flag_session_upload_progress_enabled: { name: 'php_admin_flag[session.upload_progress.enabled]', value: 'off' }" >> "$Y"
/usr/local/cpanel/scripts/php_fpm_config --rebuild
/usr/local/cpanel/scripts/restartsrv_apache_php_fpm
/usr/local/cpanel/scripts/restartsrv_httpd
O `--rebuild` **não reinicia** o FPM sozinho, por isso o `restartsrv_apache_php_fpm`.
Conferir pools que ficaram **sem** a linha:
grep -c 'session.upload_progress.enabled' /opt/cpanel/ea-php*/root/etc/php-fpm.d/*.conf | grep ':0$'
Overrides por domínio (YAML de domínio tem precedência sobre o system default):
grep -l 'upload_progress' /var/cpanel/userdata/*/*.php-fpm.yaml 2>/dev/null
⚠️ **Não** use o `rm -rf /var/cpanel/userdata/*/*.php-fpm.yaml` que aparece em tutoriais: apaga customizações de pool de todos os domínios.
### 5.3 CloudLinux (alt-php / PHP Selector, CageFS, mod_lsapi)
alt-php **não** lê o `php.d` do ea-php. Edite o `php.ini` de cada versão e reconstrua:
sed -i '/php2shell/,+1d' "$ini" # idempotente: remove aplicação anterior
- Versões antigas (alt-php44 a 53) ignoram a diretiva sem erro.
- Se o "Native" do Selector for ea-php, o 5.1 cobre. Em CloudLinux, rode `cagefsctl --force-update` depois do 5.1 para o CageFS enxergar a mudança.
- A CloudLinux também suporta `/etc/cl.selector/global_php.ini` para aplicar em todas as versões de uma vez. Confira a sintaxe na documentação da sua versão antes de usar.
- Configs por usuário do Selector podem religar o recurso:
grep -rl 'upload_progress' /var/cagefs/*/*/etc/cl.php.d/ / /*/.cl.selector/ 2>/dev/null
| PHP-FPM | `/usr/local/cpanel/scripts/restartsrv_apache_php_fpm` |
| mod_lsapi / suPHP / CGI | `/usr/local/cpanel/scripts/restartsrv_httpd` |
| LiteSpeed Enterprise | `/usr/local/lsws/bin/lswsctrl restart` (lsphp em daemon mode segura o ini antigo até reiniciar) |
### 6.1 PHP do Plesk (`/opt/plesk/php/X.Y`)
printf '%s' "$CONF" > "$d/zz-php2shell.ini"
systemctl reload 'plesk-php*-fpm.service'
systemctl reload apache2 2>/dev/null || systemctl reload httpd # recicla processos FastCGI
Se a validação HTTP (seção 7) ainda mostrar `'1'` em algum site FPM, troque `reload` por `restart` no serviço daquela versão.
Se preferir editar o `php.ini` principal da versão em vez de drop-in, propague para os domínios com:
### 6.2 PHP do sistema operacional (handler "OS vendor")
grep -l 'upload_progress' /var/www/vhosts/system/*/etc/php.ini /opt/plesk/php/*/etc/php-fpm.d/*.conf 2>/dev/null
Corrigir pelo painel (**Websites & Domains → PHP Settings → Additional configuration directives**) ou por CLI:
plesk db dump psa > /root/psa.$(date +%F-%H%M).sql # backup antes, como a KB da Plesk recomenda
echo 'session.upload_progress.enabled = 0' > /root/php2shell.ini
plesk bin site --update-php-settings DOMINIO.com.br -additional-settings /root/php2shell.ini
⚠️ Teste em **um** domínio antes de rodar em lote: confirme se o comando preserva ou substitui as diretivas adicionais que o domínio já tinha.
Se usar alt-php ou CageFS, aplique também a seção 5.3. Com CageFS, o domínio pode estar preso ao ini global do servidor, o que aqui joga a favor.
Teste **pelo menos um site por combinação versão × handler** (FPM, LSAPI, FastCGI, mod_php).
DOCROOT=/ /USUARIO/public_html # Plesk: /var/www/vhosts/$DOM/httpdocs
<?php header('Content-Type: text/plain');
echo PHP_VERSION, ' ', PHP_SAPI, ' upload_progress=';
var_export(ini_get('session.upload_progress.enabled')); echo "\n";
chown "$OWNER" "$DOCROOT/$P"; chmod 644 "$DOCROOT/$P" # suPHP/FPM por usuário recusam arquivo de root
Esperado: `upload_progress='0'` ou `upload_progress=''`. Se vier `'1'`, existe override (seções 3.4, 5.2, 5.3, 6.3) ou o serviço não foi recarregado.
Útil onde o cliente pode ter religado o recurso por `.user.ini`, ou onde você ainda não conseguiu aplicar o ini.
**ModSecurity**: bloquear o campo que aciona o handler (requer `SecRequestBodyAccess On`):
SecRule ARGS_POST_NAMES "@rx (?i)^PHP_SESSION_UPLOAD_PROGRESS$" \
"id:91021,phase:2,t:none,deny,status:403,log,msg:'php2shell: campo PHP_SESSION_UPLOAD_PROGRESS em POST'"
- Se algum ambiente customizou `session.upload_progress.name`, ajuste o nome.
- **Não cobre** o segundo caminho suspeito (parser multipart).
- Confirme que a regra de `MULTIPART_STRICT_ERROR` do `modsecurity.conf` recomendado (id 200003) está ativa: bloqueia corpo multipart malformado. Pode ajudar se o exploit depender disso, o que não está confirmado.
- cPanel: **WHM → ModSecurity Tools → Rules List → Add Rule**. Plesk: configurações do **Web Application Firewall (ModSecurity)** ou arquivo de regras custom.
- Imunify360, Cloudflare e outros WAFs comerciais costumam publicar virtual patch nesses casos. Verifique com o fornecedor.
1. **Atualizar** quando o pacote corrigido sair:
| Debian/Ubuntu | `apt update && apt upgrade` |
| cPanel (EA4) | `dnf upgrade 'ea-php*'` (`yum` em EL7/CL7) |
| CloudLinux | `dnf upgrade 'alt-php*'` |
| Plesk | `dnf upgrade 'plesk-php*'` / `apt upgrade`, ou Plesk Installer |
2. **Reiniciar** FPM / LSAPI / LiteSpeed / Apache. Processo antigo continua vulnerável até reiniciar.
3. **Conferir** versões com o inventário (3.2) e o probe HTTP (7).
4. **EOL (≤ 8.1):** sem correção oficial. Migrar, isolar, ou checar backport do fornecedor (CloudLinux alt-php, TuxCare, Ubuntu ESM, RHEL). Até lá, mantenha mitigação + WAF.
5. **Manter desligado?** O próprio manual do PHP recomenda desligar `session.upload_progress` quando não se usa barra de progresso. Se a seção 3.3 não achou uso, considere manter permanente.
rm -f /etc/php/*/*/conf.d/99-zz-php2shell.ini \
/etc/opt/remi/php*/php.d/99-zz-php2shell.ini \
/opt/cpanel/ea-php*/root/etc/php.d/zz-php2shell.ini \
/opt/plesk/php/*/etc/php.d/zz-php2shell.ini
sed -i '/php2shell/,+1d' /opt/alt/php*/etc/php.ini && cagefsctl --rebuild-alt-php-ini
# cPanel FPM: remover a linha do system_pool_defaults.yaml e rodar
# /usr/local/cpanel/scripts/php_fpm_config --rebuild && /usr/local/cpanel/scripts/restartsrv_apache_php_fpm
# Pools FPM sem painel: restaurar *.bak-php2shell ou remover a linha php_admin_flag
# mod_php: remover zz-php2shell.conf (a2disconf no Debian)
Depois, recarregar os serviços como nas seções 4 a 6.
- [ ] Inventário de versões e SAPIs (3.2)
- [ ] Uso do recurso verificado nas aplicações (3.3)
- [ ] Drop-in / ini aplicado em **todas** as versões
- [ ] Trava via `php_admin_flag` (multi-tenant)
- [ ] FPM / LSAPI / LiteSpeed / Apache recarregados
- [ ] Validação HTTP por combinação versão × handler
- [ ] Overrides de cliente auditados (`.user.ini`, `.htaccess`, YAML cPanel, Selector, Plesk)
- [ ] Patch aplicado assim que disponível + restart dos serviços
- [ ] Decisão registrada: manter desligado ou rollback
- Anúncio PHP:
- Manual `session.upload_progress`:
- Patchstack:
- Phoenix Security (dois caminhos suspeitos):
- Pesquisa independente (versões afetadas/corrigidas):
- cPanel, php.ini com PHP-FPM:
- Plesk, alterar PHP de domínios via CLI:
The full story
This article is one source in a clustered incident — the cluster page carries the summary, timeline and every other outlet covering it.
