Injeçãode Comando
Injeçãode Comando
Descrição
Exemplos
Exemplo 1
O código a seguir é um invólucro em torno do comando cat UNIX que imprime o
conteúdo de um arquivo para a saída padrão. Também é injectável:
#include <stdio.h>
#include <unistd.h>
system(command);
return (0);
}
$ ./catWrapper Story.txt
When last we left our heroes...
Se catWrapper tinha sido programado para ter um nível de privilégio maior do que o
usuário padrão, comandos arbitrários podem ser executados com o maior privilégio.
Exemplo 2
O seguinte programa simples aceita um nome de arquivo como um argumento de linha de
comando, e exibe o conteúdo do arquivo de volta para o usuário. O programa é
instalado setuid root, porque se destina a uso como uma ferramenta de aprendizagem
para permitir que os administradores de sistema in-formação para inspecionar os
arquivos do sistema privilegiadas sem dar-lhes a capacidade de modificá-los ou
danificar o sistema.
Exemplo 3
O seguinte código de um programa privilegiado usa a variável de ambiente $ APPHOME
para determinar o diretório de instalação do aplicativo, e, em seguida, executa um
script de inicialização nesse diretório.
...
char* home=getenv("APPHOME");
char* cmd=(char*)malloc(strlen(home)+strlen(INITCMD));
if (cmd) {
strcpy(cmd,home);
strcat(cmd,INITCMD);
execl(cmd, NULL);
}
...
Como no Exemplo 2, o código deste exemplo permite que um invasor execute comandos
arbitrários com os privilégios elevados da aplicação. Neste exemplo, o atacante
pode modificar a variável de ambiente $ APPHOME para especificar um caminho
diferente, contendo uma versão maliciosa de INITCMD. Porque o programa não valida o
valor lido a partir do ambiente, controlando a variável de ambiente, o atacante
pode enganar o aplicativo em execução de código malicioso.
O atacante é variável usando o ambiente para controlar o comando que o programa
chama, de modo que o efeito do meio ambiente está expressa neste exemplo. Vamos
agora voltar nossa atenção para o que pode acontecer quando o atacante muda a forma
como o comando é interpretado.
Exemplo 4
O código abaixo é de um utilitário baseado na web CGI que permite que os usuários
alterem suas senhas. O processo de atualização de senha sob NIS inclui executar o
make no diretório / var / yp diretório. Note-se que desde que o programa atualiza
os registros de senhas, que foi instalado com setuid root.
O programa invoca fazer como se segue:
Exemplo 5
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
if(argc != 2) {
printf("Error: Please enter a program to time!\n");
return -1;
}
memset(&command, 0, sizeof(command));
system(command);
return 0;
}
* Se este fosse um binário suid, considere o caso quando um atacante entra o
seguinte: 'ls; cat / etc / shadow'. No ambiente Unix, comandos shell são separados
por um ponto e vírgula. Agora podemos executar comandos do sistema à vontade!
* Java:
Existem muitos sites que lhe dirá que Runtime.exec do Java é exatamente o mesmo que
a função do sistema de C. Isto não é verdade. Ambos permitem que você invocar um
novo programa / processo. No entanto, a função do sistema de C passa seus
argumentos para o shell (/ bin / sh) para ser analisado, enquanto Runtime.exec
tenta dividir a string em um array de palavras, em seguida, executa a primeira
palavra na matriz com o resto das palavras como parâmetros. Runtime.exec não tenta
invocar o shell em qualquer ponto. A principal diferença é que grande parte da
funcionalidade fornecida pelo shell que poderia ser usado para o mal (o
encadeamento de comandos usando o "&", "&&", "|", "| |", etc, redirecionamento de
entrada e saída) seria simplesmente acabar como um parâmetro que está sendo passado
para o primeiro comando, e, provavelmente, causando um erro de sintaxe, ou ser
jogado fora como um parâmetro inválido.