Peticiones HTTP con Perl

blaxter

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;
}
 

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 }

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
 

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;
 

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.


16 Responses to “Peticiones HTTP con Perl”

  • txus Says:

    o por ejemplo para subir o bajar la nota de ciertas peliculas en cierta pagina de cine xD
    por lo que veo, los modulos de CPAN es en plan librerias hechas por otros, no ?

  • Miguel Daza Says:

    Igual entiendo algo del post ehhhhh.

    Ingenieros: no hay quien los entienda, pero sin ellos, menuda contienda.

    Ala, saludetes.

  • blaxter Says:

    txus, es un repositorio de librerías, si. Se instalan mediante sistema gestor de paquetes estilo apt-get que lleva el mismo perl.

  • Miguel Daza Says:

    Nooooooooooo Blaxter, no sigas, en serio, NO entiendo vuestro lenguaje extraño.

  • Blaxter Says:

    jaja, joer si no tiene ninguna palabra rara lo de antes.

    Repositorio ~= “almacen”.
    librería ~= conjunto de ficheros de código que realizan una función similar y concreta.
    apt-get ~= programa muy conocido usado por debian para la gestión de paquetes.
    paquete ~= “programa”.
    debian = de las mejores distro de linux.
    distro = “distribucion”.
    distribucion = conjunto de aplicaciones reunidas para formar un sistema GNU/Linux.
    perl = lenguaje de programación, concretamente del que hablo en el post

  • manolito Says:

    suena interesante,zzzzzzzzz.

  • Miguel Daza Says:

    Ok, ahora sí, gracias.

  • DraXus Says:

    Me va a venir de perlas para cierto script para cierto juego:)

    El caso es que ya sabía algo de Perl, pero nunca he hecho nada con sockets. Gracias :)

  • TuXeD Says:

    Interesante :) . Para eso yo usé php compilado con la extensión de linea de comandos (CLI) y cURL. Algo así:

    [code]
    $valor\n\n\n";
    $url="http://172.16.1.2/index.php?level=Nivel_5&vc=\"".$myMatches[1]."\" el siguiente passwd: ".$valor;
    echo "Mandare a ".$url."\n\n";
    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_POST,true);
    curl_setopt($ch,CURLOPT_COOKIE,$sid);
    curl_setopt($ch,CURLOPT_POSTFIELDS,"password=".$valor);
    $data = curl_exec($ch);
    echo $data;

    /*
    //curl_setopt($ch,
    $data=curl_exec($ch);
    echo "***** ATTENTION!!! *************\nLa pagina es: \n\n\n".$data;
    //$matrix=preg_match("/&vc=\"(%s)\"/",$data);
    //print_r($matrix);
    curl_close($ch);
    */
    ?>
    [/code]

    Como se ve, primero abrimos un ‘curl handler’ (no se como se llama, pero lo he llamado así y au xD), luego le pasamos ciertas opciones (URL, método, variables, cookies…) y lanzamos la peticion con curl_exec().

    Luego, recogemos de $data la respuesta.

    Saludos :P

    PD: Esto era la solución del nivel5 del concurso xD

  • TuXeD Says:

    Me he colado en el código, no está completo :S Esta vez creo que sí va bien

    Aquí va, por si interesa a alguien:

    $valor\n\n\n”;
    $url=”http://172.16.1.2/index.php?level=Nivel_5&vc=\”".$myMatches[1].”\” el siguiente passwd: “.$valor;
    echo “Mandare a “.$url.”\n\n”;
    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_POST,true);
    curl_setopt($ch,CURLOPT_COOKIE,$sid);
    curl_setopt($ch,CURLOPT_POSTFIELDS,”password=”.$valor);
    $data = curl_exec($ch);
    echo $data;

    /*
    //curl_setopt($ch,
    $data=curl_exec($ch);
    echo “***** ATTENTION!!! *************\nLa pagina es: \n\n\n”.$data;
    //$matrix=preg_match(”/&vc=\”(%s)\”/”,$data);
    //print_r($matrix);
    curl_close($ch);
    */
    ?>

  • blaxter Says:

    172.16.1.2!! había conseguido olvidarme de esa ip! ahora ya no se me irá de la cabeza de nuevo xD

    No conocía esa extensión de php, parece interesante, habrá que echarle un ojo, thx.

    pd: para copypastear sin que molesten los tags html y tal en vez de [code] usa <code> :)

  • TuXeD Says:

    Juas, no habia leido lo de las etiquetas xD

    Demasiado acostumbrado al BBCode estoy … la próxima vez seguro que lo pongo jeje

    Saludos

  • TuXeD Says:

    Joder, no me había dado cuenta que el script entero sigue sin salir :S Le falta un preview a esto jeje

    Ahi va ahora con la etiqueta que toca:
    $valor\n\n\n"; $url="http://172.16.1.2/index.php?level=Nivel_5&amp;vc=\"".$myMatches[1]."\" el siguiente passwd: ".$valor; echo "Mandare a ".$url."\n\n"; curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_POST,true); curl_setopt($ch,CURLOPT_COOKIE,$sid); curl_setopt($ch,CURLOPT_POSTFIELDS,"password=".$valor); $data = curl_exec($ch); echo $data; /* //curl_setopt($ch, $data=curl_exec($ch); echo "***** ATTENTION!!! *************\nLa pagina es: \n\n\n".$data; //$matrix=preg_match("/&amp;vc=\"(%s)\"/",$data); //print_r($matrix); curl_close($ch); */ ?&gt;

    Espero que ahora sí haya salido bien. Saludos

  • TuXeD Says:

    AARG se lo sigue comiendo… pues nada, http://www.php.net/curl

  • blaxter Says:

    omg! se niega a salir xD. Teoricamente con la etiqueta code pilla todo sin excusas que yo sepa :o (he puesto un preview ahora, que hacía falta, si)

  • carlos Says:

    hola amigos saludos desde colombia, he estado leiendo sobre el tema solo le pido un favor …. sera posible que publicaran un ejemplo completo pera tenerlo estudiarlo y tenerlo como guia con la siguiente peticion
    GET / CHANGEAVATAR? NombreDeUsuario = = eterte y SessionID y C31a08d9ca PLANTILLA = 2 & RoomID = R29_3-1 y = 7So AVATAR
    esto es supuestamente para hacer inyecciones en latinchat
    gracias