Em resumo: Um code review de segurança para PHP é a leitura dirigida do código-fonte com uma pergunta: onde podem entradas externas fazer algo que não deviam? Provaram-se duas formas, uma revisão de cada alteração e uma revisão de base de todo o projeto, apoiadas em análise estática com PHPStan ou Psalm. As falhas no interpretador PHP, como o PHP2Shell, uma revisão não as encontra, mas encontra os muitos erros que surgem no código próprio.
Porque olhar agora para o código próprio?
O PHP2Shell ocupou sobretudo os administradores na última semana de outubro de 2026. Aplicar o patch, reiniciar, comprovar: o trabalho estava no servidor. Para as equipas de desenvolvimento fica depois uma pergunta incómoda. Se um atacante conseguir executar código através de outra falha, o que encontra na nossa aplicação? E quantas dessas falhas escrevemos nós?
O OWASP Top 10 mostra há anos que a maioria das vulnerabilidades em aplicações web não é exótica. Controlo de acesso em falta, injeção e configuração insegura estão no topo. São erros que um olhar treinado encontra no código-fonte, muito antes de um atacante os experimentar.
Há ainda uma razão prática. Muitas empresas estão de qualquer modo a mandar verificar, corrigir e reforçar os seus servidores. Quem analisa a própria aplicação ao mesmo tempo fecha a lacuna entre operação e desenvolvimento. Um servidor reforçado com uma aplicação vulnerável continua atacável, e uma aplicação bem escrita sobre PHP sem patch também.
Revisão de base ou revisão de alterações?
O Cheat Sheet da OWASP sobre Secure Code Review distingue dois tipos, que na prática se complementam:
| Tipo | Quando | Âmbito | Objetivo |
|---|---|---|---|
| Revisão de base (baseline) | novo projeto, grande release, após um incidente | projeto inteiro, ponderado pelo risco | registar o parque de vulnerabilidades |
| Revisão de alterações (diff) | cada pull request | apenas o código alterado | evitar novos erros |
Uma revisão de base após um incidente é particularmente valiosa. Quem acabou de limpar um servidor deve saber se a aplicação oferece outras portas de entrada. A revisão de alterações mantém depois o estado limpo, porque cada alteração é lida também do ponto de vista da segurança antes de ser integrada.
Code review em PHP: onde se concentram os erros de segurança
Em projetos PHP vale a pena olhar de forma dirigida para determinadas funções e padrões. Não são proibidos, mas cada ocorrência merece a pergunta se dados externos podem lá chegar.
| Padrão no código | Risco possível | Aprofundamento |
|---|---|---|
| SQL por concatenação de strings com variáveis | injeção de SQL | Evitar SQL Injection em PHP |
unserialize() sobre dados externos |
injeção de objetos | Desserialização insegura em PHP |
include ou require com caminho variável |
inclusão de ficheiros alheios | Evitar Local File Inclusion em PHP: LFI e RFI |
exec(), system(), shell_exec(), proc_open() |
execução de comandos | Command Injection |
Saída sem htmlspecialchars() |
Cross-Site Scripting | escaping adequado ao contexto |
== em tokens ou hashes |
a conversão de tipos contorna verificações | hash_equals(), comparações estritas |
eval(), extract() sobre entradas |
injeção de código ou de variáveis | quase sempre eliminar sem substituição |
Uma primeira visão rápida obtém-se com uma pesquisa simples. Não substitui uma revisão, mas mostra por onde começar:
# Ocorrências de funções arriscadas no código próprio (vendor excluído)
grep -rnE "\b(unserialize|eval|extract|shell_exec|exec|system|passthru|proc_open)\s*\(" src/ app/ 2>/dev/null
Pelo menos igualmente importante é o que falta no código. Cada controlador verifica se o utilizador autenticado pode ver ou alterar precisamente este registo? Os uploads são restringidos quanto ao tipo e ao local de armazenamento? Falhas destas não as encontra nenhuma pesquisa por nomes de funções, só a leitura do fluxo.
Ferramentas que sustentam a revisão
A análise estática verifica o código sem o executar. O PHPStan e o Psalm encontram erros de tipos, código inacessível e suposições erradas sobre valores de retorno. O Psalm oferece ainda uma análise de taint, que acompanha se dados de pedidos fluem sem verificação para pontos críticos. Ambos podem ser tornados mais rigorosos por etapas, para que também projetos mais antigos possam começar. Uma visão geral está em Análise estática: PHPStan e Psalm.
# Análise estática no projeto, aumentar o nível gradualmente
vendor/bin/phpstan analyse src --level=5
# Análise de taint com o Psalm
vendor/bin/psalm --taint-analysis
As ferramentas dão indícios, não sentenças. Cada resultado precisa de uma avaliação, e um relatório vazio não significa que a aplicação seja segura.
Tão importante como encontrar é registar. Cada achado deve ser registado com o local, uma breve descrição, a avaliação do risco, a correção recomendada e o estado, de preferência diretamente no sistema de tickets da equipa. Assim é possível acompanhar o que foi corrigido, o que foi aceite conscientemente e o que está em aberto. Depois da correção vale a pena um segundo olhar: a causa foi eliminada ou apenas um sintoma? O mesmo padrão aparece noutros pontos do código? Um erro que foi cometido uma vez raramente está, segundo a experiência, num só sítio.
Uma lista de verificação para a sua equipa
Para revisões de alterações, provou-se uma lista curta e fixa. Pertence ao modelo dos pull requests:
- De onde vêm todos os dados que esta alteração processa, e são verificados no servidor?
- As consultas à base de dados são construídas exclusivamente com marcadores de posição?
- Cada saída está escapada para o seu contexto, ou seja, HTML, atributo, JavaScript ou URL?
- O código verifica a permissão para exatamente este objeto, e não apenas a autenticação?
- Palavras-passe, tokens ou dados pessoais vão parar a registos ou mensagens de erro?
- Existem segredos no código ou em ficheiros versionados?
- Foram incluídas novas dependências, e são mantidas?
Faça sempre ler as partes críticas para a segurança, como autenticação, gestão de permissões, fluxos de pagamento e uploads, por uma segunda pessoa que não tenha participado no código. O olhar externo encontra suposições que o autor considera óbvias.
Como ajuda concretamente a PHP SOS?
- Realizamos, com parceiros especializados, uma revisão de base da sua aplicação PHP, ponderada pelas partes de maior risco.
- Configuramos o PHPStan ou o Psalm de acordo com o estado do seu projeto e redigimos a lista de verificação para os seus pull requests.
- Ligamos a revisão a um olhar sobre o servidor e a configuração, pois muitas falhas só surgem na interação.
- Onde se deseje uma verificação a partir do exterior, complementamos a revisão com uma auditoria de segurança e teste de intrusão.
Conclusão: Um code review é o lugar mais barato para corrigir erros de segurança, ou seja, antes de serem entregues. Quem verifica cada alteração com uma lista curta e revê o projeto por completo de vez em quando reduz de forma duradoura a superfície de ataque.
Perguntas frequentes
Qual é a diferença entre code review e teste de intrusão?
Um code review lê o código-fonte e encontra erros antes de serem entregues. Um teste de intrusão ataca a aplicação em execução a partir do exterior. Ambos se complementam: a revisão encontra as causas, o teste mostra o que é realmente explorável.
Um code review encontra falhas como o PHP2Shell?
Não. O PHP2Shell está no interpretador PHP, não no código da aplicação. Contra isso só ajuda uma atualização do PHP com reinício. Uma revisão encontra erros no código próprio, por exemplo injeção, verificações de permissão em falta ou desserialização insegura.
O PHPStan ou o Psalm chegam para uma revisão de segurança?
São uma boa base e encontram automaticamente muitos erros. Mas erros de lógica, verificações de permissão em falta e suposições erradas sobre os fluxos só os reconhece uma pessoa que saiba o que a aplicação deve fazer.
Quanto tempo demora um code review de segurança?
Depende da dimensão. Uma revisão de cada alteração no pull request custa pouco tempo. Uma revisão completa de um projeto que cresceu ao longo do tempo é um projeto à parte, que se limita, em função do risco, às partes mais importantes.