Situação atual: PHP2Shell. Duas vulnerabilidades críticas do PHP (CVSS 9,2) permitem executar código malicioso sem autenticação. Patches disponíveis desde 21/10/2026.O que fazer agora →

Least Privilege: permissões do utilizador do servidor web

O código introduzido corre com as permissões do utilizador do servidor web. O que esta conta pode fazer decide até onde chega um atacante. Como limitar shell, sudo, cron, base de dados e sistema de ficheiros ao necessário.

Atualizado em 7 min de leituraHardening e configuração

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. 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. Os comandos seguintes apenas leem:

# 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.

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.

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.

-- 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.

# 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, 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

Contacto imediato

Cada hora conta. Escreva-nos agora.

Descreva brevemente o sistema, a versão do PHP e o que observou. Entramos em contacto consigo, esclarecemos a situação e trabalhamos remotamente até o incidente estar concluído e documentado.

Ajuda imediata