eb8dbf66a1
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
80 lines
2.9 KiB
Python
80 lines
2.9 KiB
Python
"""Orquestador OSINT pasivo: genera candidatos de enriquecimiento de una persona.
|
|
|
|
Compone funciones atomicas del registro (`guess_email_formats`,
|
|
`enumerate_username_sites`, `build_search_dorks`) para producir candidatos OSINT
|
|
de una persona SIN contactar ni atacar al objetivo. Los dorks se generan pero
|
|
NO se ejecutan.
|
|
|
|
Funcion IMPURA: `enumerate_username_sites` consulta servicios publicos (red).
|
|
"""
|
|
|
|
from cybersecurity import (
|
|
build_search_dorks,
|
|
enumerate_username_sites,
|
|
guess_email_formats,
|
|
)
|
|
|
|
# Dominios de correo comunes usados cuando el caller no aporta dominios propios.
|
|
_COMMON_EMAIL_DOMAINS = ("gmail.com", "outlook.com")
|
|
|
|
|
|
def enrich_person_passive(
|
|
nombre: str,
|
|
apellidos: str,
|
|
dominios: list | None = None,
|
|
usernames: list | None = None,
|
|
) -> dict:
|
|
"""Genera candidatos OSINT pasivos para una persona.
|
|
|
|
Para cada dominio aportado (o los dominios comunes gmail/outlook si no se da
|
|
ninguno) genera los formatos de email candidatos. Para cada username
|
|
aportado comprueba en que sitios publicos existe. Ademas genera dorks de
|
|
busqueda de tipo persona (que NO se ejecutan, solo se devuelven).
|
|
|
|
Args:
|
|
nombre: nombre de pila de la persona.
|
|
apellidos: apellido(s) de la persona.
|
|
dominios: lista de dominios de correo donde buscar formatos de email.
|
|
Si es None o vacia, se usan los dominios comunes gmail/outlook.
|
|
usernames: lista de usernames a comprobar en sitios publicos. Si es None
|
|
o vacia, no se realiza ninguna comprobacion de username.
|
|
|
|
Returns:
|
|
dict con las claves:
|
|
- email_candidates: lista de emails candidatos (no verificados).
|
|
- username_hits: lista de resultados de enumerate_username_sites por
|
|
cada username comprobado.
|
|
- dorks: lista de dorks de busqueda generados (no ejecutados).
|
|
|
|
Raises:
|
|
ValueError: si nombre y apellidos estan ambos vacios.
|
|
"""
|
|
if not (nombre or "").strip() and not (apellidos or "").strip():
|
|
raise ValueError("nombre y apellidos no pueden estar ambos vacios")
|
|
|
|
target_domains = [d for d in (dominios or []) if d] or list(_COMMON_EMAIL_DOMAINS)
|
|
|
|
email_candidates: list = []
|
|
for dominio in target_domains:
|
|
candidates = guess_email_formats(nombre, apellidos, dominio)
|
|
if candidates:
|
|
email_candidates.extend(candidates)
|
|
# Deduplicar preservando orden.
|
|
email_candidates = list(dict.fromkeys(email_candidates))
|
|
|
|
username_hits: list = []
|
|
for username in usernames or []:
|
|
if not username:
|
|
continue
|
|
hits = enumerate_username_sites(username)
|
|
username_hits.append({"username": username, "hits": hits})
|
|
|
|
target = f"{nombre} {apellidos}".strip()
|
|
dorks = build_search_dorks(target, "persona")
|
|
|
|
return {
|
|
"email_candidates": email_candidates,
|
|
"username_hits": username_hits,
|
|
"dorks": dorks,
|
|
}
|