1
Uso ético: Realiza estas pruebas únicamente en redes y sistemas sobre los que tengas autorización explícita. El reconocimiento no autorizado puede ser ilegal.
OBJETIVO
Descubrir la IP pública y la IP local del equipo. Identificar el hostname y realizar una primera consulta DNS. Es el punto de partida de cualquier evaluación de seguridad.
CONCEPTOS CLAVE
Dirección IP
DNS
Hostname
IP pública vs local
Resolución de nombres
NAT
Interfaces de red
Python · reconocimiento.py
import socket import urllib.request # ─── Reconocimiento básico ───────────────────────── hostname = socket.gethostname() ip_local = socket.gethostbyname(hostname) print("=" * 40) print(" RECONOCIMIENTO DE RED") print("=" * 40) print(f"Hostname : {hostname}") print(f"IP local : {ip_local}") # ─── IP pública via API ──────────────────────────── try: ip_publica = urllib.request.urlopen( "https://api.ipify.org" ).read().decode() print(f"IP pública: {ip_publica}") except Exception as e: print(f"Error obteniendo IP pública: {e}") # ─── Resolución DNS ─────────────────────────────── dominio = "google.com" ip_dns = socket.gethostbyname(dominio) print(f"DNS '{dominio}' → {ip_dns}")
EJERCICIOS
-
1Mostrar la IP pública usando la API
https://api.ipify.org→ urllib.request.urlopen(url).read().decode() -
2Resolver los registros DNS de un dominio dado por el usuario→ socket.getaddrinfo(dominio, None)
-
3Hacer una resolución inversa: de IP a nombre de dominio→ socket.gethostbyaddr(ip)
CHECKLIST
Código ejecutado sin errores
IP local identificada correctamente
IP pública obtenida via API
Ejercicio de DNS completado
2
Instalación:
pip install scapy — En Windows puede requerir Npcap. En Linux puede necesitar permisos root (sudo). OBJETIVO
Detectar todos los dispositivos activos en la red local enviando paquetes ARP broadcast y analizando las respuestas. Obtener dirección IP y MAC de cada host.
CONCEPTOS CLAVE
ARP (Address Resolution Protocol)
Broadcast
MAC Address
Red local / LAN
Subred CIDR
Scapy frames
Python · escaneo_red.py
from scapy.all import ARP, Ether, srp # ─── Configuración ──────────────────────────────── target = "192.168.1.0/24" # adaptar a tu red # ─── Construir paquete ARP broadcast ────────────── arp = ARP(pdst=target) ether = Ether(dst="ff:ff:ff:ff:ff:ff") packet = ether / arp # ─── Enviar y recibir respuestas ────────────────── resultado = srp(packet, timeout=3, verbose=0)[0] # ─── Mostrar dispositivos encontrados ──────────── print(f"\n{'IP':20} {'MAC':20}") print("-" * 40) dispositivos = [] for enviado, recibido in resultado: dispositivos.append({ "ip" : recibido.psrc, "mac" : recibido.hwsrc }) print(f"{recibido.psrc:20} {recibido.hwsrc:20}") print(f"\nTotal: {len(dispositivos)} dispositivos")
EJERCICIOS
-
1Guardar los dispositivos encontrados en un archivo JSON→ import json; json.dump(dispositivos, f)
-
2Detectar el fabricante de la tarjeta de red a partir de la MAC→ Primeros 3 bytes de la MAC = OUI del fabricante
-
3Permitir al usuario introducir el rango de red por teclado→ target = input("Introduce la red (ej: 192.168.1.0/24): ")
CHECKLIST
Scapy instalado correctamente
Escaneo ejecutado con éxito
Dispositivos listados con IP y MAC
Ejercicio JSON completado
herramienta profesional equivalente
Nmap / netdiscover
nmap -sn 192.168.1.0/24 · netdiscover -r 192.168.1.0/24
3
OBJETIVO
Detectar puertos TCP abiertos en un host. Cada puerto abierto indica un servicio activo que puede ser vulnerable. Comparar versión básica vs. versión multihilo.
CONCEPTOS CLAVE
Puerto TCP
Three-way handshake
Connect scan
Well-known ports
Socket timeout
Multihilo
Python · scanner_basico.py
import socket target = "127.0.0.1" abiertos = [] print(f"Escaneando {target}...") for port in range(20, 1025): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(0.5) result = s.connect_ex((target, port)) if result == 0: print(f" [ABIERTO] Puerto {port}") abiertos.append(port) s.close()
Python · scanner_avanzado.py — Multihilo + puertos comunes
import socket import threading target = "127.0.0.1" PUERTOS_COMUNES = { 21:"FTP", 22:"SSH", 23:"Telnet", 25:"SMTP", 53:"DNS", 80:"HTTP", 110:"POP3", 143:"IMAP", 443:"HTTPS", 445:"SMB", 3306:"MySQL", 3389:"RDP", 5432:"PostgreSQL", 6379:"Redis", 8080:"HTTP-alt" } lock = threading.Lock() def escanear_puerto(port, servicio): s = socket.socket() s.settimeout(0.5) if s.connect_ex((target, port)) == 0: with lock: print(f" [ABIERTO] {port:6} → {servicio}") s.close() hilos = [] for p, srv in PUERTOS_COMUNES.items(): t = threading.Thread(target=escanear_puerto, args=(p, srv)) hilos.append(t) t.start() for t in hilos: t.join()
herramienta profesional equivalente
Nmap
nmap -sV -p- 192.168.1.5 · nmap --top-ports 100 target
4
Python · banner_grabbing.py
import socket target = "scanme.nmap.org" port = 80 # ─── Captura banner HTTP ────────────────────────── s = socket.socket() s.settimeout(5) s.connect((target, port)) s.send(b"HEAD / HTTP/1.1\r\nHost: scanme.nmap.org\r\n\r\n") banner = s.recv(1024).decode(errors="ignore") print("Banner HTTP:") print(banner) s.close() # ─── Grabber genérico multi-puerto ──────────────── def grab_banner(ip, port): try: s = socket.socket() s.settimeout(3) s.connect((ip, port)) banner = s.recv(1024).decode(errors="ignore").strip() print(f"[{port}] {banner[:80]}") except: pass finally: s.close() for p in [21, 22, 25, 80, 110]: grab_banner(target, p)
CONCEPTOS
Banner grabbing
Fingerprinting
HTTP headers
Server versioning
CVE lookup
Service enumeration
EJERCICIOS
-
1Extraer solo la cabecera
Server:del banner HTTP -
2Intentar grabbing en los puertos abiertos encontrados en el módulo 3
-
3Guardar versión detectada en diccionario
{puerto: banner}
5
Solo simulación: Este módulo es exclusivamente educativo. Nunca uses estas técnicas contra sistemas reales sin autorización escrita. El objetivo es entender la importancia de las contraseñas seguras.
Python · ataque_diccionario.py
import hashlib import time # ─── Hash que queremos "crackear" ───────────────── password_real = "seguridad123" hash_real = hashlib.sha256( password_real.encode() ).hexdigest() print(f"Hash objetivo: {hash_real[:20]}...") # ─── Diccionario de contraseñas comunes ────────── diccionario = [ "admin", "123456", "password", "12345678", "qwerty", "abc123", "seguridad123", "letmein" ] inicio = time.time() encontrada = False print("\nIniciando ataque de diccionario...") for intento, palabra in enumerate(diccionario, 1): hash_prueba = hashlib.sha256( palabra.encode() ).hexdigest() print(f" [{intento}] Probando: {palabra}") if hash_prueba == hash_real: tiempo = time.time() - inicio print(f"\n[!] ENCONTRADA: '{palabra}' en {tiempo:.3f}s") encontrada = True break if not encontrada: print("\n[✗] No encontrada en el diccionario")
Python · hashing_seguro.py — Buenas prácticas
import hashlib import os # ─── Hash con SALT (mucho más seguro) ───────────── def hash_con_salt(password: str) -> tuple: salt = os.urandom(32) dk = hashlib.pbkdf2_hmac( "sha256", password.encode(), salt, iterations=200_000 ) return salt.hex(), dk.hex() salt, hash_seguro = hash_con_salt("MiContraseñaFuerte!9") print(f"Salt : {salt[:20]}...") print(f"Hash : {hash_seguro[:20]}...") print("[+] Resistente a ataques de diccionario")
6
Python · sniffer.py
from scapy.all import sniff, IP, TCP, UDP # ─── Analizador de paquetes ─────────────────────── def analizar_paquete(pkt): if pkt.haslayer(IP): ip_src = pkt[IP].src ip_dst = pkt[IP].dst if pkt.haslayer(TCP): print(f"[TCP] {ip_src}:{pkt[TCP].sport} → {ip_dst}:{pkt[TCP].dport}") elif pkt.haslayer(UDP): print(f"[UDP] {ip_src}:{pkt[UDP].sport} → {ip_dst}:{pkt[UDP].dport}") # ─── Captura 20 paquetes ────────────────────────── print("Capturando paquetes...") sniff(prn=analizar_paquete, count=20) # ─── Guardar captura a fichero PCAP ─────────────── from scapy.all import wrpcap paquetes = sniff(count=50) wrpcap("captura.pcap", paquetes) print("Captura guardada en captura.pcap")
CONCEPTOS
Packet sniffing
Promiscuous mode
TCP/IP stack
PCAP format
Filtros BPF
Protocolo HTTP
EJERCICIOS
-
1Filtrar solo paquetes HTTP (puerto 80)→ sniff(filter="tcp port 80", count=10)
-
2Contar paquetes por protocolo y mostrar estadísticas
herramienta profesional equivalente
Wireshark / tcpdump
tcpdump -i eth0 -w captura.pcap · Wireshark (GUI)
7
Python · monitor_integridad.py
import hashlib import os import json import time def hash_archivo(ruta: str) -> str: with open(ruta, "rb") as f: return hashlib.sha256(f.read()).hexdigest() def crear_baseline(directorio: str) -> dict: """Crea un registro de hashes de todos los archivos.""" baseline = {} for root, _, files in os.walk(directorio): for f in files: ruta = os.path.join(root, f) try: baseline[ruta] = hash_archivo(ruta) except: pass return baseline def verificar_integridad(baseline: dict): """Compara estado actual con baseline.""" alertas = 0 for ruta, hash_orig in baseline.items(): if not os.path.exists(ruta): print(f"[ELIMINADO] {ruta}"); alertas += 1 continue if hash_archivo(ruta) != hash_orig: print(f"[MODIFICADO] {ruta}"); alertas += 1 print(f"\n{alertas} alertas detectadas") # ─── Uso ───────────────────────────────────────── directorio = "./archivos_monitorizados" bl = crear_baseline(directorio) print(f"Baseline: {len(bl)} archivos registrados") # Guardar baseline a JSON with open("baseline.json", "w") as f: json.dump(bl, f, indent=2) # Verificar integridad verificar_integridad(bl)
8
EJEMPLO DE INFORME
══════════════════════════════════
INFORME DE SEGURIDAD
══════════════════════════════════
Fecha : 2025-03-10 10:30:00
Auditor : Alumno Lab
Target : 192.168.1.5
── DISPOSITIVOS DETECTADOS ────────
192.168.1.1 aa:bb:cc:dd:ee:ff Router
192.168.1.5 11:22:33:44:55:66 PC
── PUERTOS ABIERTOS ───────────────
22 SSH ⚠ RIESGO MEDIO
80 HTTP ⚠ RIESGO BAJO
3306 MySQL ⚠ RIESGO ALTO
── RECOMENDACIONES ────────────────
✓ Cerrar puerto MySQL (3306)
✓ Usar claves SSH en lugar de passwd
✓ Activar firewall con reglas mínimas
✓ Actualizar servicios expuestos
ACTIVIDADES FINALES
-
1Mejorar el escáner de puertos con multihilo (ya visto en módulo 3)
-
2Crear una interfaz con menú que integre todos los módulos→ while True: opcion = input("Elige módulo [1-7]: ")
-
3Guardar todos los resultados en un archivo JSON estructurado
-
4Generar un informe HTML con todos los hallazgos del laboratorio
Python · generar_informe.py
import json from datetime import datetime def generar_informe(target, dispositivos, puertos, servicios): informe = { "fecha" : datetime.now().isoformat(), "target" : target, "dispositivos": dispositivos, "puertos" : puertos, "servicios" : servicios, "riesgos" : evaluar_riesgos(puertos), } # Guardar JSON with open("informe_seguridad.json", "w") as f: json.dump(informe, f, indent=2, ensure_ascii=False) # Guardar TXT legible with open("informe_seguridad.txt", "w") as f: f.write(formatear_txt(informe)) print("[+] Informe generado: informe_seguridad.json / .txt") def evaluar_riesgos(puertos): RIESGO = { 21:"ALTO", 23:"CRITICO", 3306:"ALTO", 22:"MEDIO", 80:"BAJO", 443:"BAJO" } return {p: RIESGO.get(p, "INFO") for p in puertos}
PLANIFICACIÓN DE SESIÓN — 3 HORAS
| TIEMPO | ACTIVIDAD | MÓDULO |
|---|---|---|
| 00:00 – 00:30 | Teoría: redes, protocolos TCP/IP, modelo OSI | Introducción |
| 00:30 – 01:10 | Reconocimiento de red y escaneo de hosts | Módulos 1 y 2 |
| 01:10 – 01:50 | Escaneo de puertos y análisis de servicios | Módulos 3 y 4 |
| 01:50 – 02:20 | Ataque de diccionario y hashing seguro | Módulo 5 |
| 02:20 – 02:50 | Sniffer de red y monitor de integridad | Módulos 6 y 7 |
| 02:50 – 03:00 | Generación del informe y conclusiones | Módulo 8 |
¡Laboratorio completado! Has recorrido los fundamentos del hacking ético: reconocimiento, escaneo, análisis, ataques controlados e informes. El siguiente paso es practicar en entornos como HackTheBox, TryHackMe o tu propia red virtual con VirtualBox.