# FHTTP Kit by Xianur0 # Copyright (C) 2011 Oscar García López (http://hackingtelevision.blogspot.com) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # xianur0.null@gmail.com # http://hackingtelevision.blogspot.com/ package fingerprint; use Switch; use lib("tools"); use tools; $mostrartotal = ""; $rotativos = ""; $soportetracea = ""; $proxysing = ""; $http10resa = ""; $http09resa = ""; $idioma = &main::mods("--lang"); # Fingerprint sub grafico { my $ventana = Gtk2::Window->new('toplevel'); $ventana->set_title("HTTP Fingerprint"); $ventana->set_default_icon_from_file("icono.jpg"); $ventana->set_border_width(5); $ventana->set_default_size(20, 20); $ventana->set_resizable(FALSE); $hbox = Gtk2::VBox->new(0, 0); $hbox->set_border_width(5); $caja = Gtk2::HBox->new(0,0); $etiqueta = Gtk2::Label->new('URL: '); $url = Gtk2::Entry->new(); &main::share($url); $caja->pack_start($etiqueta, FALSE,FALSE,2); $caja->pack_start($url, FALSE,FALSE,2); $recur = Gtk2::CheckButton->new_with_label(dic::fingerlabels($idioma,0)); &main::share($recur); $boton = Gtk2::Button->new(dic::fingerlabels($idioma,1)); $boton->signal_connect('clicked' => sub {$threadproxy = threads->create('iniciarfingerprint'); }); my $vp = Gtk2::Viewport->new (undef,undef); my $scrolled = Gtk2::ScrolledWindow->new(); $scrolled->add($vp); $mostrar = Gtk2::Label->new(dic::fingerlabels($idioma,2)); $vp->add($mostrar); &main::share($mostrar); $imagen = Gtk2::Image->new_from_file("logo.png"); $hbox->pack_start($imagen, FALSE, FALSE, 2); $hbox->pack_start($caja, FALSE, FALSE, 2); $hbox->pack_start($recur,FALSE,FALSE,2); $hbox->pack_start($boton, FALSE, FALSE, 2); $hbox->pack_start($scrolled,FALSE,FALSE,2); $hbox->show; $ventana->add($hbox); $ventana->show_all; $ventana->resize(50, 200); Gtk2->main; } sub new { if($#ARGV >= 2 && &main::mods("Gtk2") != 1) { iniciarfingerprint(); exit; } elsif(&main::mods("Gtk2") == 1) {grafico();} else {die(dic::comunes($idioma,0).": fhttp.pl 0 [url] [".dic::fingerlabels($idioma,0)." 1|0]\n");} } sub datechecker { @dates = @_; my $contador = 0; my $totalseg = 0; my $contadord = 0; my $timeanterior = 0; my (@dia,@mes,@anio,@hora,@horas,@minutos,@segundos,@segt1,@diferencias); foreach(@dates) { ($dia[$contador],$mes[$contador],$anio[$contador],$hora[$contador],$horas[$contador],$minutos[$contador],$segundos[$contador],$segt1[$contador]) = tools::dateparser($_); if($contador > 0) { my $timediff = ($segt1[$contador]-$timeanterior); $totalseg += ($timediff > 0) ? $timediff : 0; $diferencia[$contadord] = $segt1[$contador] - $segt1[$contador-1]; $diferencia[$contadord] =~ s/^-//; switch(true) { case {$dia[$contador-1] ne $dia[$contador]} { rotativodetectado("date-day",$dia[$contador-1],$dia[$contador]); } case {$mes[$contador-1] ne $mes[$contador]} { rotativodetectado("date-month",$mes[$contador-1],$mes[$contador]); } case {$anio[$contador-1] ne $anio[$contador]} { rotativodetectado("date-year",$anio[$contador-1],$anio[$contador-1]); } case {$diferencia[$contadord] > 10 || $timediff < 0}{ rotativodetectado("date-seconds",10,$diferencia); } } $contadord++; } $timeanterior = $segt1[$contador]; $contador++; } agregaramostrar(dic::comunes($idioma,1).": ".(($totalseg > 0) ? ($totalseg/$contador) : 0)." seg\n") } sub agregaramostrar { $text = $_[0]; $mostrartotal .= $text; print &main::red, $text, &main::reset; } sub rotativodetectado { my ($tipo,$val1,$val2) = @_; print dic::mensajes($idioma,0)."...\n"; $rotativos .= "[!] ".dic::mensajes($idioma,1).":\n-".dic::mensajes($idioma,2)." : ".$tipo."\n- ".dic::mensajes($idioma,3).": ".$val1."\n- ".dic::mensajes($idioma,4).": ".$val2."\n"; } sub iniciarfingerprint { my @encabezadoss = ("User-Agent: Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.1.8) Gecko/20100214 Ubuntu/9.10 (karmic) Firefox/3.5.8"); $mostrar->set_text(dic::mensajes($idioma,5)."...\n") if(&main::mods("Gtk2")); my $puerto = 80; my $path = "/"; my $ssl = 0; my $host = ""; my $resto = ""; my $scheme = ""; my $ciclos = 1; my $keepalive; my $keepatotal; my $keepsoportados; my $banner; my $proxycoincidencias; my $http09res; my $http10res; my $hostenvio = ""; my $puertoenvio = ""; my $urlactual = $ARGV[1] || ((&main::mods("Gtk2") == 1) ? $url->get_text : die("URL Invalida!\n")); ($scheme,$resto) = ($urlactual =~ /^(https?):\/\/(.*)/); $mostrar->set_text(dic::mensajes($idioma,5).": ".$urlactual) if(&main::mods("Gtk2")); $ssl = 1 if($scheme eq "https"); if($resto =~ /^(.*?)\/(.*)/) { $path = "/".$2; $resto = $1; } if($resto =~ /^(.+):([\d]+)$/) { $host = $1; $puerto = $2; print "Host: ".$host."\nPuerto: ".$puerto."\n"; } else { $host = $resto; $puerto = "443" if($ssl == 1); } if(&main::mods("Cheat---proxy") =~ /^([^:]+):(\d+)$/) { $hostenvio = $1; $puertoenvio = $2; } else { $hostenvio = $host; $puertoenvio = $puerto; } print dic::mensajes($idioma,6).": ".$hostenvio.": ".$puertoenvio."\n\n"; $mostrar->set_text(join "","SSL: ",$ssl,"\n",dic::comunes($idioma,2),": ",$puerto,"\n",dic::comunes($idioma,3),": ",$host,"\n",dic::comunes($idioma,4),": ",$path,"\n") if(&main::mods("Gtk2")); if(($puerto != 80 && $ssl == 0) || (($puerto != 443 || $puerto ne "https") && $ssl == 1)) { $lineaurl = join "",$scheme,"://",$host,":",$puerto,$path; } else { $lineaurl = join "",$scheme,"://",$host,$path; } $ciclos = 10 if($ARGV[2] == 1 || (&main::mods("Gtk2") && $recur->get_active)); for($ia = 0; $i< $ciclos; $i++) { my $paquete = http->new("GET",$lineaurl,"1.1"); $paquete->agregarencabezados(0,@encabezadoss); $paquete->modo(1); my $tamanocontenido = length(join "","GET ",$lineaurl," HTTP/1.1\r\nHost: ",$host,"\r\nConnection: Keep-Alive\r\nProxy-Connection: Keep-Alive\r\n\r\n"); $paquete->agregarencabezadosfinal(0,("Content-Length: ".$tamanocontenido)); $paquete->siguiente("GET",$lineaurl,"1.1"); $paquete->agregarencabezados(1,@encabezadoss); $paquete->siguiente("GET","http://localhost/","1.1"); $paquete->print; %estructura = $paquete->enviar($hostenvio,$puertoenvio,$ssl); # analizador if($estructura{total} > 1) { $persistente = 1; $mostrar->set_text(dic::mensajes($idioma,7)."\n".dic::mensajes($idioma,8)."...\n") if(&main::mods("Gtk2") ); my $parser = parser->new(); my ($soportados,%estructuratmp) = $parser->soportados($lineaurl,$host,$puerto,$ssl,0,"",$hostenvio,$puertoenvio); my @dates = (); if($soportados >= 100) { &agregaramostrar(join "","[!] ",dic::mensajes($idioma,9),"!\n"); } else { rotativodetectado("keep-alive-supported",$estructura{total},$soportados) if($soportados < $estructura{total}); $estructura{encabezados}[$id]{$nombre} = $valor; &agregaramostrar(join "","[-] ",dic::mensajes($idioma,10)," ".$soportados." ",dic::mensajes($idioma,11),"\n"); } for($ina = 0; $ina < $soportados;$ina++) { unshift(@dates,$estructuratmp{encabezados}[$ina]{"Date"}); } datechecker(@dates); } else { $mostrar->set_text(dic::mensajes($idioma,12)."!\n") if(&main::mods("Gtk2")); } if($ciclos > 1) { if($keepalive =~ /^\d+$/ && $persistente != $keepalive) { rotativodetectado("keep-alive",$keepalive,$persistente); } if($keepatotal =~ /^\d+$/ && $estructura{total} != $keepatotal) { rotativodetectado("keep-alive-total",$keepatotal,$estructura{total}); } if($keepsoportados =~ /^\d+$/ && $soportados != $keepsoportados) { rotativodetectado("keep-alive-soportados",$keepsoportados,$soportados); } if($banner =~ /^(.+)$/ && $banner ne $estructura{encabezados}[0]{Server}) { rotativodetectado("server-banner",$banner,$estructura{encabezados}[0]{Server}); } $keepalive = $persistente; $keepatotal = $estructura{total}; $keepsoportados = $soportados; $soportetrace = $soportetracea; $banner = $estructura{encabezados}[0]{Server}; # termina el if de los ciclos } my %signature = ( 'Apache/2.x','Connection:\sKeep-Alive', 'Microsoft-IIS/7.x','Connection:\skeep-alive', 'Microsoft-IIS/6.x','^HTTP/1.(1|0)\s(.*?)(\r\n|\n)Content-Length:\s', 'Microsoft-IIS/x.x','Server:\s(.*?)(\r\n|\n)X-Powered-By:\s' ); my %signature2 = ( 'Microsoft-IIS/7.x','Server:\s(.*?)(\r\n|\n)X-AspNet-Version:\s', 'Microsoft-IIS/6.x','Server:\s(.*?)(\r\n|\n)P3P:(\w*?)=(.*?)(\r\n|\n)X-Powered-By:\sASP\.NET', ); my %signature3 = ( 'Microsoft-IIS/7.x','Server:\sMicrosoft-HTTPAPI', ); my %proxys = ( 'Squid/2.x','Via:\s(.*?)\(squid\/2', 'NetCache','Via:\s(.*?)\(NetCache', 'Proxy Generico','Proxy-Connection:\s', ); my %proxys2 = ( 'NetCache','Server:\sNetCache\sappliance', ); my $apache = 0; my %servidores = (); my $total = 0; my $totaldb = 0; my $http09 = 0; # if($persistente == 1) { &agregaramostrar(join "","[-] ",dic::mensajes($idioma,13),": ",$estructura{encabezados}[0]{Server},"\n"); if($estructura{total} > 2) { &agregaramostrar("[-] ".dic::comunes($idioma,6).": Cherokee Web Server o Servidor Proxy\n"); } else { $http09 = 1; } for($in=0;$in<$estructura{total};$in++) { print &main::red, dic::comunes($idioma,5).": ".dic::comunes($idioma,6)." -> FHTTP\n", &main::reset; print $estructura{encabezado}[$in]."\n\n"; foreach $key (sort keys %proxys) { $totaldb++; $value = $proxys{$key}; if($estructura{encabezado}[$in] =~ m/$value/) { $total++; $servidores{$key}++; } } foreach $key (sort keys %signature) { $totaldb++; $value = $signature{$key}; if($estructura{encabezado}[$in] =~ m/$value/) { $total++; $servidores{$key}++; } } foreach $key (sort keys %signature2) { $totaldb++; $value = $signature2{$key}; if($estructura{encabezado}[$in] =~ m/$value/) { $total++; $servidores{$key}++; } } foreach $key (sort keys %signature3) { $totaldb++; $value = $signature3{$key}; if($estructura{encabezado}[$in] =~ m/$value/) { $total++; $servidores{$key}++; } } foreach $key (sort keys %proxys2) { $totaldb++; $value = $proxys2{$key}; if($estructura{encabezado}[$in] =~ m/$value/) { $total++; $servidores{$key}++; } } &agregaramostrar(join "","[-] ",dic::mensajes($idioma,14),": ",$total,"/",$totaldb,"\n") if($total > 0); foreach $key (sort keys %servidores) { $value = $servidores{$key}; $servidores{$key} = ""; if($value ne "") { $porcentaje = (100/$total)*$value; $http09 = 1 if($porcentaje == 50); $sing = join "",$key,": ",$porcentaje,"% (",$value," ",dic::comunes($idioma,7),")\n"; $proxysing .= $sing; &agregaramostrar($sing); } } $total = 0; # probamos el trace para ver como pasan los datos :)... &agregaramostrar("[-] Trace:\n"); my $paquete = http->new("TRACE",$lineaurl,"1.0"); $paquete->agregarencabezados(0,("X: 1")); $paquete->print; %estructura = $paquete->enviar($hostenvio,$puertoenvio,$ssl); if($estructura{encabezado}[0] =~ /(\r\n|\n)Content-Type: message\/http(\r\n|\n)/) { print &main::red, (dic::comunes($idioma,8).": Servidor -> FHTTP:\n"), &main::reset; $estructura{contenidos}[0] =~ s/^(\r|\n|\s)//g; $estructura{contenidos}[0] =~ s/(\r|\n|\s)$//g; print $estructura{contenidos}[0]; $enviado = $paquete->paquete; $enviado =~ s/^(\r\n|\n|\s)//g; $enviado =~ s/(\r\n|\n|\s)$//g; if($estructura{contenidos}[0] ne $enviado) { $soportetracea = "\"!=\" (proxy?)"; &agregaramostrar("- \"!=\" (proxy?)\n"); } else { $soportetracea = "=="; &agregaramostrar("- ==\n"); } } else { $soportetracea = dic::mensajes($idioma,15); &agregaramostrar("- NO TRACE\n"); } # exit if($http09 == 0); &agregaramostrar("[-] HTTP/0.9:\n"); my $paquete = http->new("GET",$lineaurl,"0.9"); $paquete->print; %estructura = $paquete->enviar($hostenvio,$puertoenvio,$ssl); if($estructura{estados}[0] =~ /^HTTP\/1\.1 505/i) { print &main::red, (dic::comunes($idioma,9).": ".dic::comunes($idioma,6)." -> FHTTP:\n"), &main::reset; print $estructura{estados}[0]."\n\n"; $http09resa = "[!-] ",dic::comunes($idioma,6),": No IIS/Apache!\n"; &agregaramostrar($http09resa); } elsif($estructura{estados}[0] =~ /^HTTP\/1\.1/) { print &main::red, (dic::comunes($idioma,9).": ".dic::comunes($idioma,6)." -> FHTTP:\n"), &main::reset; print $estructura{estados}[0]."\n\n"; $http09resa = "- ".dic::comunes($idioma,6).": IIS\n"; &agregaramostrar($http09resa); } else { $http09resa = "- ".dic::comunes($idioma,6).": Apache\n"; &agregaramostrar($http09resa); } &agregaramostrar("[-] HTTP/1.0:\n"); my $paquete = http->new("GET",$lineaurl,"1.0"); $paquete->print; $http10resa = ""; %estructura = $paquete->enviar($hostenvio,$puertoenvio,$ssl); if($estructura{estados}[0] =~ /^HTTP\/1\.0/i) { $http10resa = "[!-] No IIS/Apache!\n"; &agregaramostrar($http10resa); } else { $http10resa = "- Normal (HTTP/1.1)\n"; &agregaramostrar($http10resa); } if($persistente == 1) { &agregaramostrar("[-] HTTP/1.0 + Keep-Alive:\n"); my $paquete = http->new("GET",$lineaurl,"1.0"); $paquete->modo(1); $paquete->siguiente("GET",$lineaurl,"1.0"); $paquete->print; %estructura = $paquete->enviar($hostenvio,$puertoenvio,$ssl); if($estructura{total} > 1) { $http10resa .= "- Keep-Alive + HTTP/1.0 [!]\n"; &agregaramostrar($http10resa); } else { $http10resa .= "- NO Keep-Alive + HTTP/1.0\n"; &agregaramostrar($http10resa); } } # comienza el siguiente analisis... if($ciclos > 1) { if($soportetrace =~ /^(.+)$/ && $soportetrace ne $soportetracea) { rotativodetectado("result-trace",$soportetrace,$soportetracea); } if($proxysingb =~ /^(.+)$/ && $proxysing != $proxysingb) { rotativodetectado("firm-proxys",$proxysingb,$proxysing); } if($http09res =~ /^(.+)$/ && $http09res != $http09resa) { rotativodetectado("http-0.9-result",$http09res,$http09resa); } if($http10res =~ /^(.+)$/ && $http10res != $http10resa) { rotativodetectado("http-1.0-result",$http10res,$http10resa); } } $soportetrace = $soportetracea; $proxysingb = $proxysing; $http09res = $http09resa; $http10res = $http10resa; } # termina el siguiente analisis. # /analizador if($rotativos ne "") { &agregaramostrar($rotativos); } $persistente = ""; $estructura{total} = ""; $soportados = ""; $estructura{encabezados}[0]{Server} = ""; } # analizamos los separadores permitidos para intentar detectar el tipo de servidor web &agregaramostrar("[-] ".dic::comunes($idioma,10).": \n"); open REGLAS,"reglas.txt"; %reglas = (); @estados = ("501","400","502"); my $firma = ""; while($linea = ) { if($linea =~ /^separador:\s+/) { ($separador,$servidor) = ($linea =~ /^separador:\s+(.+)=>(.+)$/); $servidor =~ s/