Interactuando con aplicaciones web (Requests)

CiberseguridadBeginner
Practicar Ahora

Introducción

Bienvenido al laboratorio de Interacción con Aplicaciones Web. En el mundo de la ciberseguridad y la automatización web, interactuar con aplicaciones web mediante programación es una habilidad fundamental. Ya sea que estés extrayendo datos (scraping), probando vulnerabilidades o automatizando tareas repetitivas, necesitas una forma confiable de enviar y recibir solicitudes HTTP.

En este laboratorio, aprenderás a utilizar la potente biblioteca requests de Python. Escribirás scripts para enviar solicitudes HTTP GET y POST, extraer información importante de las respuestas del servidor, automatizar el envío de formularios y gestionar cookies de sesión para mantener el estado de autenticación.

En comparación con los sockets sin procesar, requests funciona a un nivel de abstracción superior. Maneja muchos detalles HTTP por ti, como encabezados, codificación, redirecciones y cookies. Esto lo hace ideal para la automatización de seguridad, donde te interesa más el comportamiento web y los flujos de trabajo que la mecánica paquete por paquete.

Enviar solicitudes HTTP GET

En este paso, aprenderás a enviar una solicitud HTTP GET básica utilizando Python. El método GET se utiliza para solicitar datos de un recurso específico, de forma muy similar a como tu navegador web solicita una página cuando escribes una URL.

Piensa en esto como la forma más sencilla de automatización web: solicitar un recurso e inspeccionar la respuesta. Muchas tareas de reconocimiento, pruebas y monitoreo comienzan exactamente aquí.

Primero, asegúrate de estar en tu directorio de proyecto. Aquí es donde crearás todos tus scripts de Python para este laboratorio.

cd ~/project

Ahora, creemos un script de Python para enviar una solicitud GET a un servidor web local que ha sido preparado para ti. Usa el editor de texto nano para crear un archivo llamado get_request.py:

nano get_request.py

Escribe el siguiente código de Python en el editor:

import requests

url = 'http://127.0.0.1:5000/get'
response = requests.get(url)

print("Response Body:")
print(response.text)

Guarda el archivo y sal del editor (en nano, presiona Ctrl+O, Enter para guardar, y Ctrl+X para salir).

El código anterior importa la biblioteca requests, define la URL de destino y utiliza la función requests.get() para enviar la solicitud. La respuesta del servidor se almacena en la variable response, y luego imprimimos el texto sin formato del cuerpo de la respuesta.

Ejecuta tu script usando el intérprete de Python:

python3 get_request.py

Deberías ver una salida similar a esta:

Response Body:
{"message":"GET request successful"}

Extraer estado y encabezados HTTP

En este paso, aprenderás a extraer información más detallada de una respuesta HTTP, específicamente el código de estado y los encabezados.

El cuerpo de la respuesta es solo una parte de la historia. Los códigos de estado te indican cómo entendió el servidor la solicitud, y los encabezados describen metadatos como el tipo de contenido, la política de caché, las cookies o el software del servidor. Una buena automatización observa las tres capas: código, encabezados y cuerpo.

Cuando un servidor responde a una solicitud HTTP, incluye un código de estado (como 200 para OK, o 404 para Not Found) y encabezados que proporcionan metadatos sobre la respuesta (como el tipo de contenido o el software del servidor).

Crea un nuevo archivo llamado check_status.py en tu directorio de proyecto:

nano check_status.py

Añade el siguiente código al archivo:

import requests

url = 'http://127.0.0.1:5000/get'
response = requests.get(url)

print(f"Status Code: {response.status_code}")

if response.status_code == 200:
    print("The request was successful!")

print("\nResponse Headers:")
print(f"Content-Type: {response.headers.get('Content-Type')}")
print(f"Server: {response.headers.get('Server')}")

Guarda el archivo y sal del editor.

En este script, response.status_code recupera el código de estado entero devuelto por el servidor. response.headers es un objeto similar a un diccionario que contiene todos los encabezados HTTP enviados por el servidor. Usamos el método .get() para extraer de forma segura encabezados específicos.

Ejecuta el script para ver la información extraída:

python3 check_status.py

Tu salida debería verse así:

Status Code: 200
The request was successful!

Response Headers:
Content-Type: application/json
Server: Werkzeug/3.0.1 Python/3.10.12

Automatizar el envío de formularios (POST)

En este paso, aprenderás a enviar una solicitud HTTP POST. A diferencia de las solicitudes GET, que se utilizan para recuperar datos, las solicitudes POST se utilizan para enviar datos al servidor. Esto se usa comúnmente para enviar formularios web, como credenciales de inicio de sesión.

Esta distinción refleja la semántica HTTP. En la práctica, GET se usa generalmente para leer recursos, mientras que POST se usa a menudo para acciones que envían o cambian el estado. Entender esa diferencia te ayuda a predecir cómo se comportan las aplicaciones y cómo deben interactuar tus scripts con ellas.

Escribiremos un script para simular el envío de un formulario de inicio de sesión con un nombre de usuario y una contraseña.

Crea un nuevo archivo llamado post_request.py:

nano post_request.py

Introduce el siguiente código:

import requests

url = 'http://127.0.0.1:5000/post'

## Define the form data as a dictionary
form_data = {
    'username': 'admin',
    'password': 'secret'
}

## Send the POST request with the data parameter
response = requests.post(url, data=form_data)

print(f"Status Code: {response.status_code}")
print(f"Response Body: {response.text}")

Guarda el archivo y sal del editor.

Aquí, definimos un diccionario llamado form_data que contiene nuestras credenciales. Luego usamos requests.post() y pasamos nuestro diccionario al parámetro data. La biblioteca requests formatea automáticamente estos datos como un envío de formulario web estándar.

Ejecuta el script para enviar el formulario:

python3 post_request.py

Deberías ver un mensaje de inicio de sesión exitoso:

Status Code: 200
Response Body: {"message":"Login successful"}

Puedes intentar cambiar la contraseña en el script por un valor incorrecto (como wrongpass) y ejecutarlo de nuevo para ver cómo el servidor responde con un código de estado 401 Unauthorized.

Gestionar cookies de sesión

En este paso final, aprenderás a gestionar cookies de sesión. HTTP es un protocolo sin estado, lo que significa que cada solicitud es independiente. Para recordar a un usuario después de que inicia sesión, las aplicaciones web utilizan cookies.

Si usas requests.get() o requests.post() directamente, las cookies no se guardan entre solicitudes. Para mantener una sesión (como permanecer conectado), debes usar un objeto Session proporcionado por la biblioteca requests.

Crea un archivo llamado session_request.py:

nano session_request.py

Añade el siguiente código:

import requests

## Create a Session object
session = requests.Session()

login_url = 'http://127.0.0.1:5000/login'
profile_url = 'http://127.0.0.1:5000/profile'

print("Attempting to access profile BEFORE login...")
response1 = session.get(profile_url)
print(f"Status: {response1.status_code}, Body: {response1.text.strip()}")

print("\nLogging in to establish a session...")
## The session object will automatically store cookies returned by the server
session.post(login_url)

print("\nAttempting to access profile AFTER login...")
## The session object will automatically send the stored cookies with this request
response2 = session.get(profile_url)
print(f"Status: {response2.status_code}, Body: {response2.text.strip()}")

Guarda el archivo y sal del editor.

En este script, requests.Session() crea una sesión persistente. Cuando enviamos la solicitud POST a /login, el servidor establece una cookie de sesión. El objeto Session almacena esta cookie y la incluye automáticamente en la solicitud GET posterior a /profile, permitiéndonos acceder a la ruta protegida.

Ejecuta el script:

python3 session_request.py

Observa la salida. Verás que el primer intento falla porque no hemos iniciado sesión, pero el segundo intento tiene éxito porque la cookie de sesión se gestionó automáticamente:

Attempting to access profile BEFORE login...
Status: 401, Body: {"message":"Unauthorized"}

Logging in to establish a session...

Attempting to access profile AFTER login...
Status: 200, Body: {"message":"Welcome to your profile!"}

Resumen

Has aprendido a utilizar la biblioteca requests de Python para automatizar interacciones web. Comenzaste enviando solicitudes HTTP GET básicas y extrayendo metadatos importantes como códigos de estado y encabezados. Luego avanzaste al envío de solicitudes HTTP POST para automatizar el envío de formularios. Finalmente, aprendiste a usar objetos Session para gestionar cookies y mantener el estado de autenticación a través de múltiples solicitudes.

Estas habilidades forman la base para muchas tareas avanzadas en web scraping, integración de API y pruebas de seguridad automatizadas.