# Least Privilege: permissões do utilizador do servidor web

> Utilizador do servidor web com permissões mínimas: sem shell, sudo nem cron, base de dados restrita e systemd no PHP-FPM. Com comandos de verificação.

Fonte: https://phpsos.de/pt/blog/rechte-des-webserver-benutzers/  
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:** O utilizador do servidor web com que o PHP corre deve, segundo o princípio das permissões mínimas (Least Privilege), ler apenas o que o site precisa e escrever apenas onde o site guarda dados. Não tem shell de início de sessão, direitos sudo, cronjobs próprios nem chaves SSH, e a sua conta de base de dados só pode ler e alterar dados. Opções do systemd como `ProtectSystem` e `PrivateTmp` limitam adicionalmente o PHP-FPM.

## A pergunta após a intrusão: o que pode este processo fazer?

O PHP2Shell trata da execução remota de código malicioso sem autenticação. Se for bem-sucedida, o código não corre no vazio, mas como um utilizador bem determinado: o utilizador do processo PHP. Tudo o que este utilizador pode fazer, o atacante passa também a poder fazer a partir desse momento.

Em muitos servidores isso é surpreendentemente muito. O utilizador é proprietário de todo o código do programa, tem uma shell, pode criar cronjobs próprios, e a conta de base de dados da aplicação tem todos os direitos sobre todas as bases de dados. Para um atacante, é o ponto de partida ideal para se instalar de forma duradoura.

Como atribuir corretamente ficheiros e pastas é descrito no guia [Permissões de ficheiros no servidor web](https://phpsos.de/pt/ratgeber/dateirechte-webserver/). Este artigo olha para a própria conta: início de sessão, direitos especiais, tarefas agendadas, base de dados e os limites que o systemd traça.

## Inventário: quem é o utilizador do servidor web?

Primeiro, esclareça que utilizadores estão envolvidos. No PHP-FPM, cada pool define com `user` e `group` sob que utilizador correm os seus workers. No mod_php, o PHP corre como utilizador do Apache. Como o mestre e os workers do PHP-FPM interagem é explicado em [PHP-FPM explicado: gestor de processos, pools e workers](https://phpsos.de/pt/php/php-fpm-erklaert/). Os comandos seguintes apenas leem:

```bash
# Com que utilizadores correm o servidor web e o PHP?
ps -eo user,group,cmd | grep -E "[p]hp-fpm|[n]ginx|[a]pache2|[h]ttpd" | sort | uniq -c
# Dados da conta: diretório home e shell (adaptar o utilizador)
getent passwd www-data
# O utilizador tem direitos sudo?
sudo -l -U www-data
# Cronjobs próprios?
sudo crontab -l -u www-data
# Chaves SSH no diretório home (no Debian/Ubuntu é /var/www)
sudo ls -la /var/www/.ssh 2>/dev/null
```

Anote os resultados de cada utilizador de pool. Se todos os sites correrem sob o mesmo utilizador, esse é o primeiro ponto da lista; como separá-los é descrito em [Isolar pools PHP-FPM por site](https://phpsos.de/pt/blog/php-fpm-pools-isolieren/).

## Permissões do utilizador do servidor web: o que a conta não precisa

O quadro seguinte mostra o que um utilizador do servidor web normalmente não precisa e como o retirar.

| Permissão | Porque é perigosa | Recomendação |
|---|---|---|
| Shell de início de sessão | possível início de sessão e uso interativo | shell `/usr/sbin/nologin` |
| entradas sudo | caminho para direitos de root | nenhuma entrada, nem para comandos isolados |
| crontab própria | porta dos fundos duradoura que sobrevive a qualquer reinício | nenhuma, limitar com `/etc/cron.allow` |
| chaves SSH | início de sessão a partir do exterior | sem `authorized_keys` |
| propriedade do código do programa | o código pode ser alterado | o proprietário é um utilizador de deploy |
| escrita fora das pastas de dados | colocação de código malicioso | apenas uploads, cache, temp |
| direitos totais na base de dados | bases de dados de outras aplicações, acesso a ficheiros através da base de dados | apenas a própria base de dados, apenas direitos de dados |

A shell define-se com `usermod -s /usr/sbin/nologin www-data`. Para o cron aplica-se o seguinte: se existir `/etc/cron.allow`, só os utilizadores aí indicados podem criar cronjobs próprios. Cronjobs recém-criados ou chaves SSH desconhecidas são um sinal típico de que alguém se fixou no sistema. Um sinal de alerta particularmente claro é descrito no artigo [Sinal de alerta: o servidor web inicia uma shell](https://phpsos.de/pt/blog/webserver-startet-shell/).

## A base de dados: limitar os direitos ao necessário

A conta de base de dados de um site é, na prática, um segundo utilizador do servidor web. As suas credenciais estão no ficheiro de configuração da aplicação e são legíveis por código introduzido. Por isso, só deve poder fazer o que a aplicação precisa em funcionamento.

```sql
-- Exemplo MySQL/MariaDB: conta própria por site, apenas direitos de dados
CREATE USER 'seite1'@'localhost' IDENTIFIED BY 'hier-ein-langes-Zufallspasswort';
GRANT SELECT, INSERT, UPDATE, DELETE ON seite1.* TO 'seite1'@'localhost';
-- Verificar direitos
SHOW GRANTS FOR 'seite1'@'localhost';
```

Direitos como `FILE`, `SUPER` ou `GRANT OPTION` e o acesso a `*.*` não são necessários a uma conta de aplicação. Muitos CMS precisam, para as atualizações, também de `CREATE`, `ALTER`, `INDEX` e `DROP`. É mais limpo ter uma conta separada para atualizações e migrações, usada apenas durante a manutenção. Verifique os requisitos na documentação do fabricante.

## Limitar adicionalmente o PHP-FPM com o systemd

O systemd pode restringir a visão que um serviço tem do sistema. Para o PHP-FPM, algumas opções da documentação do systemd são particularmente adequadas. Também atuam sobre o processo mestre, que arranca como root.

```ini
# sudo systemctl edit php8.3-fpm
[Service]
# /usr, /boot e /etc só de leitura
ProtectSystem=full
# /home, /root e /run/user invisíveis
ProtectHome=true
# /tmp e /var/tmp próprios, só para este serviço
PrivateTmp=true
# sem elevação de privilégios através de setuid ou capabilities de ficheiros
NoNewPrivileges=true
```

Teste estas opções antes da utilização em produção. Se os sites estiverem em `/home`, o `ProtectHome=true` impede o acesso. O `NoNewPrivileges=true` pode perturbar programas chamados pelo PHP que mudam os seus direitos de grupo ao arrancar, por exemplo alguns programas de correio locais para a função `mail()` do PHP. Por isso, avance por etapas:

1. Acrescentar uma opção, reiniciar o serviço e verificar com `systemctl status php8.3-fpm`.
2. Testar as funções essenciais do site: início de sessão, formulários, envio de correio, uploads, cronjobs da aplicação.
3. Analisar o registo de erros do PHP-FPM e da aplicação.
4. Só então acrescentar a opção seguinte.

Por fim, o socket: segundo o manual do PHP, recebe por defeito as permissões `0660` para o utilizador e o grupo do pool. Defina `listen.owner` e `listen.group` de modo que apenas o servidor web se possa ligar, e não qualquer utilizador local.

> **Dica:**
> As permissões mínimas são uma atitude de base, não um projeto pontual. Repita o inventário deste artigo após cada reestruturação e após cada novo site, pois os novos serviços trazem muitas vezes permissões por defeito generosas.

## Conclusão: o atacante herda o que você permite

O Least Privilege parece teoria, mas é uma questão muito prática: o que pode fazer alguém que executa código como utilizador do servidor web? Num servidor com shell, entrada sudo, crontab própria e uma conta de base de dados com todos os direitos, a resposta é: quase tudo. Num servidor delimitado, o mais provável é um incidente num único site, que pode ser identificado e limpo.

A mudança não exige software novo, apenas um inventário cuidadoso e testes por etapas. Comece pelos pontos que dificilmente quebram alguma coisa, ou seja, shell, sudo e chaves SSH, e avance depois para os direitos da base de dados e as opções do systemd.

## Como ajuda concretamente a PHP SOS?

- **Verificar contas:** Registamos, para cada pool e servidor web, o utilizador, a shell, as entradas sudo, os cronjobs, as chaves SSH e os direitos da base de dados.
- **Reduzir permissões:** Retiramos o que não é necessário e separamos as contas de deploy, de execução e de manutenção.
- **Limitar serviços:** Definimos as opções de proteção do systemd por etapas e testamos o site após cada passo.
- **Manter de forma duradoura:** No âmbito do [reforço de segurança de servidores](https://phpsos.de/pt/leistungen/server-haertung/), documentamos o conceito de permissões para alterações futuras.


## Perguntas frequentes

**Com que utilizador corre o PHP no meu servidor?**  
Depende do modo de funcionamento. Com o mod_php, o PHP corre como utilizador do Apache, por exemplo www-data ou apache. Com o PHP-FPM, cada pool define o seu utilizador com user e group; o processo mestre corre normalmente como root, os workers como utilizador do pool. O comando ps mostra-o rapidamente.

**O utilizador do servidor web precisa de uma shell de início de sessão?**  
Não. Nem o Nginx, nem o Apache, nem o PHP-FPM precisam de um início de sessão interativo para este utilizador. Uma shell como /usr/sbin/nologin impede que alguém inicie sessão com esta conta. Os deployments correm através de um utilizador próprio.

**Porque é que o www-data não deve ter direitos sudo, nem sequer para um único comando?**  
Porque o código introduzido herda exatamente estes direitos. Mesmo um comando aparentemente inofensivo pode, se for mal autorizado, levar a direitos de root. As tarefas que exigem permissões elevadas devem ficar em serviços ou processos separados, fora do servidor web.

**Isto ajuda contra o PHP2Shell?**  
Não fecha a vulnerabilidade; para isso são necessárias a atualização do PHP e o reinício de todos os workers. Permissões mínimas limitam, no entanto, o que um atacante pode fazer após uma exploração bem-sucedida: alterar ficheiros, fixar-se no sistema, chegar a outros sites.

## Fontes

- [Manual do PHP: configuração do FPM (user, listen.mode)](https://www.php.net/manual/en/install.fpm.configuration.php)
- [systemd.exec (ProtectSystem, PrivateTmp, NoNewPrivileges)](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html)
- [BSI IT-Grundschutz](https://www.bsi.bund.de/DE/Themen/Unternehmen-und-Organisationen/Standards-und-Zertifizierung/IT-Grundschutz/it-grundschutz_node.html)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
