En la última Campus Party, como comenté en su post, estuve bastante tiempo con el concurso de seguridad web. Muchas veces para ir probando a mandar peticiones web concretas, GET o POST, había que usar “algo” que lo hiciese. Las opciones son varias, se podría usar un proxy, pero con él nos limitamos el poder tratar la respuesta del servidor o hacer cosas algo más complejas que una simple petición, esto mismo se puede aplicar a usar un telnet contra el servidor web remoto, así que al final, hay que usar un lenguaje de programación desde el cual abrimeros un socket contra el puerto 80 del servidor web en cuestión, por el cual hablaremos HTTP 1.1.
Un amigo que también participó en el concurso, OddBug, como es un poco windosero (aunque ahora es medio GentooManPr0 xD) usó Visual Basic :o, en mi caso opté por usar Perl porque mola mogollón :). Así que vamos al asunto!, como narices crear una petición (y obtener la respuesta por parte del servidor) http. Vamos a crear un socket y ya está, más facil no puede ser :). Tenemos dos formas, la tradicional:
#! /usr/bin/perl -w
use Socket;
use strict;
my( $host, $in_addr, $proto, $port, $addr, $file);
$host = "www.marca.es";
$file = "/"; # el index vamos...
$port = 80;
$proto = getprotobyname('tcp');
$in_addr = inet_aton($host);
$addr = sockaddr_in($port, $in_addr);
# creamos el socket y conectamos al servidor
socket(S, AF_INET, SOCK_STREAM, $proto) or die "socket: $!";
connect(S, $addr) or die "connect: $!";
# para flushear nada mas escribir en el socket
select(S); $| = 1; select(STDOUT);
# Una peticion normal GET
print S "GET $file HTTP/1.1\nHOST: $host\n\n";
while(<S>)
{
print;
} |
#! /usr/bin/perl -w
use Socket;
use strict;
my( $host, $in_addr, $proto, $port, $addr, $file);
$host = "www.marca.es";
$file = "/"; # el index vamos...
$port = 80;
$proto = getprotobyname('tcp');
$in_addr = inet_aton($host);
$addr = sockaddr_in($port, $in_addr);
# creamos el socket y conectamos al servidor
socket(S, AF_INET, SOCK_STREAM, $proto) or die "socket: $!";
connect(S, $addr) or die "connect: $!";
# para flushear nada mas escribir en el socket
select(S); $| = 1; select(STDOUT);
# Una peticion normal GET
print S "GET $file HTTP/1.1\nHOST: $host\n\n";
while(<S>)
{
print;
}
Que es un poco fea, bastante similar a C, y no muy limpia. Y la forma maja, usar los modulos de CPAN que hacen grande a Perl. Lo anterior queda simplificado a esto:
#! /usr/bin/perl -w
use IO::Socket;
use strict;
my $host = "www.marca.es";
my $file = "/"; # el index vamos...
my $port = 80;
my $S = IO::Socket::INET->new
(
Proto => "tcp",
PeerAddr => "$host",
PeerPort => "$port",
) or die "cannot connect!";
# para flushear nada mas escribir en el socket
select($S); $| = 1; select(STDOUT);
print $S "GET $file HTTP/1.1\nHOST: $host\n\n";
while(<$S>){ print } |
#! /usr/bin/perl -w
use IO::Socket;
use strict;
my $host = "www.marca.es";
my $file = "/"; # el index vamos...
my $port = 80;
my $S = IO::Socket::INET->new
(
Proto => "tcp",
PeerAddr => "$host",
PeerPort => "$port",
) or die "cannot connect!";
# para flushear nada mas escribir en el socket
select($S); $| = 1; select(STDOUT);
print $S "GET $file HTTP/1.1\nHOST: $host\n\n";
while(<$S>){ print }
Más simple ya, imposible. Ahora ya solo queda variar las peticiones que se mandan. Un GET no tiene mucha complejidad, solo recordar que en HTTP 1.1 hay que indicar el host y al final hay dos saltos de linea:
$peticion = 'GET /fichero/que/quiero/lala.php HTTP 1.1
HOST: www.LAwebQUEsea.com'."\n\n";
print $S $peticion |
$peticion = 'GET /fichero/que/quiero/lala.php HTTP 1.1
HOST: www.LAwebQUEsea.com'."\n\n";
print $S $peticion
Para una peticion POST, tenemos que indicar la longitud de los datos que se envían, podemos usar algo del estilo (es un ejemplo inventado de un supuesto formulario para votar):
$voto = 10;
$discoID = 28912;
$peticionPost='POST /discos/votar.asp HTTP/1.1
Host: www.paginaQUEsea.com
Content-Type: application/x-www-form-urlencoded
Content-Length: ';
$post = 'accion=votar&id='.$discoID.'&voto='.$voto
$peticion = $peticionPost.length($post)."\n\n".$post
print $S $peticion; |
$voto = 10;
$discoID = 28912;
$peticionPost='POST /discos/votar.asp HTTP/1.1
Host: www.paginaQUEsea.com
Content-Type: application/x-www-form-urlencoded
Content-Length: ';
$post = 'accion=votar&id='.$discoID.'&voto='.$voto
$peticion = $peticionPost.length($post)."\n\n".$post
print $S $peticion;
Además de esto podemos enviar muchas más cabeceras (Cookies con sesiones php u otras cosas, Referer’s, User-Agents, etc, etc…). Luego ya, según el escenario, después de obtener el resultado del servidor, se podría tratar y buscar patrones o lo que nos interesase, las combinaciones y posibilidades son infinitas.