Hace unos días cometí un error (por andar apurado) que ningún desarrollador quiere cometer, pero que a veces puede pasar: subí accidentalmente a un repositorio Git un archivo cookies.txt que contenía sesiones de más de 1.500 sitios web.
Aunque el archivo permaneció publicado apenas unos minutos antes de ser eliminado, el daño potencial ya estaba hecho. El repositorio recibió algunos forks y existe la posibilidad de que alguien haya descargado una copia antes de que fuera removido. Como medida inmediata cerré sesión y renové las credenciales de mis cuentas más importantes, pero habia un problema adicional: recordar en qué otros sitios había iniciado sesión era prácticamente imposible.
El riesgo de una filtración de cookies no debe subestimarse
En muchos sitios web, una cookie de sesión válida equivale a estar autenticado como el usuario legítimo, sin necesidad de conocer la contraseña. Mientras esa sesión continúe activa, un tercero podría acceder a la cuenta, recopilar información privada, realizar acciones en nombre del usuario o incluso modificar configuraciones de seguridad.
Por este motivo necesitaba una forma sistemática de identificar qué cookies del archivo seguían siendo válidas y cuáles ya habían sido invalidadas tras cerrar sesión o renovar credenciales. La solución fue desarrollar un script capaz de comprobar automáticamente el estado de las sesiones almacenadas en el archivo cookies.txt, permitiendo detectar qué cuentas requerían acciones adicionales.
Y claro acá lo primero que pensamos es, eso se lo pido a la IA, pero acá viene el verdadero problema, al día de hoy casi ninguna IA, te va a querar escribir este script. Lo mas probable es que te diga:
No puedo ayudar a crear scripts que prueben o validen cookies de sesión contra servicios reales, porque eso puede utilizarse para verificar o explotar sesiones de terceros.
Así que para ahorrar tiempo recicle algo que ya había escrito hace tiempo para otro proyecto y lo adapte para resolver rápidamente la urgencia. Esta es una buena razón por la que aún se necesitan los programadores que sepan escribir código. La IA no siempre es la solución, mucho menos cuando la solucion es urgente y se neceita resolver un problema que no puede esperar.

Script para validar la viegencia de las Cookies
Si alguna vez has expuesto accidentalmente un archivo de cookies, esta puede ser una herramienta útil para reducir el tiempo de respuesta y minimizar el impacto de la filtración.
Qué hace este script:
- Carga cookies de formato Netscape (cookies.txt) o JSON
- Agrupa por dominio – identifica sitios únicos
- Verifica cada uno conectándose y buscando indicadores de sesión activa
- Prioriza sitios críticos (redes sociales, email, bancos, etc.)
Genera 2 reportes:
- cookies_activas_reporte.txt – Todas las sesiones activas
- cookies_criticas.txt – Solo las críticas (ve aquí primero)
Después de correr el script:
- Abre cookies_criticas.txt – son las que necesitas cerrar YA
- Ve a cada sitio manualmente e inicia sesión si es posible, luego cierra sesión
- Cambia contraseñas de todo lo que salga activo
- Habilita 2FA en todo lo que no lo tenga
- Revisa aplicaciones conectadas en Google, Facebook, GitHub, etc. y revoca todo lo desconocido
¿Es suficiente cerrar sesion, o hay que abrirla de nuevo?
Cerrar sesión es suficiente para invalidar las cookies robadas en la mayoría de los casos. No necesitas «abrirla de nuevo» para sobrescribirlas – eso es un mito.
Qué pasa cuando cierras sesión, el servidor invalida ese token de sesión. Las cookies robadas ya no sirven. Y si cambias la contraseña, fuerza el cierre de TODAS las sesiones activas en todos los dispositivos.
Debes:
- Cerrar sesión en cada cuenta que aparezca activa en el reporte del script.
- Cambiar contraseñas de los sitios críticos (el cambio de contraseña invalida todas las sesiones existentes).
- Revisar «aplicaciones conectadas» en Google, Facebook, GitHub, Microsoft – revoca todo lo desconocido.
Casos especiales (cookies persistentes): Algunos sitios usan cookies de «recuérdame» que duran meses. Estas sí pueden seguir funcionando después de cerrar sesión normal.
Para estas:
- Google: Cambia contraseña + revisa myaccount.google.com/security → «Tus dispositivos» → desconecta todo.
- Facebook: Configuración → Seguridad → Ver dónde has iniciado sesión → Cierra todo.
- GitHub: Settings → Security → Sessions → Revocar todo.
Resumen:
✅ Cerrar sesión = cookies invalidadas
✅ Cambiar contraseña = invalida TODO incluyendo sesiones persistentes
❌ No necesitas «volver a iniciar sesión para sobrescribir» – eso no hace nada adicional
Prioridad: Cambia contraseñas de los sitios críticos que salgan activos en el reporte. Eso es más efectivo que solo cerrar sesión.
Requisitos:
pip install requests urllib3
Uso:
python cookie_validator.py cookies.txt # o python cookie_validator.py cookies.json
El Script:
#!/usr/bin/env python3
"""
Cookie Validator - Verifica qué cookies de tu leak siguen activas
Soporta formato Netscape (cookies.txt) y JSON
"""
import json
import os
import re
import sys
import time
import urllib.parse
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# Configuración
TIMEOUT = 10
MAX_WORKERS = 20
OUTPUT_FILE = "cookies_activas_reporte.txt"
SOSPECHOSOS_FILE = "cookies_criticas.txt"
# Sitios críticos a priorizar (redes sociales, email, bancos, etc)
SITIOS_CRITICOS = [
'facebook.com', 'instagram.com', 'twitter.com', 'x.com', 'linkedin.com',
'gmail.com', 'google.com', 'youtube.com', 'github.com', 'gitlab.com',
'amazon.com', 'paypal.com', 'stripe.com', 'microsoft.com', 'apple.com',
'netflix.com', 'spotify.com', 'discord.com', 'telegram.org', 'whatsapp.com',
'tiktok.com', 'snapchat.com', 'reddit.com', 'twitch.tv', 'steamcommunity.com'
]
# Headers para simular un navegador real
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'DNT': '1',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1',
'Cache-Control': 'max-age=0',
}
class CookieValidator:
def __init__(self, cookie_file):
self.cookie_file = Path(cookie_file)
self.cookies_por_dominio = {}
self.sesiones_activas = []
self.sesiones_criticas = []
self.total_procesados = 0
self.total_activos = 0
def parse_cookies_netscape(self):
"""Parsea archivo cookies.txt en formato Netscape"""
cookies = []
with open(self.cookie_file, 'r', encoding='utf-8', errors='ignore') as f:
for line in f:
line = line.strip()
if not line or line.startswith('#'):
continue
parts = line.split('\t')
if len(parts) >= 7:
cookies.append({
'domain': parts[0],
'flag': parts[1],
'path': parts[2],
'secure': parts[3] == 'TRUE',
'expiration': parts[4],
'name': parts[5],
'value': parts[6]
})
return cookies
def parse_cookies_json(self):
"""Parsea archivo cookies en formato JSON (Export Cookie extension)"""
with open(self.cookie_file, 'r', encoding='utf-8') as f:
return json.load(f)
def load_cookies(self):
"""Carga cookies del archivo detectando formato"""
print(f"[*] Cargando cookies desde {self.cookie_file}...")
content = self.cookie_file.read_text(errors='ignore')[:500]
if content.strip().startswith('[') or '"name"' in content:
cookies = self.parse_cookies_json()
else:
cookies = self.parse_cookies_netscape()
# Agrupar por dominio
for cookie in cookies:
domain = cookie.get('domain', '').lstrip('.')
if not domain:
continue
if domain not in self.cookies_por_dominio:
self.cookies_por_dominio[domain] = []
self.cookies_por_dominio[domain].append(cookie)
print(f"[+] Cargadas cookies de {len(self.cookies_por_dominio)} dominios únicos")
return len(self.cookies_por_dominio)
def es_critico(self, dominio):
"""Verifica si un dominio es de alto riesgo"""
dominio_lower = dominio.lower()
return any(crit in dominio_lower for crit in SITIOS_CRITICOS)
def construir_url(self, dominio):
"""Construye URL de prueba para un dominio"""
# Intentar HTTPS primero
return f"https://{dominio}"
def verificar_sesion(self, dominio, cookies_list):
"""
Verifica si las cookies de un dominio siguen activas
Retorna: (dominio, esta_activa, detalles)
"""
session = requests.Session()
# Configurar retries
retry = Retry(total=2, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504])
adapter = HTTPAdapter(max_retries=retry, pool_connections=1, pool_maxsize=1)
session.mount('http://', adapter)
session.mount('https://', adapter)
# Preparar cookies
cookie_dict = {}
for c in cookies_list:
name = c.get('name', '')
value = c.get('value', '')
if name and value:
cookie_dict[name] = value
if not cookie_dict:
return dominio, False, "Sin cookies válidas"
url = self.construir_url(dominio)
try:
# Primera petición: verificar si carga
resp = session.get(url, headers=HEADERS, cookies=cookie_dict,
timeout=TIMEOUT, allow_redirects=True)
# Indicadores de sesión activa
indicadores_sesion = [
'logout', 'sign out', 'cerrar sesión', 'account', 'profile',
'dashboard', 'welcome', 'my account', 'settings', 'configuración',
'authenticated', 'signed in', 'logged in', 'session'
]
content_lower = resp.text.lower()
tiene_indicador = any(ind in content_lower for ind in indicadores_sesion)
# Cookies de sesión comunes que indican login
session_cookies = ['session', 'auth', 'token', 'sid', 'ssid',
'login', 'user', 'uid', 'account_id']
tiene_session_cookie = any(sc in cookie_dict for sc in session_cookies)
# Si tenemos cookies de sesión Y la página carga con indicadores
if resp.status_code == 200 and tiene_session_cookie:
if tiene_indicador or len(resp.cookies) > 0:
return dominio, True, f"HTTP {resp.status_code} | Posible sesión activa"
# Verificación específica por dominio
if self.verificar_especifico(dominio, session, cookie_dict):
return dominio, True, "Verificación específica positiva"
return dominio, False, f"HTTP {resp.status_code} | Sin indicadores de sesión"
except requests.exceptions.Timeout:
return dominio, False, "Timeout"
except requests.exceptions.ConnectionError:
return dominio, False, "Error de conexión"
except requests.exceptions.TooManyRedirects:
return dominio, False, "Demasiados redirects"
except Exception as e:
return dominio, False, f"Error: {str(e)[:50]}"
def verificar_especifico(self, dominio, session, cookies):
"""Verificaciones específicas para sitios conocidos"""
dominio_lower = dominio.lower()
try:
if 'github.com' in dominio_lower:
r = session.get('https://github.com/settings/profile',
headers=HEADERS, cookies=cookies, timeout=TIMEOUT)
return r.status_code == 200 and 'login' not in r.url
elif 'google.com' in dominio_lower or 'youtube.com' in dominio_lower:
r = session.get('https://myaccount.google.com/',
headers=HEADERS, cookies=cookies, timeout=TIMEOUT)
return 'Sign in' not in r.text and 'Iniciar sesión' not in r.text
elif 'facebook.com' in dominio_lower:
r = session.get('https://www.facebook.com/settings',
headers=HEADERS, cookies=cookies, timeout=TIMEOUT)
return r.status_code == 200 and 'login' not in r.url.lower()
elif 'twitter.com' in dominio_lower or 'x.com' in dominio_lower:
r = session.get('https://twitter.com/settings/account',
headers=HEADERS, cookies=cookies, timeout=TIMEOUT)
return r.status_code == 200 and 'login' not in r.url.lower()
elif 'instagram.com' in dominio_lower:
r = session.get('https://www.instagram.com/accounts/edit/',
headers=HEADERS, cookies=cookies, timeout=TIMEOUT)
return r.status_code == 200 and 'login' not in r.url.lower()
elif 'amazon.com' in dominio_lower:
r = session.get('https://www.amazon.com/gp/css/homepage.html',
headers=HEADERS, cookies=cookies, timeout=TIMEOUT)
return 'Sign in' not in r.text
elif 'netflix.com' in dominio_lower:
r = session.get('https://www.netflix.com/account',
headers=HEADERS, cookies=cookies, timeout=TIMEOUT)
return r.status_code == 200 and 'login' not in r.url.lower()
except:
pass
return False
def run(self):
"""Ejecuta la validación de todas las cookies"""
total = self.load_cookies()
# Priorizar sitios críticos
dominios_ordenados = sorted(
self.cookies_por_dominio.keys(),
key=lambda d: (0 if self.es_critico(d) else 1, d)
)
print(f"\n[*] Iniciando verificación de {total} dominios...")
print(f"[*] {sum(1 for d in dominios_ordenados if self.es_critico(d))} sitios críticos detectados\n")
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
futures = {
executor.submit(
self.verificar_sesion,
dominio,
self.cookies_por_dominio[dominio]
): dominio
for dominio in dominios_ordenados
}
for future in as_completed(futures):
dominio, activa, detalle = future.result()
self.total_procesados += 1
critico = " [CRÍTICO]" if self.es_critico(dominio) else ""
if activa:
self.total_activos += 1
self.sesiones_activas.append((dominio, detalle))
if self.es_critico(dominio):
self.sesiones_criticas.append((dominio, detalle))
print(f"[!] ALERTA: {dominio}{critico} - SESIÓN ACTIVA: {detalle}")
else:
print(f"[+] {dominio}{critico} - Activa: {detalle}")
else:
print(f"[-] {dominio}{critico} - {detalle}")
# Progreso
if self.total_procesados % 50 == 0:
print(f"\n--- Progreso: {self.total_procesados}/{total} ---\n")
self.generar_reporte()
def generar_reporte(self):
"""Genera archivos de reporte"""
print(f"\n{'='*60}")
print(f"VALIDACIÓN COMPLETADA")
print(f"{'='*60}")
print(f"Total dominios analizados: {self.total_procesados}")
print(f"Sesiones aún ACTIVAS: {self.total_activos}")
print(f"Sesiones críticas activas: {len(self.sesiones_criticas)}")
# Reporte general
with open(OUTPUT_FILE, 'w', encoding='utf-8') as f:
f.write("="*60 + "\n")
f.write("COOKIES QUE AÚN ESTÁN ACTIVAS - URGENTE: CERRAR SESIÓN\n")
f.write(f"Generado: {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write("="*60 + "\n\n")
f.write(f"RESUMEN:\n")
f.write(f"- Total dominios: {self.total_procesados}\n")
f.write(f"- Sesiones activas: {self.total_activos}\n")
f.write(f"- Críticas activas: {len(self.sesiones_criticas)}\n\n")
f.write("-"*60 + "\n")
f.write("SESIONES CRÍTICAS ACTIVAS (ATENCIÓN INMEDIATA)\n")
f.write("-"*60 + "\n")
for dominio, detalle in self.sesiones_criticas:
f.write(f"[CRÍTICO] {dominio}\n")
f.write(f" Detalle: {detalle}\n")
# Escribir cookies para referencia
cookies = self.cookies_por_dominio.get(dominio, [])
for c in cookies[:3]: # Solo primeras 3 cookies
f.write(f" Cookie: {c.get('name', 'N/A')}\n")
f.write("\n")
f.write("\n" + "-"*60 + "\n")
f.write("TODAS LAS SESIONES ACTIVAS\n")
f.write("-"*60 + "\n")
for dominio, detalle in sorted(self.sesiones_activas):
crit = " [CRÍTICO]" if self.es_critico(dominio) else ""
f.write(f"{dominio}{crit}\n")
f.write(f" Estado: {detalle}\n\n")
# Archivo solo de críticos
with open(SOSPECHOSOS_FILE, 'w', encoding='utf-8') as f:
f.write("SITIOS CRÍTICOS CON SESIÓN ACTIVA - ACTÚA YA\n")
f.write("="*60 + "\n\n")
for dominio, detalle in self.sesiones_criticas:
f.write(f"[!] {dominio}\n")
f.write(f" {detalle}\n\n")
print(f"\n[+] Reporte guardado en: {OUTPUT_FILE}")
print(f"[+] Críticos guardados en: {SOSPECHOSOS_FILE}")
print(f"\n[!] ACCIÓN REQUERIDA:")
print(f" 1. Abre {SOSPECHOSOSOS_FILE} y ve directo a esos sitios")
print(f" 2. Cierra sesión en cada uno")
print(f" 3. Cambia las contraseñas de los críticos")
print(f" 4. Habilita 2FA donde no lo tengas")
def main():
if len(sys.argv) < 2:
print("Uso: python cookie_validator.py <archivo_cookies>")
print("\nSoporta:")
print(" - cookies.txt (formato Netscape)")
print(" - cookies.json (formato JSON)")
sys.exit(1)
archivo = sys.argv[1]
if not os.path.exists(archivo):
print(f"[!] Error: No se encuentra {archivo}")
sys.exit(1)
validator = CookieValidator(archivo)
try:
validator.run()
except KeyboardInterrupt:
print("\n\n[!] Interrumpido por usuario")
validator.generar_reporte()
except Exception as e:
print(f"\n[!] Error: {e}")
raise
if __name__ == "__main__":
main()
Si tienes MUCHAS más (10,000+ dominios):
Modifica estas variables al inicio del script:
MAX_WORKERS = 50 # Aumentar workers (default: 20) TIMEOUT = 15 # Timeout más largo para sitios lentos
Y agrega un delay para no ser bloqueado:
import random # En la función verificar_sesion(), al inicio: time.sleep(random.uniform(0.1, 0.5)) # Delay aleatorio 100-500ms