← Blog

Como Desenvolver Aplicações Mais Seguras com PHP

Um guia prático de desenvolvimento seguro em PHP: previna SQL injection, XSS, inclusão de arquivos e command injection, e fortaleça dependências com SCA.

Bruno Baldo·14 de set. de 2026·7 min de leitura·Revisado por Rainforest Technologies

O PHP ainda movimenta uma parcela enorme da web, de pequenos sites a algumas das maiores plataformas online. Esse alcance torna o desenvolvimento seguro em PHP uma necessidade prática, e não uma reflexão tardia. A boa notícia é que a segurança em PHP é muito aprendível: a maioria dos incidentes remete a uma lista curta de erros bem compreendidos, e cada um tem uma correção confiável e bem amparada. Este guia percorre as vulnerabilidades que mais importam e as práticas de programação segura em PHP que as neutralizam.

A mentalidade que amarra tudo é simples: trate cada trecho de entrada como não confiável até que se prove o contrário, e trate cada trecho de saída como perigoso até que ele esteja devidamente codificado para o seu destino.

SQL injection e prepared statements

O SQL injection continua sendo uma das falhas de maior impacto em aplicações PHP, e ele aparece sempre que a entrada do usuário é concatenada diretamente em uma string de consulta. A correção é parar de misturar dados e código. Use PDO com consultas parametrizadas para que o mecanismo do banco de dados, e não a concatenação de strings, decida o que é dado.

Prepare uma instrução como $stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?'); e, em seguida, $stmt->execute([$email]);. O valor do usuário é vinculado como parâmetro e nunca pode alterar a estrutura da consulta. Faça do PDO sua camada de banco de dados padrão, habilite exceções com PDO::ATTR_ERRMODE e evite prepares emulados para que o binding real do lado do servidor seja utilizado.

Inclusão de arquivos (LFI e RFI)

O include e o require do PHP são poderosos, e esse poder é exatamente o problema quando a entrada do usuário chega até eles. Passar um parâmetro de requisição para include($_GET['page'] . '.php') abre a porta para local file inclusion (ler ou executar arquivos já presentes no servidor) e, em ambientes mal configurados, remote file inclusion.

Nunca construa um caminho de include a partir da entrada do usuário diretamente. Em vez disso, use uma allowlist: mapeie um pequeno conjunto de chaves conhecidas e válidas para caminhos de arquivo fixos, e rejeite qualquer coisa que não esteja na lista. Mantenha allow_url_include e allow_url_fopen desabilitados, a menos que você tenha um motivo específico e revisado para alterá-los.

Command injection

Funções como system, exec, shell_exec, passthru e o operador de crase entregam a entrada ao shell do sistema operacional. Se qualquer valor controlado pelo usuário chegar a elas sem escape, um atacante pode encadear seus próprios comandos. Sempre que possível, evite recorrer ao shell e use uma função ou biblioteca nativa do PHP em vez disso. Quando você realmente precisar chamar um programa externo, faça o escape dos argumentos com escapeshellarg() e do nome do comando com escapeshellcmd(), e valide a entrada primeiro contra um formato esperado estrito.

Desserialização insegura

Chamar unserialize() sobre entrada não confiável é perigoso porque o PHP instanciará objetos e disparará métodos mágicos durante o processo, o que os atacantes podem transformar em cadeias de object injection e execução remota de código. A regra é direta: nunca execute unserialize() em dados que vieram de um usuário, de um cookie ou de qualquer fonte externa. Prefira json_decode() para intercâmbio, já que ele produz estruturas de dados simples em vez de objetos vivos. Se você precisar aceitar entrada serializada, passe a opção allowed_classes para restringir o que pode ser instanciado.

Cross-site scripting (XSS)

O XSS acontece quando dados fornecidos pelo usuário são escritos em uma página HTML sem codificação, permitindo que o script de um atacante seja executado no navegador da vítima. A codificação de saída é a resposta. Codifique valores dinâmicos para o seu contexto com htmlspecialchars($value, ENT_QUOTES, 'UTF-8') antes de imprimi-los no HTML. Para uma defesa robusta, combine a codificação de saída com um cabeçalho Content Security Policy e use um motor de templates que faça auto-escape por padrão.

Cross-site request forgery (CSRF)

O CSRF engana o navegador de um usuário autenticado, fazendo-o enviar uma requisição que ele não pretendia. Defenda as requisições que alteram estado com tokens anti-CSRF: gere um token criptograficamente aleatório, armazene-o na sessão, incorpore-o como um campo oculto em cada formulário e verifique-o no envio com uma comparação de tempo constante como hash_equals(). Configurar cookies com o atributo SameSite adiciona uma valiosa segunda camada.

Type juggling e comparações frouxas

O operador de comparação frouxa do PHP (==) realiza coerção de tipos que pode produzir resultados surpreendentes, o que se torna um problema de segurança em verificações como comparação de tokens ou hashes. Usar == onde dois valores de tipos diferentes podem ser tratados como iguais pode permitir que um atacante contorne uma verificação. Use sempre comparação estrita (===) para decisões de segurança, e utilize funções feitas para esse fim, como hash_equals() para comparar segredos e password_verify() para senhas.

Fortalecimento de sessão e configuração

Muitos problemas clássicos do PHP foram problemas de configuração. A era do register_globals já passou há muito tempo, mas sua lição permanece: padrões inseguros causam violações. Mantenha display_errors desligado em produção, registre os erros em log em vez disso e configure os cookies de sessão com as flags HttpOnly, Secure e SameSite. Regenere o ID da sessão no login com session_regenerate_id(true), armazene segredos em variáveis de ambiente em vez de no código-fonte, e mantenha o próprio PHP atualizado em uma versão com suporte.

Risco de dependências com o Composer

Aplicações PHP modernas incorporam dezenas de pacotes por meio do Composer e do Packagist, e cada dependência é código no qual você está confiando. Uma vulnerabilidade em um pacote transitivo é a sua vulnerabilidade. Faça commit do seu arquivo composer.lock para que as builds sejam reproduzíveis, revise o que você adiciona, remova pacotes que não usa mais e execute composer audit para verificar os pacotes instalados contra advisories conhecidos. A software composition analysis automatizada vai além, sinalizando continuamente componentes vulneráveis e desatualizados em toda a sua árvore de dependências.

Leve isso para a CI: SAST e SCA

A revisão manual é valiosa, mas não escala. O static application security testing (SAST) analisa seu código-fonte PHP em busca de padrões inseguros, enquanto o SCA monitora suas dependências. Integrar ambos ao seu pipeline de integração contínua significa que cada commit e pull request é verificado automaticamente, de modo que os problemas sejam capturados enquanto ainda são baratos de corrigir, em vez de após a implantação. Se você está avaliando onde cada técnica se encaixa, nossa comparação SAST vs DAST detalha os trade-offs, e essas ferramentas se posicionam naturalmente dentro de um ciclo mais amplo de desenvolvimento seguro de software.

Um checklist rápido de PHP seguro

  • Use consultas parametrizadas com PDO em cada interação com o banco de dados.
  • Codifique toda a saída com htmlspecialchars() para o seu contexto.
  • Use allowlist em qualquer caminho dinâmico de include/require.
  • Faça escape dos argumentos de shell com escapeshellarg(), ou evite recorrer ao shell por completo.
  • Nunca use unserialize() em entrada não confiável; prefira json_decode().
  • Use === e hash_equals() para comparações sensíveis à segurança.
  • Proteja cada formulário que altera estado com um token CSRF.
  • Fortaleça os cookies de sessão e mantenha a exibição de erros desligada em produção.
  • Fixe e audite as dependências do Composer.
  • Execute SAST e SCA em cada build.

Como a Rainforest ajuda

A Rainforest foi construída para tornar o desenvolvimento seguro em PHP parte do seu fluxo de trabalho normal, e não uma tarefa à parte. Nossa plataforma de application security testing faz a varredura do seu código em busca das classes de vulnerabilidade acima e se integra diretamente à CI/CD, de modo que os achados apareçam no pull request com orientações claras sobre onde está o problema e como corrigi-lo. No lado das dependências, a software composition analysis acompanha seus pacotes do Composer e alerta você quando um componente carrega uma vulnerabilidade conhecida. Fundamentar seu programa nas categorias de risco da OWASP mantém sua equipe focada no que os atacantes realmente têm como alvo.

Aplicações seguras vêm de bons hábitos reforçados por boas ferramentas. Se você quiser ver como a Rainforest se encaixa na sua stack PHP, agende uma demonstração e a percorreremos junto com você.

Perguntas frequentes

O PHP é seguro?

O PHP pode ser muito seguro. A linguagem e seu ecossistema moderno oferecem ferramentas robustas, como PDO, password_hash() e templates com auto-escape. A maioria das violações em PHP vem de práticas de programação inseguras e dependências desatualizadas, e não da linguagem em si. Permanecer em uma versão do PHP com suporte e seguir as práticas deste guia resolve a grande maioria do risco no mundo real.

Quais são as vulnerabilidades de segurança comuns do PHP?

As mais frequentes são SQL injection, cross-site scripting (XSS), cross-site request forgery (CSRF), inclusão local e remota de arquivos (LFI/RFI), command injection e desserialização insegura. Bugs de comparação frouxa (type juggling) e configurações fracas de sessão ou de ambiente completam a lista. Todas elas são evitáveis com técnicas bem estabelecidas.

Como prevenir SQL injection em PHP?

Use prepared statements do PDO com parâmetros vinculados em cada consulta, para que a entrada do usuário seja sempre tratada como dado e nunca como SQL executável. Habilite o tratamento de erros em modo de exceção, desabilite os prepares emulados para forçar o binding real do lado do servidor, e valide a entrada contra o formato que você espera antes de ela chegar ao banco de dados.

Como gerenciar o risco de dependências em PHP?

Trate as dependências do Composer como parte da sua superfície de ataque. Faça commit do composer.lock para builds reproduzíveis, revise e minimize o que você adiciona, e execute composer audit regularmente. Para cobertura contínua, use software composition analysis para detectar automaticamente pacotes vulneráveis e desatualizados em suas dependências diretas e transitivas.

Como fazer a varredura de código PHP em busca de vulnerabilidades?

Combine o static application security testing (SAST), para analisar seu código-fonte, com a software composition analysis (SCA), para verificar suas dependências, e execute ambos automaticamente no seu pipeline de CI/CD. A Rainforest oferece os dois e reporta os achados diretamente nos seus pull requests, de modo que os problemas sejam corrigidos antes de irem para produção.

Bruno Baldo

Escrito por

Bruno Baldo

CMO

Um pouco de marketing e um pouco de curiosidade e temos a receita pra criar um apaixonado por cyber!

Continue lendo