O php2shell-checker da OpenAI é útil como primeira triagem, mas não comprova que um servidor está seguro. A ferramenta compara a versão do PHP exposta nos cabeçalhos HTTP ou por php -v com limites de correção incorporados ao código. Por isso, um cabeçalho oculto pode resultar em UNKNOWN, enquanto um backport da distribuição pode fazer um servidor corrigido parecer vulnerável.
Comece entendendo os estados do resultado
O repositório oficial da OpenAI informa três estados relevantes. Use-os como sinais de triagem, não como uma avaliação completa da vulnerabilidade.
| Saída | Código de saída | O que ela indica | Próxima ação |
|---|---|---|---|
OK | 0 | Uma branch reconhecida está na versão mínima corrigida ou acima dela | Confirme que o processo do PHP que atende o tráfego web usa essa versão |
VULNERABLE | 1 | A versão detectada é anterior à versão mínima corrigida | Aplique o patch no runtime que atende o site, reinicie os workers e execute as duas verificações novamente |
UNKNOWN | 3 | O verificador não conseguiu confirmar uma versão ou resposta reconhecida | Inspecione o servidor localmente; não considere o resultado como sinal de correção |
| Argumentos inválidos | 2 | O próprio comando não era válido | Corrija o comando e execute-o novamente |
O que a OpenAI disponibilizou
O repositório público do php2shell-checker reúne um script em Node.js, testes e duas skills do Codex: phpcheck-url, para um site acessível pela rede, e phpcheck-server, para um servidor ao qual você tenha acesso. A ferramenta coleta evidências sobre a versão; ela não explora o alvo nem verifica o código da aplicação.
Execute a verificação no modo correto
Verifique uma URL pública
Clone ou baixe o repositório e execute o script Node.js apontando para um site:
node phpcheck.js "https://example.com"
A verificação remota envia uma requisição HTTP HEAD e só recorre a GET quando o servidor retorna 405 ou 501. Ela consulta os cabeçalhos X-Powered-By e Server, não segue redirecionamentos e não analisa o corpo da resposta.
Um CDN, proxy reverso, expose_php=off ou uma configuração personalizada do servidor pode remover a versão do PHP antes que a resposta chegue ao verificador. O resultado VULNERABLE exige correção; já a ausência do cabeçalho precisa ser investigada com evidências do servidor.
Verifique um binário local do PHP
Em uma máquina com PHP instalado, use:
node phpcheck.js --local
Esse comando executa php -v no binário disponível no PATH atual. Isso não comprova que o mesmo binário atende seu site: um único host pode ter instalações separadas para CLI, PHP-FPM, CGI, módulo do Apache, contêiner ou compilação própria.
Depois da verificação local, identifique o runtime conectado ao servidor web. Em uma implantação com contêineres, inspecione o contêiner em execução, e não apenas a tag da imagem. Em um serviço instalado por pacote, confira o pool relevante do PHP-FPM ou o módulo do Apache, além do changelog do pacote fornecido pelo vendor.
Instale e use as skills do Codex
O README oficial instala as duas skills com um único comando do Codex:
$skill-installer install both skills from https://github.com/openai/php2shell-checker
Em seguida, escolha a interface que corresponde ao seu nível de acesso:
$phpcheck-url check https://example.com
$phpcheck-server check the PHP version serving my site
O Codex é opcional. O comando do Node.js continua sendo a interface direta para jobs de CI e hosts mínimos. Para automação, adicione --json; o campo patch_status retorna ok, vulnerable ou unknown, sem exigir que um script interprete texto do terminal.
Verifique o checker baixado
O repositório usa o test runner integrado do Node:
node --test phpcheck.test.js
A suíte testa a CLI com servidores HTTP locais e usa um executável PHP falso nos cenários locais. Segundo o README, ela não exige uma instalação real do PHP nem acesso a um site externo.
Trate UNKNOWN como resultado de depuração
Considere UNKNOWN uma evidência incompleta. O alvo pode ocultar a versão do PHP, usar uma branch não reconhecida, não responder ou executar uma versão prerelease mais recente. Nenhuma dessas situações confirma que a correção está presente.
Um usuário real, @jvr0x, resumiu a limitação desta forma:
“É apenas uma comparação de versões com os limites de 20 de outubro; por isso, cabeçalhos ocultos retornam UNKNOWN.”
O comando remoto enxerga uma resposta HTTP, não o processo que está por trás do proxy reverso. Quando o cabeçalho está oculto, é preciso verificar o servidor, em vez de repetir consultas à URL.
Depois de um resultado UNKNOWN, siga esta sequência:
- Execute
node phpcheck.js --localno host que atende o site. - Identifique se a requisição chega ao PHP-FPM, CGI,
mod_phpdo Apache ou a um contêiner. - Consulte o changelog do pacote fornecido pelo vendor em busca de backports.
- Reinicie os workers relevantes do PHP-FPM ou do Apache depois da atualização.
- Faça a verificação pelo caminho que atende as requisições, e não apenas pelo binário
phppadrão do shell.
Sem acesso SSH, o modo de URL pode ser a única primeira tentativa. Se um host compartilhado ocultar o cabeçalho da versão, o provedor de hospedagem deverá confirmar o runtime que atende as requisições, a revisão do pacote e o status da reinicialização.
A tabela de versões não decide sozinha se o patch foi aplicado
O checker considera PHP 8.5.12, 8.4.27, 8.3.36 e 8.2.35 como as versões upstream mínimas corrigidas para suas respectivas branches. Os testes oficiais confirmam que 8.4.26 é classificado como VULNERABLE, enquanto 8.4.27 aparece como OK; o PHP identifica 8.5.12, 8.4.27, 8.3.36 e 8.2.35 como releases de segurança.
| Branch | Release upstream mínima corrigida | Release anterior classificada como vulnerável |
|---|---|---|
| PHP 8.5 | 8.5.12 | 8.5.11 |
| PHP 8.4 | 8.4.27 | 8.4.26 |
| PHP 8.3 | 8.3.36 | 8.3.35 |
| PHP 8.2 | 8.2.35 | 8.2.34 |
| Situação da implantação | Por que uma comparação simples de versões pode enganar | Evidência a usar |
|---|---|---|
Cabeçalho X-Powered-By ou Server oculto | O verificador remoto não consegue identificar o PHP | Inventário do runtime local |
| Pacote de segurança do Debian ou Ubuntu | O vendor pode aplicar o backport da correção mantendo uma versão upstream mais antiga | Advisory do vendor e changelog do pacote |
| PHP-FPM e CLI no mesmo host | php -v pode descrever a CLI, não o worker HTTP | Configuração do servidor web e do FPM |
| Contêiner em cache ou digest fixado | A tag do registry pode estar atualizada enquanto o contêiner em execução continua antigo | ID da imagem e versão do contêiner em execução |
| Workers do Apache ou FPM não reiniciados | Os arquivos corrigidos podem estar no disco enquanto workers antigos continuam ativos | Horário de início do processo e verificação após a reinicialização |
| Branch sem suporte ou prerelease | O checker pode não reconhecer o estado do patch específico do vendor | Nota de segurança do PHP ou do vendor |
A seção de limitações do repositório informa que a ferramenta presume que os patches estáveis posteriores de uma branch listada contenham a correção e não consegue verificá-la de forma independente. Uma distribuição pode aplicar um backport de segurança sem alterar o número da versão upstream. Nesse caso, o changelog oferece uma evidência mais forte do que o número exibido isoladamente.
Atualizar WordPress, Drupal, Laravel ou outra aplicação PHP não corrige o engine do PHP. Atualize o pacote ou a imagem do runtime, reinicie os workers e confirme o processo que recebe as requisições web.
Perguntas frequentes
Qual resultado permite encerrar um ticket de correção em produção?
Nenhum resultado deve encerrar um ticket sozinho. Combine OK com a confirmação do SAPI que atende as requisições, do status de backport do vendor, de todos os vhosts ou contêineres relevantes e de que os workers foram reiniciados após a aplicação do patch.