PHP

Segurança em PHP: XSS, CSRF, Injeção e Boas Práticas Finais: Do Básico ao Avançado

6 min de leitura

Segurança em PHP: XSS, CSRF, Injeção e Boas Práticas Finais: Do Básico ao Avançado

XSS (Cross-Site Scripting) XSS ocorre quando um atacante injeta código JavaScript malicioso que é executado no navegador da vítima. Existem três tipos principais: Stored (armazenado no banco), Reflected (refletido na URL) e DOM-based (manipulação direta do DOM). A vulnerabilidade acontece quando você confia em entrada do usuário sem sanitização adequada. A defesa fundamental é escapar a saída para o contexto HTML correto. Use para converter caracteres especiais em entidades HTML, impedindo que o navegador interprete tags perigosas. Se você permite HTML limitado, use uma biblioteca como HTMLPurifier. Veja o exemplo: Use para escapar aspas duplas e simples, essencial em atributos. Em contextos JSON, use que já escapa caracteres perigosos. Headers de segurança como adicionam uma camada extra de proteção, bloqueando execução de scripts inline não autorizados. CSRF (Cross-Site Request Forgery) CSRF força um usuário autenticado a realizar ações indesejadas em outro site. Um atacante cria um formulário malicioso que, ao ser visualizado por um usuário logado, executa requisições sem consentimento.

<h2>XSS (Cross-Site Scripting)</h2>

<p>XSS ocorre quando um atacante injeta código JavaScript malicioso que é executado no navegador da vítima. Existem três tipos principais: Stored (armazenado no banco), Reflected (refletido na URL) e DOM-based (manipulação direta do DOM). A vulnerabilidade acontece quando você confia em entrada do usuário sem sanitização adequada.</p>

<p>A defesa fundamental é escapar a saída para o contexto HTML correto. Use <code>htmlspecialchars()</code> para converter caracteres especiais em entidades HTML, impedindo que o navegador interprete tags perigosas. Se você permite HTML limitado, use uma biblioteca como HTMLPurifier. Veja o exemplo:</p>

<pre><code class="language-php"></code></pre>

<p>Use <code>ENT_QUOTES</code> para escapar aspas duplas e simples, essencial em atributos. Em contextos JSON, use <code>json_encode()</code> que já escapa caracteres perigosos. Headers de segurança como <code>Content-Security-Policy</code> adicionam uma camada extra de proteção, bloqueando execução de scripts inline não autorizados.</p>

<h2>CSRF (Cross-Site Request Forgery)</h2>

<p>CSRF força um usuário autenticado a realizar ações indesejadas em outro site. Um atacante cria um formulário malicioso que, ao ser visualizado por um usuário logado, executa requisições sem consentimento. A defesa padrão é usar tokens únicos por sessão que devem ser validados em operações sensíveis (POST, PUT, DELETE).</p>

<p>Implemente tokens CSRF gerando um valor aleatório na sessão e validando em cada requisição. O token deve ser incluído no formulário e verificado no servidor. Exemplo prático:</p>

<pre><code class="language-php">&lt;?php

session_start();

// Gerar token (na primeira carga da página)

if (empty($_SESSION[&#039;csrf_token&#039;])) {

$_SESSION[&#039;csrf_token&#039;] = bin2hex(random_bytes(32));

}

// Exibir no formulário

?&gt;

&lt;form method=&quot;POST&quot; action=&quot;processar.php&quot;&gt;

&lt;input type=&quot;hidden&quot; name=&quot;csrf_token&quot; value=&quot;&lt;?php echo $_SESSION[&#039;csrf_token&#039;]; ?&gt;&quot;&gt;

&lt;input type=&quot;text&quot; name=&quot;email&quot; required&gt;

&lt;button type=&quot;submit&quot;&gt;Atualizar Email&lt;/button&gt;

&lt;/form&gt;

&lt;?php

// Validar no processamento

if ($_SERVER[&#039;REQUEST_METHOD&#039;] === &#039;POST&#039;) {

if (empty($_POST[&#039;csrf_token&#039;]) || $_POST[&#039;csrf_token&#039;] !== $_SESSION[&#039;csrf_token&#039;]) {

die(&#039;Token CSRF inválido!&#039;);

}

// Processar requisição segura

}

?&gt;</code></pre>

<p>Regenere o token após login para evitar fixação. Use <code>SameSite</code> cookies para adicionar proteção: <code>session.cookie_samesite = &quot;Strict&quot;</code> no php.ini. Isso previne envio automático de cookies em requisições cross-site.</p>

<h2>Injeção SQL e Prepared Statements</h2>

<p>Injeção SQL ocorre quando entrada do usuário é concatenada diretamente em queries. Um atacante pode manipular a lógica SQL para acessar, modificar ou deletar dados. A defesa comprovada é usar prepared statements com placeholders que separam código SQL de dados.</p>

<p>PDO e MySQLi oferecem proteção nativa via prepared statements. O SQL é compilado separadamente dos parâmetros, tornando impossível alterar a estrutura da query:</p>

<pre><code class="language-php"></code></pre>

<p>Nunca confie em tipo de dado. Mesmo um número pode ser vulnerável se não for tratado. Use prepared statements para TODAS as queries dinâmicas, sem exceção. Validação de entrada complementa mas não substitui prepared statements — use ambas as técnicas.</p>

<h2>Boas Práticas Finais</h2>

<p>Além das vulnerabilidades específicas, implemente defesas em profundidade. Use HTTPS obrigatoriamente para todas as requisições, protegendo dados em trânsito. Implemente rate limiting para dificultar ataques de força bruta. Mantenha PHP, dependências e bibliotecas atualizadas — use Composer para gerenciar versões e receber atualizações de segurança.</p>

<p>Adicione headers HTTP essenciais em cada resposta:</p>

<pre><code class="language-php">&lt;?php

// Prevenir clickjacking

header(&quot;X-Frame-Options: SAMEORIGIN&quot;);

// Proteger contra MIME sniffing

header(&quot;X-Content-Type-Options: nosniff&quot;);

// Habilitar HSTS (obriga HTTPS)

header(&quot;Strict-Transport-Security: max-age=31536000; includeSubDomains&quot;);

// Content Security Policy forte

header(&quot;Content-Security-Policy: default-src &#039;self&#039;; script-src &#039;self&#039;; style-src &#039;self&#039; &#039;unsafe-inline&#039;&quot;);

// Proteger contra XSS no IE antigo

header(&quot;X-XSS-Protection: 1; mode=block&quot;);

?&gt;</code></pre>

<p>Implemente logging e monitoramento de atividades suspeitas. Nunca exponha informações sensíveis em mensagens de erro — use logs internos. Valide TODAS as entradas de usuário, escape TODAS as saídas para o contexto correto, e use prepared statements para TODA interação com banco de dados. Estes três pilares eliminam a maioria das vulnerabilidades comuns.</p>

<h2>Conclusão</h2>

<p>Os três conceitos mais críticos são: <strong>1) Escapar saída com <code>htmlspecialchars()</code> para XSS</strong>, garantindo que entrada malicioso se torne inofensivo no navegador; <strong>2) Usar tokens CSRF em formulários e validar em POST/PUT/DELETE</strong>, protegendo contra requisições forçadas; <strong>3) Implementar prepared statements em TODAS as queries</strong>, tornando injeção SQL tecnicamente impossível. Segurança não é um recurso opcional — é a base para software confiável. Pratique constantemente e mantenha-se atualizado sobre novas vulnerabilidades.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://owasp.org/www-project-top-ten/" target="_blank" rel="noopener noreferrer">OWASP Top 10 - Web Application Security Risks</a></li>

<li><a href="https://www.php.net/manual/en/security.php" target="_blank" rel="noopener noreferrer">PHP Security Guide - Official Documentation</a></li>

<li><a href="https://content-security-policy.com/" target="_blank" rel="noopener noreferrer">Content Security Policy Reference</a></li>

<li><a href="https://portswigger.net/web-security/cross-site-scripting" target="_blank" rel="noopener noreferrer">PortSwigger Web Security Academy - XSS</a></li>

<li><a href="https://phptherightway.com/#security" target="_blank" rel="noopener noreferrer">PHP: The Right Way - Security Section</a></li>

</ul>

Comentários

Mais em PHP

Construindo uma API REST Completa com Laravel na Prática
Construindo uma API REST Completa com Laravel na Prática

Fundações: Preparando o Ambiente Antes de construir sua API REST em Laravel,...

Trabalhando com Pacotes Populares do Packagist: Do Básico ao Avançado
Trabalhando com Pacotes Populares do Packagist: Do Básico ao Avançado

Introdução ao Packagist e Composer O Packagist é o repositório oficial de pac...

Como Usar Prepared Statements e Prevenção de SQL Injection em Produção
Como Usar Prepared Statements e Prevenção de SQL Injection em Produção

O Problema: SQL Injection SQL Injection é uma das vulnerabilidades mais críti...