Random IRC quote :      <matalaz> pues sigue averrante abominacion amorfica

Fscan 1.0: Programando con la API de HTTP de FSCAN

Para los que lo estabais esperando, aquí está la versión compilada para win32 de Fscan 1.0 (FHScan), orientado a automatizar las tareas de revisión de routers y otros dispositivos HTTP.

FHscan Core api es una librería de HTTP/1.1 que fue desarrollada a raíz del proyecto «Fast HTTP Vulnerability Scanner«, hasta llegar a convertirse en el núcleo del mismo. Esta librería debía cumplir una serie de requisitos, velocidad, sencillez y flexibilidad, y por supuesto, dado que su objetivo principal era ser utilizada para ataques de fuerza bruta, soporte de varios mecanismos de autenticación (basic, digest y NTLM) así como soporte de compresión gzip/deflate, callbacks y SSL. El resultado es prometedor y dado que es portable y que me gustaría que la gente pudiese colaborar en su desarrollo, voy a dejar el rollo de exploits por una vez y os voy a contar algún ejemplo de como realizar aplicaciones mas o menos sencillas usando esta API.

Lo único que debéis incluir en vuestra aplicación es el fichero «HTTP.h» y una vez hecho esto, inicializar el motor de HTTP con InitHTTPApi(). Esta función se encarga de manter en memoria varias tablas que gestionan las conexiones activas, aunque eso es totalmente transparente para nosotros.

Antes de establecer una conexión es necesario generar un pseudoHandle al sistema remoto. Esto se consigue con la llamada InitHTTPConnectionHandle() cuyos parámetros son el host remoto, el puerto, y si la conexión usa o no SSL.

HTTPHANDLE HTTPHandle=InitHTTPConnectionHandle("blog.48bits.com",80,0);

Una vez generado el Handle, podemos empezar a generar peticiones. Todas estas peticiones se almacenan en una estructura PREQUEST que comentaremos más adelante. Véase un ejemplo de como realizar una peticion a la web de 48bits.

#include "HTTP.h"

void main(int argc, char *argv[]) {

InitHTTPApi(); //Inicialización del motor HTTP

HTTPHANDLE HTTPHandle = InitHTTPConnectionHandle("blog.48bits.com",80,0);

PREQUEST DATA=SendHttpRequest(HTTPHandle,NULL,"GET","/",NULL,NULL,NULL,NO_AUTH);
//do stuff with the data….

if (DATA) FreeRequest(DATA); //liberamos la memoria de la petición

CloseHTTPConnectionHandle(HTTPHandle); //Liberamos el Handle

CloseHTTPApi(); //Paramos el motor HTTP
}


La función SendHttpRequest() tiene 8 parámetros de los cuales 5 de ellos son opcionales.


SendHTTPRequest Function

– El primer parámetro es HANDLE al servidor HTTP remoto.
– El segundo parámetro es un vhost opcional que se enviará en la cabecera «Host: vhost». Si no se especifica, se utilizará el valor de la llamada InitHTTPConnectionHandle()
– El tercer parámetro es el método HTTP utilizado. Este puede ser «GET»,»POST»,»PUT»,»WHATEVER»,…
– El cuarto parámetro son los datos enviados al servidor. en una petición GET, para acceder a «http://blog.48bits.com/?p=287» deberíamos incluir «p=287» en ese parámetro
– El quinto y sexto parámetro son también opcionales y especifican el usuario y la contraseña.
– El séptimo y último parámetro, es el tipo de autenticación utilizado. Si dejamos el valor por defecto ( 0 o NO_AUTH) el sistema lo negociará automáticamente.

Dado que ya está más o menos claro como enviar una petición, vamos a ver como se estructura la información devuelta, es decir, la estructura PREQUEST.

char    hostname [256]; //<– host o vhost sobre el que se ha hecho la petición
int     ip; //<- dirección ip  de un sockaddr_in
int     port; //<- puerto al que se establece la conexión
int     NeedSSL; //<- Indica si la petición ha utilizado SSL (1) o no ( 0)
char    url [512]; //<- dirección URL contra la que se ha realizado la peticion HTTP
PHTTP_DATA      request; //<- DATOS ENVIADOS
PHTTP_DATA      response; //<- DATOS RECIBIDOS
char *  server;   //<- banner del servidor Web
unsigned int    status  //<- código HTTP de la respuesta (200 si la pagina existe, 401 para acceso denegado,..)
unsigned int    challenge //<- tipo de autenticacion requerida por el servidor web (en base a la cabecera www-authenticate)
 

un sencillo ejemplo:

printf("Host: %s port: %i URL: %s – status: %i\n",DATA->hostname, DATA->port, DATA->url, DATA->status);

devolvería:

Host: blog.48bits.com port: 80 URL: /index.html – status: 200

Por último queda comentar los datos almacenados dentro de la estructura PHTTP_DATA (campos request y response). Esta es también una estructura sencilla que contiene los siguientes campos

char *Header;  // Cabeceras HTTP enviadas o recibidas
unsigned int    HeaderSize; //Tamaño de las cabeceras HTTP
char *Data; //Datos enviados (por ejemplo en una peticion POST) o recibidos (por ejemplo el codigo html)
unsigned int    DataSize; //tamaño del buffer
 

para ilustrar con mas detalle esto, aqui viene el ejemplo final 🙂

#include "HTTP.h"
void main(int argc, char *argv)
{
InitHTTPApi();
HTTPHANDLE HTTPHandle = InitHTTPConnectionHandle("blog.48bits.com",80,0);
if (HTTPHandle) {
 PREQUEST DATA= SendHttpRequest(HTTPHandle,NULL,"GET","/","p=290",NULL,NULL,NO_AUTH);
 if (DATA) {
  printf("Host: %s port: %i URL: %s – status: %i\n",DATA->hostname, DATA->port, DATA->url, DATA->status);
  printf("Peticion %i bytes:\n%s\n",DATA->request->HeaderSize,DATA->request->Header);
  printf("Respuesta %i bytes\n%s\n",DATA->response->HeaderSize,DATA->response->Header);
  printf("Datos %i bytes\n%s\n",DATA->response->DataSize,DATA->response->Data);
  FreeRequest(DATA);
 }
 CloseHTTPConnectionHandle(HTTPHandle);
}
}       
 

y la salida devuelta por la aplicación

Host: blog.48bits.com port: 80 URL: / – status: 200
Peticion 136 bytes:

GET /?p=290 HTTP/1.1
Host: blog.48bits.com
User-Agent: Mozilla/5.0 (FSCAN)
Accept-Encoding: gzip, deflate
Connection: keep-alive

Respuesta 433 bytes
HTTP/1.1 200 OK
Date: Thu, 13 Nov 2008 13:12:15 GMT
Server: Apache/2.2.3 (Debian) DAV/2 SVN/1.4.2 mod_python/3.2.10 Python/2.4.4 PHP/5.2.0-8+etch13 mod_ssl/2.2.3
OpenSSL/0.9.8c mod_perl/2.0.2 Perl/v5.8.8
X-Powered-By: PHP/5.2.0-8+etch13
X-Pingback: http://blog.48bits.com/xmlrpc.php
Vary: Accept-Encoding
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
Content-Length: 19038

Datos 19038 bytes
//aqui va todo el código html devuelto por la página web..

Obviamente este es un ejemplo sencillo, pero es mucho más potente. Como primicia, si queréis mas información, podéis descargar la librería HTTP de Fscan en http://www.tarasco.org/security/fscan-core/ y consultar la documentación HTML que hay generada.

7 Comentarios para “Fscan 1.0: Programando con la API de HTTP de FSCAN”

  1. Comment por Luis | 11/13/08 at 6:05 pm

    muy guapo!

  2. Comment por Thor | 11/13/08 at 6:23 pm

    Justo lo que andaba buscando 😉
    Gracias !

  3. Comment por Lechón | 11/13/08 at 7:19 pm

    Muchas gracias por currarte un artículo tan bien explicado…
    Para los que estamos aprendiendo, no tiene precio!
    Gracias one more time.

    PD: Me parto el ojete con las IRC quotes XD

  4. Comment por carpeta | 11/28/08 at 10:28 am

    Excelente artículo.
    He creado un proyecto en blanco en visual studio 6 y al linkar me genera los siguientes errores:

    HTTPCore.obj : error LNK2001: unresolved external symbol «void __cdecl UnLockMutex(void *)» (?UnLockMutex@@YAXPAX@Z)
    IoFunctions.obj : error LNK2001: unresolved external symbol «void __cdecl UnLockMutex(void *)» (?UnLockMutex@@YAXPAX@Z)

    Los includes correspondientes al fichero Threading.h están puestos. Qué estoy haciendo mal?
    Si lo intento compilar también me da unos errors similares al linkar.

    Gracias y saludos

  5. Comment por Tarasco | 11/29/08 at 6:06 pm

    Hola,

    Voy a verificarlo con un proyecto nuevo y te comento algo, pero me da la impresión de que falta algún define en las propiedades del proyecto.

    mandame un email a atarasco [a t] gmail.com y te echo una mano.

    Andrés Tarascó

  6. Comment por carpeta | 12/02/08 at 8:45 pm

    Hola de nuevo,

    Antes de nada, gracias por responder.
    Al final ya me funcionó en el visual studio, no había puesto correctamente las opciones del proyecto a la hora de crear la librería.
    Eso sí, he tenido que dejar fuera del proyecto el fichero httprelay.cpp, puesto que contiene un include a httprelay.h, y ese fichero no está en el paquete FSCAN_HTTPCore_API.zip que habéis puesto para descargar, no se si es un error o si debe ser así y estoy haciendo mal alguna otra cosa…
    En cualquier caso sigo haciendo pruebas

    Un saludo

  7. Comment por sha0 | 12/05/08 at 7:51 pm

    Que currao, siguiendo a raja tabla el rfc 🙂

Se han cerrado los comentarios