# Proteger APIs REST em PHP

> Proteger APIs REST em PHP: autenticação, verificação por objeto, JWT, limites de tamanho e tipo, mensagens de erro e limitação de taxa, com código.

Fonte: https://phpsos.de/pt/blog/rest-api-php-absichern/  
Atualizado em: 25/10/2026  
Prestador: PHP SOS, Assistência de emergência PHP e segurança de servidores. Ajuda imediata por WhatsApp: https://wa.me/491736494914?text=Ol%C3%A1%2C%20PHP%20SOS%2C%20precisamos%20de%20ajuda%20com%20o%20nosso%20servidor%20PHP.%20Empresa%3A%20%E2%80%A6%20Site%3A%20%E2%80%A6

**Em resumo:** Para a segurança de API em PHP contam sobretudo cinco pontos: apenas HTTPS, autenticação em cada endpoint não público, verificação de permissões para cada objeto individual, limites estritos para o método, o tipo de conteúdo e o tamanho do pedido e mensagens de erro breves, sem pormenores internos. Acrescem a limitação de taxa e um registo de eventos relevantes para a segurança. Contra falhas no próprio interpretador PHP, como o PHP2Shell, isto não ajuda; para isso é necessária a atualização do PHP.

## A interface por trás do site

Muitas empresas verificaram os seus sites na semana após 21 de outubro de 2026. As interfaces por trás estiveram com menos frequência na lista. E é precisamente aí que decorrem processos sensíveis: a aplicação do portal de clientes vai buscar faturas, o sistema de gestão de mercadorias escreve existências na loja, um parceiro comunica encomendas por webhook. Muitas vezes, estas APIs foram construídas à pressa, para uma única finalidade, e nunca mais foram revistas.

Uma API não tem interface que torne os erros visíveis. Uma verificação de permissão em falta não é notada por ninguém no dia a dia, desde que todos os clientes consultem apenas o que devem. Um atacante, pelo contrário, tenta precisamente o que não está previsto.

O primeiro passo é por isso um inventário. Que endpoints existem, afinal? Encontram-se com frequência versões antigas como `/api/v1/`, que nunca foram desativadas após a mudança para `/v2/`, endpoints de teste do desenvolvimento ou uma descrição da interface acessível publicamente que lista funções internas. Cada endpoint que já não é necessário deve ser desativado. Cada um que permanece precisa de um responsável.

## Segurança de API em PHP: as regras básicas

O REST Security Cheat Sheet da OWASP resume regras provadas. Para projetos PHP, podem traduzir-se numa lista curta:

1. **Apenas HTTPS.** Tokens e credenciais nunca podem ser transmitidos sem cifragem.
2. **Cada endpoint verifica por si.** A autenticação pode ser feita de forma central, a decisão sobre o acesso é tomada no endpoint.
3. **Permissão por objeto.** Não apenas “está autenticado”, mas “pode aceder a exatamente este registo”.
4. **Definir os métodos permitidos.** O que não é expressamente permitido é rejeitado com 405.
5. **Verificar o tipo de conteúdo e o tamanho.** Tipo errado dá 415, pedidos demasiado grandes 413.
6. **Validar as entradas.** Tipo, comprimento, formato e intervalo de valores, no servidor.
7. **Sem segredos em URLs.** Tokens e chaves pertencem a cabeçalhos, não à query string.
8. **Erros breves.** Sem stack traces, caminhos ou mensagens SQL para o cliente.
9. **Limitação de taxa.** Demasiados pedidos são respondidos com 429.
10. **Isolar os endpoints de administração.** Não acessíveis publicamente ou apenas com autenticação forte.

## Permissão por objeto: o erro mais frequente

Um exemplo torna o problema palpável. Um endpoint fornece faturas em `/api/rechnungen/{id}`. Verifica-se se existe um token válido. Não se verifica se a fatura pertence ao cliente do token. Quem aumentar em um o seu próprio número de fatura vê a do vizinho.

A solução é simples e tem, mesmo assim, de ser aplicada em todos os pontos: a própria consulta restringe-se à área autorizada.

```php
<?php
// Permitir apenas o método GET
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
    http_response_code(405);
    header('Allow: GET');
    exit;
}

$kundeId = $auth->kundeId();          // do token verificado
$id = filter_var($routeId, FILTER_VALIDATE_INT);
if ($id === false) {
    http_response_code(400);
    exit;
}

// A permissão está na consulta: apenas as faturas próprias
$stmt = $pdo->prepare('SELECT nummer, betrag, datum FROM rechnungen WHERE id = ? AND kunde_id = ?');
$stmt->execute([$id, $kundeId]);
$rechnung = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$rechnung) {
    http_response_code(404);           // não revelar se o ID existe
    exit;
}

header('Content-Type: application/json');
echo json_encode($rechnung, JSON_THROW_ON_ERROR);
```

A consulta com marcadores de posição protege ao mesmo tempo contra a injeção de SQL, ver [Evitar SQL Injection em PHP](https://phpsos.de/pt/ratgeber/sql-injection-php/). Como o PHP disponibiliza os dados do pedido, como método, cabeçalhos e corpo, é explicado em [Superglobals: $_GET, $_POST, $_FILES e companhia](https://phpsos.de/pt/php/superglobals/).

## Verificar corretamente os tokens

Muitas APIs trabalham com JSON Web Tokens. O Cheat Sheet da OWASP indica regras claras para isso: os tokens têm de ser assinados, os tokens não assinados são rejeitados e o algoritmo da verificação é fixado no servidor, não retirado do token. O emissor, o público-alvo e o tempo de expiração fazem também parte da verificação. Use para isso uma biblioteca mantida, em vez de implementações próprias.

Tokens próprios, por exemplo para webhooks ou links de utilização única, têm de provir de um gerador de números aleatórios criptograficamente seguro e ser comparados em tempo constante. Como se faz em PHP é mostrado em [Números aleatórios e tokens seguros em PHP](https://phpsos.de/pt/blog/sichere-tokens-php/).

> **Dica:**
> Dê a cada cliente e a cada parceiro uma chave própria, com exatamente as permissões de que precisa. Assim, uma chave extraviada pode ser bloqueada individualmente, sem interromper todas as outras ligações.

## Impor limites: tamanho, tipo e ritmo

Uma API só deve aceitar o que espera. Isso começa no tipo de conteúdo: um endpoint que processa JSON rejeita tudo o resto. O tamanho máximo de um pedido limita-se a vários níveis, no servidor web e, no PHP, através de `post_max_size`. Este limite faz também parte das medidas transitórias que o php.net indicou para o PHP2Shell. Como escolhê-lo de forma sensata é descrito em [Limitar com critério post_max_size e upload_max_filesize](https://phpsos.de/pt/blog/post-max-size-upload-limits/).

A limitação de taxa protege contra a tentativa de adivinhar identificadores e contra a sobrecarga. Pode ser implementada no servidor web, num proxy intermédio ou na aplicação. É importante que os limites valham por chave ou utilizador e não apenas por endereço IP.

Para APIs chamadas diretamente a partir do navegador, acresce o CORS, isto é, as regras sobre que sites externos podem fazer pedidos. Defina estes cabeçalhos apenas se tais chamadas estiverem realmente previstas e indique as origens permitidas individualmente, em vez de admitir qualquer origem. Um marcador que permite todos os sites é, em endpoints com autenticação, quase sempre um erro.

Por último, o registo: inícios de sessão falhados, tokens rejeitados e acessos negados pertencem ao registo, os tokens em si não. Sem estas entradas, um ataque à API permanece invisível.

## Como ajuda concretamente a PHP SOS?

- Registamos todas as interfaces dos seus sistemas PHP, também as esquecidas e internas, e verificamos quais são acessíveis publicamente.
- Lemos a lógica de permissões e testamos de forma dirigida se registos alheios podem ser obtidos.
- Definimos limites de tamanho, tipo e ritmo no servidor web e no PHP e acordamo-los com os seus clientes.
- Para uma verificação abrangente a partir do exterior, combinamos isto com uma [auditoria de segurança e teste de intrusão](https://phpsos.de/pt/leistungen/sicherheitsaudit-penetrationstest/).

**Conclusão:** Uma API é tão segura quanto o seu endpoint mais descuidado. Quem verifica as permissões por objeto, impõe limites claros e mantém os erros breves fecha as falhas mais comuns muito antes de alguém as procurar de forma dirigida.


## Perguntas frequentes

**Uma chave de API chega como proteção?**  
Para dados sensíveis, não. Uma chave de API identifica normalmente uma aplicação, não um utilizador, e é facilmente transmitida. O REST Security Cheat Sheet da OWASP aconselha a não usar chaves de API como única proteção de recursos sensíveis.

**O que é uma permissão por objeto e porque é que falta tantas vezes?**  
Refere-se à verificação de se o utilizador autenticado pode ver ou alterar exatamente este registo. Falta muitas vezes porque os programadores só verificam se alguém está autenticado. Então basta alterar um identificador no URL para obter dados alheios.

**Uma API bem protegida protege contra o PHP2Shell?**  
Não. O PHP2Shell está no interpretador PHP e atua nos modos de funcionamento afetados antes de o seu código sequer correr. Contra isso só ajuda uma atualização do PHP com reinício. Limites de tamanho para os pedidos são, mesmo assim, úteis e fazem também parte das medidas transitórias do php.net.

**Que códigos de estado deve uma API devolver em erros de segurança?**  
É habitual 401 sem autenticação válida, 403 sem permissão, 405 para método não permitido, 413 para pedido demasiado grande, 415 para tipo de conteúdo errado e 429 para demasiados pedidos. A própria resposta permanece breve e sem pormenores internos.

## Fontes

- [OWASP: REST Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html)
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [Manual do PHP](https://www.php.net/manual/de/)
- [php.net: avisos de segurança](https://www.php.net/)
