Outro dia encontrei um programa que me permitiu selecionar a partir de um conjunto de consultas pré-embaladas e depois me comuniquei com um servidor para recuperar a resposta à consulta selecionada. Comecei a me perguntar quando percebi que o programa nunca pedia uma senha para autenticação com o servidor. Acontece que a senha estava embutida no programa. O autor explicou que estava tudo bem porque 1) era um arquivo binário para que ninguém pudesse lê-lo e 2) se pudessem lê-lo, não conseguiriam encontrar a cadeia de senhas.
Nenhuma destas razões é válida e eu gostaria de usar este posto para demonstrar isso. Meu programa de exemplo apenas escreve a "senha" no terminal, mas a única diferença entre ela e um programa de produção real é o número de cordas que um usuário malicioso teria que pesquisar.
#include <stdio.h>
#include <string.h>
main ()
{
char password [9] = {"secret"};
printf ("This is the password: %sn", password);
}
|
Figura 1 - Programa básico com senha embutida |
Quando executado, ele exibe
x1
Esta é a senha: segredo
pronto 14:12:16
|
Figura 2 - Execução do programa básico |
Para exibir as strings no módulo do programa, nosso usuário malicioso pode usar o comando strings do >system>gnu_library>bin directory. O -n5 limita a saída para strings de 5 caracteres ou mais. Eu trunquei a saída (. . . .) para encurtar a exibição, mas você pode ver que a senha é uma das primeiras strings exibidas. Ter a senha próxima a palavras-chave como "login" ou "password" ou a um ID de usuário identificável como "admin", "root" ou "sql" torna a busca mais fácil.
>system>gnu_library>bin>strings -n5 x1.pm
bind, Release 17.1.beta.be
phx_vos#
Noah_Davids.CAC
Pré-lançamento
Esta é a senha: %s
secreto
s$start_c_program
_preensão_cleanup
sair
. . . . .
|
Figura 3 - Usando o comando GNU strings para encontrar todas as strings com mais de 4 caracteres no módulo do programa |
Se o comando strings não estiver disponível, nosso usuário malicioso pode simplesmente exibir o módulo do programa. Suspeito que todos nós tenhamos feito isto por acidente e embora não seja bonito, ele exibirá a senha. Eu trunquei novamente a saída e novamente você pode ver a senha.
d x1.pm
%phx_vos#m16_mas>SysAdmin>Noah_Davids>x1.pm 11-01-13 14:13:59 mst
`00`01`00`1Abind, Release 17.1.beta.be`00`00`00`00`00`00`00`04ctp
`00`00`00`00`0
+`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`0
0phx_vos
+#`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`
00`00Noa
. . . .
+`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`C
D'`8B`C0
+`00`00`00`00 Esta é a senha: %s
`00`00`00`00`00`00`00secret`00`00`00`00`00`00`00`04`B0`00`00`00`00`01`00
`00`00,`
+`00`00`04`00`00`00`03@`00`FF`F8`FF`FE`00`04main`00`00`83`EC`2C`C7D$$`00
. . . .
|
Figura 4 - Exibição do módulo do programa para encontrar a senha |
Há várias alternativas para incorporar a senha no programa.
A senha pode ser colocada em um arquivo e o programa pode ler o arquivo. Somente as pessoas com "necessidade de correr" têm acesso lido ao arquivo e todos os outros têm acesso nulo. É claro que "necessidade de executar" pode não se equiparar a "necessidade de conhecer a senha". Além disso, há sempre o perigo de alguém mudar erroneamente o acesso.
Uma alternativa é manter a seqüência de senhas no programa e apenas limitar o acesso ao programa. Esta solução também sofre com o problema "é fácil mudar uma lista de acesso". Se o programa for mantido no mesmo diretório que outros programas que podem ser executados por qualquer pessoa, a probabilidade de uma mudança na lista de acesso aumenta.
Finalmente, você pode manter a senha no módulo do programa, mas de alguma forma ofuscar a corda. O programa a seguir mostra uma maneira simples de fazer isto.
#include <stdio.h>
#include <string.h>
main ()
{
char obfuscate [9] = {0x0c, 0x81, 0xe2, 0x94, 0xe6, 0x9c};
char key [9] = {127, 228, 129, 230, 131, 232, 133, 234, 135};
char password [9];
int i;
for (i = 0; i < strlen (obfuscate); i++)
password [i] = obfuscate [i] ^ key [i];
password [i] = 0x0;
printf ("This is the password: %sn", password);
}
|
Figura 5 - Programa com cadeia de senhas ofuscadas |
Como você pode ver tudo o que faz é pegar os caracteres ofuscados e XOR com outro conjunto de caracteres-chave para criar a senha. A execução do programa produz a mesma saída que o primeiro programa.
x2
Esta é a senha: segredo
pronto 14:12:51
|
Figura 6 - Execução de programa ofuscado |
Mas uma busca por cordas não mostra nada que se pareça com a senha
>system>gnu_library>bin>strings -n5 x1.pm bind, Release 17.1.beta.be phx_vos# Noah_Davids.CAC Pré-lançamento Esta é a senha: %s s$start_c_program _preensão_cleanup sair . . . . |
Figura 7 - O comando strings não mostra mais a senha |
E enquanto exibe o arquivo mostrará os caracteres da senha ofuscada e os caracteres-chave que você tem que saber exatamente onde procurá-los e também como eles são combinados para criar a senha.
d x2.pm
%phx_vos#m16_mas>SysAdmin>Noah_Davids>x2.pm 11-01-13 14:15:27 mst
. . . .
+`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`CD'`8B`
C0`00`0
+0`00`00 Esta é a senha: %s
`00`00`00`00`00`00`00`0C`81`E2`94`E6`9C`00`00`00`00`00`00`00`00`00`00`7F
`E4`81`
+E6`83`E8`85`EA`87`00`00`00`00`04`B0`00`00`00`00`01`00`00`00`00`00`00`0
4`01`B0
+`00`03@`00`FF`F0`00`08`FF`FE`00`04main`00`00`83`EC`89$X`89t$T`89|$P`C
7D$L`00
|
Figura 8 - O módulo do programa de exibição não mostra mais a senha reconhecível |
Esta ainda não é uma solução perfeita, já que o módulo do programa pode ser desmontado para descobrir como a senha é gerada. A desmontagem do programa ainda requer muito mais sofisticação do que apenas a exibição do módulo do programa.
Sou de duas mentes sobre colocar a cadeia de senhas ofuscadas em um arquivo e depois proteger o arquivo através de uma lista de acesso. Por um lado, se a senha precisar ser mudada, esta é uma solução muito melhor do que incorporar a cadeia de senhas ofuscada no programa. Por outro lado, suspeito que mesmo que haja outras opções de configuração no arquivo, colocar a cadeia de caracteres no arquivo dará ao nosso usuário malicioso menos cadeias de senhas potenciais para investigar. É claro que ele ainda precisará obter acesso ao arquivo e então terá que descobrir a técnica e a chave de ofuscação.
Um último ponto, como eu gerei os caracteres da senha ofuscada? O bom da operação XOR é que ((A XOR B) XOR B) é igual a A, então eu apenas escrevi um pequeno programa para pegar a senha original XOR os caracteres com minha chave e imprimir o resultado.
#include <stdio.h>
#include <string.h>
main ()
{
char password [9];
char key [9] = {127, 228, 129, 230, 131, 232, 133, 234, 135};
char newPW [9];
int i;
strcpy (password, "secret");
for (i = 0; i < strlen (password); i++)
{
newPW [i] = password [i] ^ key [i];
printf ("%xn", newPW [i]);
}
}
|
Figura 9 - Programa para gerar senha ofuscada |