Tabla de Contenidos
Protocolo HTTP y creación de clientes HTTP en Python
Módulo perteneciente al curso Python avanzado para proyectos de seguridad
En esta sección, vamos a presentar el protocolo HTTP y cómo podemos construir clientes HTTP con httplib.
HTTP es un protocolo de capa de aplicación que básicamente consta de dos elementos: una solicitud realizada por el cliente, que solicita al servidor un recurso específico especificado por una URL, y una respuesta, enviada por el servidor, que suministra el recurso que el cliente ha solicitado.
Introducción al protocolo HTTP
El protocolo HTTP es un protocolo de transferencia de datos de hyper-texto, sin estado, que no almacena la información que se intercambia entre cliente y servidor. Este protocolo define las reglas que deben de seguir clientes, proxies y servidores para el intercambio de información. Se trata de un protocolo sencillo, donde los clientes realizan peticiones y los servidores emiten las respuestas.
Al ser un protocolo sin estado para poder almacenar información relativa a una transacción HTTP hay que recurrir a otras técnicas como cookies (valores almacenados en el lado del cliente) o sesiones (espacios de memoria temporal reservada para almacenar información sobre una o varias transacciones HTTP en el lado del servidor).
Los servidores devuelven un código HTTP que indica el resultado de una operación solicitada por el cliente, además se pueden utilizar cabeceras (headers) en las peticiones para incluir información extra tanto en peticiones como en respuestas.
HTTP define una serie predefinida de métodos de petición que pueden utilizarse. El protocolo tiene flexibilidad para ir añadiendo nuevos métodos y para así añadir nuevas funcionalidades. Los ejemplos más comunes son:
GET. Pide una representación del recurso especificado. Por seguridad no debería ser usado por aplicaciones que causen efectos ya que transmite información a través de la URI agregando parámetros a la URL.HEAD. Pide una respuesta idéntica a la que correspondería a una peticiónGET, pero en la petición no se devuelve el cuerpo. Esto es útil para poder recuperar los metadatos de los encabezados de respuesta, sin tener que transportar todo el contenido.POST. Envía los datos para que sean procesados por el recurso identificado. Los datos se incluirán en el cuerpo de la petición. Esto puede resultar en la creación de un nuevo recurso o de las actualizaciones de los recursos existentes o ambas cosas.
Módulo http.client
El protocolo HTTP emplea los sockets a nivel más bajo para establecer la conexión entre cliente y servidor. En Python tenemos la posibilidad de usar un módulo de un nivel más alto que nos abstrae del funcionamiento de los sockets a bajo nivel.
Python proporciona una serie de módulos para crear un cliente HTTP. Los módulos que proporciona Python en la biblioteca estándar son httplib.client, urllib.request. .
También podemos encontrar paquetes como el de requests que proporcionan algunas mejoras sobre el módulo urllib.request estándar.
Este módulo define una clase que implementa la clase HTTPConnection como podemos ver en la documentación oficial.
La clase HTTPConnection acepta un host y un puerto como parámetros. Se requiere el host y el puerto es opcional.
Una instancia de esta clase representa una transacción con un servidor HTTP. Debe instanciarse pasando un identificador de servidor y un número de puerto opcional. Si no se especifica el número de puerto, el número de puerto de la cadena de identificación del servidor se extrae si tiene el formulario host: puerto; de lo contrario, se utiliza el puerto HTTP predeterminado (80).
Puede encontrar el siguiente código en el archivo request_httplib.py:
import http.client connection = http.client.HTTPConnection("www.google.com") connection.request("GET", "/") response = connection.getresponse() print('Respuesta:',response) print('Estado:', response.status, response.reason) datos = response.read() print(datos)
Actividad práctica
Completar las xxx del siguiente script para obtener el contenido y las cabeceras de la respuesta correspondiente a la petición de un dominio. Será obligatorio pedir al usuario el target correspondiente al dominio a analizar:
usage: httplib_domino.py [-h] -target TARGET httplib_domino.py: error: the following arguments are required: -target
#!/usr/bin/python3 import http.client import argparse parser = argparse.xxx(description='obtener respuesta de un dominio') # argumentos parser.add_argument("-target", dest="target", help="IP /dominio", required=True) parsed_args = parser.xxx() connection = http.xxx.HTTPConnection(parsed_args.target) connection.xxx("GET", "/") data = xxx.getresponse() print (xxx.code) print (xxx.headers) texto = xxx.readlines() print(texto)
Solución
#!/usr/bin/python3 import http.client import argparse parser = argparse.ArgumentParser(description='obtener respuesta de un dominio') # argumentos parser.add_argument("-target", dest="target", help="IP /dominio", required=True) parsed_args = parser.parse_args() connection = http.client.HTTPConnection(parsed_args.target) connection.request("GET", "/") data = connection.getresponse() print (data .code) print (data .headers) texto = data .readlines() print(texto)
