Introdução
A injeção de comandos no shell (Command Injection) é uma vulnerabilidade crítica que permite a um atacante executar comandos arbitrários no sistema operacional através do PHP. Se funções inseguras forem utilizadas sem validação, o invasor pode assumir o controle do servidor.
1. Desativando funções perigosas no php.ini
A melhor prática para evitar a injeção de comandos é desativar funções perigosas que permitem a execução de comandos do sistema:
disable_functions = exec, shell_exec, system, passthru, proc_open, popen
Isso impede que scripts PHP executem comandos diretamente no shell.
2. Evitando uso de funções inseguras
Funções como exec()
, shell_exec()
e system()
executam comandos do sistema operacional. Se forem utilizadas com entradas do usuário, tornam-se uma grande ameaça.
Exemplo de código inseguro:
$comando = $_GET['cmd'];
echo shell_exec($comando);
Se um atacante passar cmd=rm -rf /
, pode causar danos irreversíveis ao servidor.
3. Validando e escapando entradas do usuário
Se for realmente necessário executar comandos do sistema, utilize escapes para impedir injeção maliciosa:
$comando = escapeshellcmd($_GET['cmd']);
echo shell_exec($comando);
O escapeshellcmd()
remove caracteres perigosos que poderiam ser usados para manipular o comando.
Para argumentos individuais, use escapeshellarg()
:
$arquivo = escapeshellarg($_GET['arquivo']);
echo shell_exec("cat $arquivo");
Isso impede que o usuário insira comandos extras acidentalmente.
4. Utilizando alternativas seguras
Na maioria dos casos, é possível substituir comandos do sistema por funções PHP seguras. Por exemplo:
-
Em vez de
ls
, usescandir()
:$arquivos = scandir('/var/www/uploads'); print_r($arquivos);
-
Em vez de
cat
, usefile_get_contents()
:echo file_get_contents('/var/www/uploads/texto.txt');
Isso evita a necessidade de comandos externos, reduzindo riscos de injeção.
5. Executando comandos com restrição de privilégios
Se for inevitável executar comandos do sistema, restrinja o usuário do servidor para que ele tenha permissões limitadas e não possa comprometer o sistema inteiro.
Conclusão
A injeção de comandos no shell pode comprometer completamente um servidor PHP. Desativar funções perigosas, validar entradas do usuário e utilizar alternativas seguras são medidas fundamentais para proteger a aplicação contra esse tipo de ataque.
Por que evitar a injeção de comandos no shell em PHP é fundamental?
Ataques de injeção de comandos são amplamente explorados por invasores para comprometer servidores e roubar dados sensíveis. Muitas falhas ocorrem porque desenvolvedores utilizam funções inseguras sem validação adequada, permitindo que usuários mal-intencionados executem comandos arbitrários.
Uma das maneiras mais eficazes de proteger aplicações PHP é substituir chamadas ao sistema por funções nativas do PHP, como scandir()
, file_get_contents()
e unlink()
. Se comandos externos forem absolutamente necessários, a validação rigorosa das entradas e o uso de escapes são essenciais.
Além disso, desativar funções de execução de comandos no php.ini
pode prevenir exploits antes mesmo que eles ocorram. Com essas medidas, garantimos que o PHP seja utilizado de forma segura e protegemos o ambiente de execução contra ameaças externas.
Algumas aplicações:
- Evitar que atacantes executem comandos no servidor via PHP.
- Proteger arquivos e dados contra exclusão ou modificação maliciosa.
- Garantir que apenas comandos autorizados sejam executados na aplicação.
- Reduzir o risco de comprometer todo o ambiente do servidor.
Dicas para quem está começando
- Evite usar
exec()
,shell_exec()
esystem()
em seu código PHP. - Se precisar executar comandos, sempre use
escapeshellcmd()
ouescapeshellarg()
. - Desative funções perigosas no
php.ini
para reforçar a segurança. - Prefira funções nativas do PHP para manipulação de arquivos e diretórios.
- Nunca confie diretamente em entradas do usuário para executar comandos.
Contribuições de Gustavo Ferraz