Algumas vulnerabilidades web levam diretamente ao comprometimento do servidor, e a command injection (injeção de comandos do sistema operacional) é a mais direta de todas. Ela ocorre quando uma aplicação web executa comandos do sistema operacional incorporando entrada do usuário sem tratamento — permitindo ao atacante executar seus próprios comandos no servidor. É a ponte mais curta entre uma falha web e um shell no sistema, conectando o Bloco XII ao Bloco VIII (exploração). Pratique no DVWA, que tem um módulo de command injection didático.
A mesma raiz, agora no sistema operacional
O mecanismo é a mesma raiz de toda injeção — misturar dados e comando —, agora no nível do sistema operacional. Imagine uma funcionalidade web que "pinga" um host para verificar conectividade: o usuário digita um endereço, e o servidor executa, por baixo, um comando de sistema como ping ENDERECO. Se a aplicação constrói esse comando colando a entrada do usuário diretamente, sem sanitizá-la, o atacante pode encadear seus próprios comandos. Os sistemas operacionais permitem executar múltiplos comandos numa linha usando separadores — o ; (executa o próximo comando em seguida), o | (encadeia via pipe), o && (executa se o anterior teve sucesso), e as crases ou $() (substituição de comando). Injetando esses separadores, o atacante quebra a estrutura do comando pretendido e adiciona o seu:
# a aplicação pretendia executar: ping 8.8.8.8
# o atacante digita no campo: 8.8.8.8; whoami
# o servidor executa: ping 8.8.8.8; whoami
# ↑ o comando do atacante roda também
De whoami a reverse shell
Aquele ; whoami faz o servidor, além de pingar, executar o whoami — e a saída revela com que usuário a aplicação roda. A partir daí, o atacante pode executar qualquer comando que aquele usuário permita: listar arquivos, ler dados, e — o passo natural — obter um reverse shell (aula O que é um exploit: da vulnerabilidade ao acesso), transformando a command injection num acesso interativo completo ao servidor. É por isso que a command injection é tão crítica: ela pula direto da web para a execução de código no sistema, o objetivo máximo da exploração.
A variante cega
Como no XSS e na SQLi, há uma variante cega (blind command injection): às vezes o comando executa mas sua saída não aparece na resposta da página. Você confirma e explora a vulnerabilidade por canais indiretos — como fazer o servidor esperar (; sleep 10) e medir o tempo de resposta (a mesma lógica time-based da SQLi cega, aula SQL Injection na mão: conversando com o banco de dados), ou fazer o servidor te enviar dados por outro canal (uma requisição de rede para um servidor que você controla — a exfiltração out-of-band). O raciocínio é idêntico ao da injeção cega em outros contextos: quando você não vê o resultado, você o infere por diferenças de comportamento ou por canais laterais.
Code injection: executar a própria linguagem
Uma vulnerabilidade relacionada que vale mencionar é a code injection propriamente dita — quando a aplicação executa código da própria linguagem (PHP, Python) a partir de entrada do usuário, em vez de comandos do SO. Funções perigosas que avaliam strings como código (como eval em várias linguagens) são a causa clássica. O impacto é similar (execução de código no servidor), e a raiz é a mesma: entrada do usuário sendo interpretada como código executável. Command injection e code injection são primas próximas, distinguidas por o quê é injetado — comandos do SO vs. código da linguagem.
Toda injeção, uma raiz e uma defesa
O ponto conceitual, que fecha o padrão de injeção do bloco: toda injeção — SQL, XSS, comandos, código — compartilha a mesma raiz e a mesma defesa. A raiz é sempre entrada não confiável sendo interpretada como instrução (SQL no banco, JS no navegador, comando no SO, código na linguagem). A defesa é sempre manter a fronteira entre dado e instrução. Uma vez que você internaliza esse padrão único, você reconhece injeção em qualquer contexto novo que encontrar — e reconhece a defesa correta. É a beleza de entender o princípio em vez de decorar cada ataque isoladamente: a command injection é "a SQLi do sistema operacional", governada pela mesma lógica.
Não deixar a entrada virar comando
Do lado defensivo, a command injection tem defesas claras, todas visando não deixar a entrada virar comando. A melhor prática é evitar chamar o sistema operacional com entrada do usuário sempre que possível — usar funções seguras da linguagem que fazem a tarefa sem invocar um shell (por exemplo, resolver um endereço via biblioteca em vez de chamar o comando ping). Quando a chamada ao sistema é inevitável: usar APIs que separam comando e argumentos (passando os argumentos como uma lista, não como uma string concatenada, de modo que a entrada nunca seja interpretada como parte do comando — o equivalente às prepared statements da SQLi); validação rigorosa de entrada (allowlist — se o campo espera um endereço IP, aceitar apenas o formato de um IP, rejeitando qualquer caractere de shell); menor privilégio (a aplicação web não deve rodar como root, para limitar o dano de uma injeção bem-sucedida); e nunca usar funções de avaliação de código com entrada do usuário. A lição, unificada com todo o bloco: separe dado de instrução, valide no servidor, e limite privilégios para conter o impacto.
Fontes e leituras recomendadas
- PortSwigger Web Security Academy — labs de OS command injection
- OWASP — Command Injection e Code Injection (Testing Guide e prevenção)
- DVWA — módulo de Command Injection em níveis de dificuldade
- HackTricks — seção de command injection e exfiltração out-of-band
Exercícios
-
Como a command injection permite ao atacante executar seus próprios comandos, e qual o papel de separadores como
;e&&?✓ Resposta:A aplicação executa um comando do SO incorporando a entrada do usuário sem sanitizá-la; usando separadores como
;,|ou&&, o atacante encadeia comandos próprios ao comando pretendido. Assim,8.8.8.8; whoamifaz o servidor executar owhoamialém doping, rodando o comando do atacante. -
Por que a command injection é considerada uma das pontes mais diretas entre uma falha web e o comprometimento do servidor?
✓ Resposta:Porque leva diretamente à execução de comandos no sistema operacional do servidor, permitindo obter um reverse shell e acesso interativo completo — pulando da web para a execução de código, o objetivo máximo da exploração, sem etapas intermediárias.
-
O que é a blind command injection, e como se confirma/explora a vulnerabilidade sem ver a saída?
✓ Resposta:É quando o comando executa mas sua saída não aparece na resposta. Confirma-se/explora-se por canais indiretos: fazendo o servidor esperar (
; sleep 10) e medindo o tempo de resposta, ou provocando o servidor a enviar dados a um servidor controlado pelo atacante (exfiltração out-of-band). -
Qual a diferença entre command injection e code injection, e o que elas têm em comum?
✓ Resposta:Command injection injeta comandos do sistema operacional; code injection injeta código da própria linguagem da aplicação (ex.: via funções como
eval). Em comum: ambas resultam em execução no servidor e têm a mesma raiz — entrada do usuário interpretada como instrução executável. -
Qual o padrão único que une SQLi, XSS e command injection, e qual a defesa correspondente para a command injection especificamente?
✓ Resposta:O padrão único é entrada não confiável sendo interpretada como instrução (SQL, JS, comando do SO, código). Para a command injection, a defesa é evitar chamar o SO com entrada do usuário; quando inevitável, usar APIs que separam comando e argumentos (argumentos como lista), validar por allowlist e aplicar menor privilégio — mantendo a fronteira entre dado e comando.