Peticiones HTTP con Perl

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 Thoughts on “Peticiones HTTP con Perl

  1. 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 ?

  2. Igual entiendo algo del post ehhhhh.

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

    Ala, saludetes.

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

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

  5. 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

  6. manolito on 31 August, 2006 at 8:40 said:

    suena interesante,zzzzzzzzz.

  7. Ok, ahora sí, gracias.

  8. 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 🙂

  9. TuXeD on 31 August, 2006 at 22:34 said:

    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 😛

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

  10. TuXeD on 31 August, 2006 at 22:41 said:

    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);
    */
    ?>

  11. 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> 🙂

  12. TuXeD on 31 August, 2006 at 23:29 said:

    Juas, no habia leido lo de las etiquetas xD

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

    Saludos

  13. TuXeD on 31 August, 2006 at 23:31 said:

    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&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);
    */
    ?>

    Espero que ahora sí haya salido bien. Saludos

  14. TuXeD on 31 August, 2006 at 23:32 said:

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

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

  16. carlos on 31 January, 2009 at 15:25 said:

    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

Post Navigation