Saltar para o conteúdo
folhas.io
secure by design para produtos ligados· Artigos

Artigos

PHP2Shell e Node.js: o que pedem a quem fabrica aparelhos

A 21 de outubro de 2026, o PHP e o Node.js publicaram correções de segurança graves. Quem fabrica aparelhos com painel web, gateways ou executáveis Node tem três perguntas para responder: se o produto traz o componente, se há dever de reporte ao abrigo do artigo 14.º e como chega a correção às unidades que já estão no terreno.

Publicado

A 21 de outubro de 2026, dois runtimes que muitos produtos ligados trazem lá dentro publicaram correções de segurança no mesmo dia. O PHP corrigiu duas vulnerabilidades críticas, conhecidas como PHP2Shell, que podem permitir execução remota de código sem autenticação. O Node.js corrigiu dez, entre elas uma escrita fora dos limites no descodificador Brotli que, segundo o projeto, permite execução remota de código.

Este texto olha para o caso do lado de quem fabrica aparelhos com um destes runtimes embebido (um painel de gestão web, um gateway, uma aplicação Node empacotada num executável) e segue as três perguntas que ele levanta ao mesmo tempo: se o componente está no produto, se há dever de reporte ao abrigo do artigo 14.º do CRA, e como chega a correção às unidades já vendidas.

O que aconteceu a 21 de outubro

O PHP publicou as versões 8.5.12, 8.4.27, 8.3.36 e 8.2.35, que corrigem a CVE-2026-109618 e a CVE-2026-109619, depois de as ter pré-anunciado na véspera. As falhas foram descobertas e reportadas por investigadores da Calif, da Wiz e da OpenAI, e o projeto, que atribuiu as duas CVE, deu a cada uma 9,2 em CVSS v4.0. O NVD avalia-as noutro sistema de pontuação, o CVSS v3.1: 9,8 para a CVE-2026-109618, o valor que alguns fabricantes usam nos seus avisos, e 8,1 para a CVE-2026-109619. As distribuições Linux e os fornecedores de suporte alargado receberam as correções antes do lançamento.

Segundo o aviso do php.net, estão em risco todas as instalações de PHP que servem pedidos web, incluindo PHP-FPM, Apache com mod_php, php-cgi, FrankenPHP e LiteSpeed. Os advisories técnicos do projeto validam a execução remota de código em mod_php nas duas falhas, sem depender da aplicação. Em PHP-FPM, o advisory da CVE-2026-109619 validou-a também, por um caminho que depende de uma operação adequada da aplicação; o da CVE-2026-109618 conclui, pela análise do código, que o PHP-FPM é suscetível, mas sem exploit completo demonstrado. O PHP 8.1 e anteriores já não recebem versões novas, mas, dada a gravidade, a equipa de segurança publicou correções mínimas para os ramos 7.4, 8.0 e 8.1, em código-fonte e sem número de versão novo.

No mesmo dia, o Node.js publicou as versões 22.23.4, 24.22.1 e 26.12.1, com dez CVE corrigidas. O projeto classifica as falhas por severidade, sem pontuação CVSS, e a mais alta em cada linha é «high». Uma das quatro de severidade alta é a CVE-2026-111497, a escrita fora dos limites no descodificador Brotli, reportada pela OpenAI Codex Security (Khai Tran e Sylvie Mayer) e corrigida, segundo o aviso do Node.js, por Matteo Collina e Antoine du Hamel. A falha está na própria biblioteca Brotli da Google, nas versões 1.0.3 a 1.2.0, e a Google publicou a 21 out as versões corrigidas 1.2.1, 1.1.1 e 1.0.10. O registo CVE da biblioteca, atribuído pela Google, dá-lhe 9,2 em CVSS v4.0. Entre as restantes há dois contornos, de severidade alta, à verificação do nome de anfitrião nos certificados TLS, e a CVE-2026-106074, de severidade média, que afeta snapshots de arranque e executáveis SEA e volta a aparecer mais abaixo. O Node.js 20, em fim de vida desde 30 abr 2026, não recebeu correção, e o projeto lembra que as versões em fim de vida ficam sempre afetadas quando há um lançamento de segurança.

Sobre a exploração, as fontes divergem, e cada afirmação tem data. No alerta de 21 out 2026, a CISA escreveu que ainda não tinha observado exploração do PHP2Shell. No mesmo dia, a Amazon Threat Intelligence disse ter registado nos seus honeypots uma tentativa de exploração datada de 17 out, quatro dias antes da divulgação, e outras na madrugada de 21 out, ainda sob embargo, admitindo não saber se alguma teria tido êxito em sistemas reais. Depois do lançamento, viu surgir em poucas horas novas provas de conceito, usadas quase de imediato contra os seus sensores, e descreveu tentativas de exploração em larga escala. A Cloudflare disse ter observado tráfego de ataque contra os seus clientes. A 23 out 2026, nenhuma das duas CVE do PHP constava do catálogo KEV da CISA.

Para as falhas do Node.js não se conhece exploração ativa: também não estavam no KEV nessa data. Há, porém, prova de conceito pública para a CVE-2026-111497, e a 22 out a Imperva demonstrou execução de código numa imagem oficial do Node.js 24.22.0 para Linux arm64, o que por si só não indica exploração ativa. A avaliação SSVC da CISA no registo dessa CVE não serve aqui de referência: a 23 out passou de «none» a «poc» e, na revisão seguinte do mesmo dia, voltou a «none».

LinhaVersão corrigida a 21 out 2026Fim de suporte do projeto
PHP 7.3 e anterioresnenhuma6 dez 2021 ou antes
PHP 7.4, 8.0 e 8.1nenhuma; só correções mínimas em código-fonte28 nov 2022, 26 nov 2023 e 31 dez 2025
PHP 8.28.2.3531 dez 2026
PHP 8.38.3.3631 dez 2027
PHP 8.48.4.2731 dez 2028
PHP 8.58.5.1231 dez 2029
Node.js 20 e 25nenhuma30 abr 2026 e 1 jun 2026
Node.js 2222.23.430 abr 2027
Node.js 2424.22.130 abr 2028
Node.js 2626.12.130 abr 2029

As datas do Node.js são as do calendário do projeto, que avisa que podem mudar.

Primeira pergunta: o componente está no produto?

A CISA avisou que o PHP é muitas vezes componente de outro software e que a sua presença pode não ser diretamente observável. O NCSC-NL, o centro nacional de cibersegurança dos Países Baixos, foi mais concreto: o PHP vem também embebido em appliances, equipamentos de rede e interfaces de gestão, onde o administrador pode não conseguir atualizá-lo diretamente. Para o cliente de um aparelho, a pergunta pode não ter resposta à vista; quem a pode dar é o fabricante.

Com uma SBOM gerada no build (o artigo 01 explica porquê), a resposta obtém-se consultando o inventário, sem abrir nenhum aparelho. Neste caso, cada entrada precisa de mais do que o nome: a versão exata; as correções aplicadas, porque as correções mínimas para ramos em fim de vida não trazem número de versão novo (no 7.4, o binário compilado a partir delas identifica-se até como 7.4.31-dev, abaixo da última versão oficial, a 7.4.33); a forma como o runtime corre (no PHP, mod_php, PHP-FPM ou php-cgi; no Node.js, o runtime do sistema ou um executável SEA); e se o código vulnerável é alcançável no produto. Para a CVE-2026-111497, a entrada a procurar é também a biblioteca Brotli, que pode estar no firmware sem o Node.js. O registo CVE situa a falha no descodificador: o que importa é onde o produto descomprime dados Brotli de origem não confiável, como respostas HTTP comprimidas ou corpos de pedido descomprimidos por middleware.

A resposta pública é um estado por produto e versão (afetado, não afetado, corrigido ou em investigação), de preferência em formato legível por máquina, como o VEX. A lista que o NCSC-NL abriu a 21 out, e que o aviso 2026-018 do CERT-EU e a declaração conjunta de 21 out recomendam consultar, segue esta lógica: é um inventário em SPDX, trata cada entrada como pista de investigação e só a dá como corrigida ou não afetada com fonte do projeto ou do fabricante. O aviso que o fabricante publica é o que permite fechar a sua linha.

Também uma avaliação de risco mínimo tem trabalho por trás. A Synology confirmou impacto em dez pacotes que dependem do PHP e que se corrigem atualizando o PHP pelo Package Center. Sobre o componente PHP de uso interno do DSM, concluiu que não tem superfície de ataque exposta e avaliou o risco como mínimo, mas, mesmo assim, agendou a correção para uma versão posterior, para que os resultados dos scanners de vulnerabilidades e o estado de conformidade fiquem coerentes.

Vários dos aparelhos com PHP embebido que aparecem nos avisos destes dias (firewalls, appliances de rede, sistemas de gestão de rede) coincidem com categorias de produtos importantes do Anexo III do CRA: as firewalls na classe II e os sistemas de gestão de rede na classe I, conforme as descrições técnicas do Regulamento de Execução (UE) 2025/2392, quando essa é a funcionalidade principal do produto (art. 7.º, n.º 1). Nessas categorias, a avaliação da conformidade pode exigir terceiros: na classe I, quando não se aplicam na íntegra normas harmonizadas, especificações comuns ou certificação europeia; na classe II, sempre (art. 32.º, n.os 2 e 3), como mostra o artigo 03.

Os painéis de gestão com php-cgi

O aviso do php.net inclui expressamente o php-cgi entre as instalações em risco. É a forma que a documentação do lighttpd usa para ligar o PHP a esse servidor web: o servidor arranca o executável /usr/bin/php-cgi como processos FastCGI persistentes, que tratam pedidos sucessivos. No OpenWrt, o PHP não faz parte da imagem de origem: é um pacote opcional do feed de pacotes (php8-cgi), e a configuração de origem do servidor uHTTPd traz comentada, e portanto desativada, a linha que entrega os ficheiros .php ao php-cgi. Quem acrescenta um painel PHP à sua imagem herda esta escolha.

Os dois advisories técnicos do PHP analisam mod_php, PHP-FPM, LSAPI e FrankenPHP e não tratam o php-cgi à parte. Sem essa análise, a posição prudente é tratá-lo como afetado, em qualquer modo em que corra, e atualizar. Até a atualização chegar ao terreno, a interface de gestão deve ficar restrita à rede de administração: o CERT-EU e a declaração conjunta de 21 out recomendam ponderar o isolamento das aplicações expostas em relação à rede pública, e a Netgate lembra que, por omissão, a interface web do pfSense só é acessível a partir da rede local. A mesma Netgate pede aos utilizadores do portal cativo, por natureza exposto a clientes não confiáveis, que atualizem o PHP quanto antes. Restringir a interface de gestão não protege as funções que o aparelho serve por PHP a redes não confiáveis.

Uma nota para quem limita a memória do processo PHP no script de arranque, com ulimit por exemplo: o advisory da CVE-2026-109618 desaconselha RLIMIT_AS e RLIMIT_DATA, porque podem desencadear a própria falha, e diz que um limite de contentor ou de cgroup não impede com garantia a falha de alocação nem é mitigação completa; o aviso do php.net trata-o como fronteira de disponibilidade. As medidas temporárias do PHP (memory_limit=-1 fixado de forma que as aplicações não o alterem, post_max_size baixo, session.upload_progress.enabled=0 e, no PHP 8.5, fatal_error_backtraces=0, com reinício de todos os workers) reduzem a exposição a caminhos concretos, e o próprio projeto diz que só a atualização resolve por completo.

Segunda pergunta: há dever de reporte?

Desde 11 set 2026 (art. 71.º, n.º 2), o artigo 14.º obriga o fabricante a notificar as vulnerabilidades ativamente exploradas contidas no seu produto, também nos produtos colocados no mercado antes de 11 dez 2027 (art. 69.º, n.º 3). A declaração conjunta de 21 out da Comissão, da ENISA, do CERT-EU, da Europol e da rede de CSIRT lembrou, a propósito do PHP2Shell, que essa notificação se faz pela plataforma única de comunicação de informações da ENISA. Os prazos estão no artigo sobre o reporte de 24h e 72h.

A pergunta própria deste caso é outra: a exploração de um componente noutros sistemas obriga, por si só, quem o integra a notificar? As orientações da Comissão de 27 jul 2026, C(2026) 5252, respondem no ponto 218, para o qual remete a FAQ da ENISA sobre a plataforma (pergunta 14), a par da secção 5.4 das FAQ da Comissão sobre a aplicação do CRA, de 3 dez 2025: o fabricante só tem de notificar vulnerabilidades ativamente exploradas contidas no seu produto. Se a vulnerabilidade de um componente de terceiros está a ser explorada no produto, notifica. Se a vulnerabilidade não pode ser explorada no produto (por exemplo, porque o código vulnerável não é alcançável), ou se não houve exploração nele, não fica sujeita a reporte obrigatório para esse fabricante.

As FAQ de 2025 são mais amplas: só excluem o caso em que a vulnerabilidade não pode ser explorada no produto, e a definição do art. 3.º, ponto 42, fala de exploração num sistema, sem dizer qual. As orientações são o texto mais recente e mais específico; nenhum dos dois é vinculativo.

Na prática, as tentativas de exploração em larga escala contra servidores PHP são um gatilho de avaliação, não a tomada de conhecimento. Segundo as mesmas orientações, o fabricante toma conhecimento quando, depois de uma avaliação inicial imediata, tem um grau razoável de certeza de que uma vulnerabilidade do seu produto está a ser ativamente explorada, e o sinal pode chegar de clientes, de autoridades ou da comunicação social. As perguntas da triagem são concretas: em que produtos e versões o PHP serve pedidos, se a interface fica acessível a partir de redes não confiáveis nas instalações conhecidas, e se a telemetria, os registos ou os relatos de clientes mostram sinais de exploração em unidades do próprio produto. Se a triagem concluir, com grau razoável de certeza, que há exploração ativa em unidades do produto, é essa hora que abre o prazo de 24 horas da notificação de alerta precoce; convém registá-la, e registar também a conclusão quando é negativa. Do lado do Node.js, a 23 out 2026 não havia exploração ativa conhecida que pusesse esta pergunta, mas a prova de conceito pública para a CVE-2026-111497 justifica manter a triagem aberta nos produtos que descomprimem dados Brotli de origem não confiável.

Há uma assimetria que pesa no parque instalado. Segundo as orientações (secção 9.1), o reporte aplica-se aos produtos colocados no mercado antes de 11 dez 2027 e continua depois de terminado o período de suporte, ao passo que as obrigações de tratamento de vulnerabilidades do Anexo I, Parte II, não se aplicam a esses produtos. Um aparelho vendido hoje pode, por isso, ter dever de reporte sem ter, pelo CRA, dever de correção. Depois de tomar conhecimento, o fabricante tem ainda de informar os utilizadores afetados e, se for caso disso, todos os utilizadores, da vulnerabilidade e, se necessário, das medidas de atenuação e corretivas que podem tomar (art. 14.º, n.º 8). Segundo as orientações (ponto 220), este dever aplica-se de forma proporcional ao risco e não obriga a tornar a informação pública.

Para os casos sem reporte obrigatório, o ponto 218 admite a notificação voluntária do artigo 15.º, mas a plataforma ainda não a recebe: segundo a FAQ da ENISA, chega numa fase futura.

Nota de rigor. As orientações C(2026) 5252 não são vinculativas: a própria Comissão lembra que só o Tribunal de Justiça da União Europeia pode interpretar o CRA com autoridade. Até 23 out 2026 não encontrámos posição oficial sobre este caso concreto. O que fica acima é a leitura das orientações aplicada a ele e não substitui a análise jurídica de cada produto.

Terceira pergunta: como chega a correção ao terreno?

A mesma CVE corrige-se por caminhos diferentes consoante a forma como o runtime entrou no produto, e é a SBOM que diz qual se aplica.

Quatro caminhos pelos quais a correção de um runtime chega ao aparelho, consoante a forma como entrou no produto. Como pacote do sistema, vindo de uma distribuição ou feed: atualizar o pacote, reconstruir a imagem e enviá-la, porque um pacote corrigido ainda não é firmware no terreno. Compilado na imagem de firmware: atualizar a receita, reconstruir e enviar por OTA ou localmente; num ramo em fim de vida não há versão corrigida. Dentro de um executável SEA do Node.js: reconstruir com o Node.js corrigido, refazer os snapshots e redistribuir, porque atualizar o Node.js do sistema não chega. Como aplicação à parte ou contentor: atualizar a aplicação pelo canal próprio sem mudar o firmware, o que pressupõe um canal de aplicações no aparelho. Em todos, a SBOM diz qual caminho se aplica e a correção só conta quando chega a cada unidade.
O trabalho que falta depois de o projeto publicar a correção depende de como o runtime entrou no produto, e essa informação tem de estar registada antes de ser precisa.

Quando o runtime vem de uma distribuição ou de um feed de pacotes, a correção do projeto chega primeiro ao pacote, e no PHP as distribuições tiveram-na antes do lançamento. Isso ainda não é firmware nas unidades. No OpenWrt, a receita do PHP no ramo principal do feed de pacotes já está na 8.4.27; quem constrói sobre ela tem de reconstruir a imagem de cada produto e enviá-la. Há também casos em que a correção do componente contorna o canal normal do produto: a Netgate publicou pacotes PHP corrigidos para o pfSense, mas, nas instalações existentes, essa atualização não se faz pela interface web, só pela linha de comandos (uma instalação nova, ou uma atualização para uma versão corrente, já os traz). No Brotli, a correção pode chegar por dois lados. O Node.js traz por omissão a sua própria cópia da biblioteca, mas pode ser compilado ligado à do sistema (opção --shared-brotli), e nesse caso a correção chega com a atualização dessa biblioteca. Como a falha está na biblioteca, o registo CVE pede a atualização de qualquer biblioteca ou binário Brotli das versões afetadas, o que inclui um firmware que use o Brotli sem Node.js.

Se o runtime é compilado dentro da imagem de firmware, a correção só chega com uma imagem nova, distribuída por OTA ou localmente. Nos ramos em fim de vida o trabalho cresce: para o PHP 7.4, 8.0 e 8.1 há só as correções mínimas em código-fonte; para os ramos anteriores e para o Node.js 20, nem isso. A tabela acima mostra ainda um problema que o artigo sobre o período de suporte desenvolve: nenhuma linha atual do PHP ou do Node.js é suportada pelo projeto até ao fim de um período de suporte de cinco anos que comece em dezembro de 2027.

Um executável SEA do Node.js é o próprio binário do Node com a aplicação injetada, e a documentação exige que o blob da aplicação seja gerado pela mesma versão do binário em que é injetado. Daí deduzimos que atualizar o Node.js do sistema não corrige um SEA já distribuído: é preciso reconstruí-lo com a 22.23.4, a 24.22.1 ou a 26.12.1 e redistribuí-lo. Os snapshots de arranque seguem a mesma lógica, porque o Node recusa carregar um snapshot gerado por um binário de versão diferente, e têm de ser regenerados com o binário corrigido. A CVE-2026-106074 dá uma razão a mais: as caches de entropia de crypto.randomUUID() e crypto.randomInt() ficavam gravadas nos snapshots e nos SEA, e todos os processos arrancados a partir deles repetiam os mesmos valores. Se esses valores serviram para identificadores de unidade ou para segredos, convém revê-los; a recomendação é nossa, porque o Node.js não publicou orientação sobre os valores já gerados.

O caminho encurta quando o runtime corre como aplicação separada do firmware. Nos dispositivos com u-OS, a Weidmüller passou o Node-RED de serviço nativo do sistema para uma aplicação em contentor, o que permite, segundo o próprio fabricante, atualizar o Node-RED e o firmware de forma independente.

O mesmo lançamento do Node.js mexeu também na confiança TLS: bloqueia, com uma lista compilada no binário, oito certificados intermédios da eMudhra cujas chaves privadas foram dadas como comprometidas, e atualiza a loja de raízes embebida para a do NSS 3.131.1. Um aparelho com loja de raízes própria precisa de caminho de atualização também para ela. O incidente da eMudhra, e o que a mesma semana trouxe para o kernel Linux e para o Python, estão no artigo 10.

Quanto ao que o CRA exige aqui, as datas contam. A partir de 11 dez 2027, para os produtos colocados no mercado a partir dessa data (ou modificados substancialmente depois dela, art. 69.º, n.º 2), o Anexo I, Parte II, pede, durante o período de suporte (art. 13.º, n.º 8), que as vulnerabilidades sejam tratadas e corrigidas sem demora em função dos riscos que representam, com atualizações de segurança separadas das funcionais quando tecnicamente viável, mecanismos de distribuição seguros (automáticos, quando aplicável) e atualizações disponibilizadas sem demora e, em regra, sem custo, acompanhadas de avisos aos utilizadores. Para as unidades que já estão no terreno, corrigir é hoje uma decisão técnica e contratual, que o CRA não impõe. Fora do CRA, nos bens de consumo com elementos digitais, a Diretiva (UE) 2019/771 (art. 7.º, n.º 3, transposta em Portugal pelo Decreto-Lei n.º 84/2021) obriga o vendedor a assegurar que o consumidor recebe as atualizações, incluindo as de segurança, necessárias para manter os bens em conformidade durante o período que pode razoavelmente esperar.

O dever de comunicar a montante

O CRA desenha também o sentido inverso. Para os produtos colocados no mercado a partir de 11 dez 2027, o artigo 13.º, n.º 6, obriga o fabricante que identifique uma vulnerabilidade num componente integrado a comunicá-la a quem o mantém e, se desenvolver uma correção, a partilhá-la. As orientações da Comissão (secção 9.2.1) dispensam a comunicação quando o fabricante pode confirmar que o mantenedor já conhece a vulnerabilidade, como acontece com falhas que o próprio projeto publicou, e não exigem que a correção partilhada seja aceite. Para os produtos que hoje estão no mercado nada disto é ainda obrigação, mas partilhar uma correção própria (um backport para um ramo do PHP em fim de vida, por exemplo) é boa prática. Como enviar e receber estas comunicações é o tema do artigo sobre divulgação coordenada.

O que fazer esta semana

Para quem tem produtos com PHP ou Node.js no terreno:

  • Consultar a SBOM de cada produto e versão em campo à procura de PHP (e da forma como corre), de Node.js (do sistema ou num SEA) e da biblioteca Brotli, com a versão exata e as correções aplicadas. Onde não houver SBOM, o manifesto do build é o ponto de partida.
  • Publicar o estado por produto e versão (afetado, não afetado, corrigido ou em investigação) e atualizá-lo à medida que a análise avança.
  • Abrir a triagem do artigo 14.º para os produtos em que o PHP serve pedidos, com dono, critério escrito e a hora de conclusão registada.
  • Preparar as imagens corrigidas: PHP 8.5.12, 8.4.27, 8.3.36 ou 8.2.35; Node.js 22.23.4, 24.22.1 ou 26.12.1; Brotli 1.2.1, 1.1.1 ou 1.0.10 onde a biblioteca estiver presente; SEA e snapshots reconstruídos; loja de raízes, se o aparelho tiver uma própria.
  • Nas imagens novas, seguir também o aviso informativo do PHP de 23 out 2026, que recomenda manter session.upload_progress.enabled=0 até à próxima versão regular, por causa de um vetor adicional que o projeto considera improvável (CVE-2026-115560).
  • Até a atualização chegar, indicar aos clientes as medidas ao seu alcance, a começar por restringir a interface de gestão à rede de administração.
  • Para os produtos com PHP 8.1 ou anterior, ou com Node.js 20, decidir entre migrar de versão, contratar suporte alargado ou manter correções próprias, e deixar a decisão escrita.

Fontes