WhisperGraph — Guía Completa (MCP + llama.cpp)

Fuente: documentación oficial de Whisper Security. Adaptado por Sammi De Blas.


Índice

  1. ¿Qué es WhisperGraph?
  2. Configuración en llama.cpp
  3. Las 6 Tools MCP
  4. Recursos Disponibles (Resources)
  5. Los 8 Prompts Integrados
  6. Procedimientos Especiales (CALL)
  7. Labels del Grafo (20 tipos)
  8. Reglas de Seguridad en Queries
  9. Modelo de Errores
  10. Patrón de Introspección Recomendado
  11. Casos de Uso por Rol
  12. Preguntas de Ejemplo en Lenguaje Natural
  13. Enlaces Útiles

¿Qué es WhisperGraph?

WhisperGraph es una base de datos de infraestructura de Internet con 7.39 mil millones de nodos, 39 mil millones de aristas y 5.6 millones de aristas de threat intel en 20 tipos de entidades.

Cubre:

  • DNS — resoluciones, nameservers, mail servers
  • BGP — routing, peers, ASNs, anuncios de prefijos
  • IP allocation — rangos, geoip, organización
  • WHOIS — 237 millones de emails, 65 millones de teléfonos
  • Email infrastructure — MX, SPF chains completas
  • DNSSEC — firmas y algoritmos
  • Web links — 9.1 mil millones de hipervínculos de Common Crawl
  • Threat intel — ~40 feeds de amenazas activas

Acceso: vía MCP (Model Context Protocol) — 6 herramientas read-only + recursos + prompts.


Configuración en llama.cpp

Requisitos

  • llama.cpp con soporte Streamable HTTP
  • API key de Whisper Security (desde Whisper Console)

Config

En la UI de llama.cpp, añadir servidor MCP:

URL: https://mcp.whisper.security
Headers:
  X-API-Key: <tu-api-key>

NOTA: No usar Authorization: Bearer — WhisperGraph acepta X-API-Key. OAuth también está disponible para clientes que lo soporten.

Verificar conexión

Usar el tool list_labels:

Lista las labels disponibles en el grafo de Whisper

Esperado: 20 labels con sus conteos (HOSTNAME ~2.6B, IPV4 ~619M, etc.)


Las 6 Tools MCP

1. query — Cypher primario

Ejecuta cualquier query Cypher contra el grafo. Es la herramienta principal.

query(statement: string) -> rows[]

Parámetros:

  • statement: Query Cypher válida

Ejemplo:

MATCH (h:HOSTNAME {name: "google.com"})-[:RESOLVES_TO]->(ip:IPV4)
RETURN h.name, ip.name LIMIT 10

Límites: LIMIT ≤ 500, sin excepciones.


2. list_labels — Introspección de esquema

Devuelve todas las labels de nodo con conteos y propiedades indexadas.

list_labels() -> {name, count, indexed_properties}[]

Cacheado server-side por 5 minutos — no consume quota.


3. describe_label(label) — Metadatos de label

Propiedades, tipos, flags de índice, aristas de entrada/salida para una label.

describe_label(label: string) -> {properties: [], out_edges: [], in_edges: []}

Cacheado server-side por 5 minutos — no consume quota.


4. explain_indicator(indicator) — Assessment de amenazas

Evaluación compuesta de amenaza para IP, hostname, ASN o CIDR.

explain_indicator(indicator: string) -> {score, level, explanation, factors[], sources[]}

Funciona con:

  • IPs: 185.220.101.1
  • Hostnames: evil.example.com
  • ASNs: AS13335
  • CIDRs: 185.220.101.0/24

Devuelve:

  • score: numérico compuesto (ej: 4.95)
  • level: INFO, LOW, MEDIUM, HIGH, CRITICAL
  • explanation: texto legible
  • factors[]: desglose del cálculo
  • sources[]: feeds que contribuyen con peso, firstSeen, lastSeen

5. whisper_history(indicator) — Histórico WHOIS/BGP

Snapshots históricos de WHOIS o BGP para un indicador.

whisper_history(indicator: string) -> rows[]

6. domain_variants(name, [label], [includeNonExistent]) — Typosquatting

Genera variantes de typosquatting usando 14 algoritmos de mutación:

  1. Omission (omitir caracter)
  2. Repetition (repetir caracter)
  3. Transposition (transponer caracteres adyacentes)
  4. QWERTY-adjacent replacement
  5. QWERTY-adjacent insertion
  6. Vowel-swap
  7. Bitsquatting
  8. Homoglyph / Unicode confusables
  9. Hyphenation
  10. Dot insertion/omission
  11. TLD-swap
  12. TLD-addition
  13. Subdomain-add

Por defecto devuelve solo los lookalikes registrados en el grafo.

Cada fila: variant, method, exists, nodeId, label, confidence (0.3–0.9), confidenceLabel

NOTA: exists significa “registrado/observado”, NO “malicioso”. Usar explain_indicator para veredicto de amenaza.

Parámetros:

  • name (requerido): dominio a analizar
  • label (opcional, default HOSTNAME): label contra la que verificar
  • includeNonExistent (opcional, default false): si true, también devuelve variantes no registradas

Recursos Disponibles (Resources)

RecursoContenido
whisper://schema/fullSchema completo: labels, edge types, propiedades threat-intel
whisper://schema/relationshipsMapa entidad-relación — qué labels conectan con cuáles
whisper://guide/functionsReferencia de funciones Cypher (agregación, string, numéricas, fecha, schema)
whisper://guide/cookbookCookbook de 70+ patrones de consulta validados para 8 roles de analista
whisper://statsEstadísticas en vivo — conteos de nodos/aristas físicas, virtuales, totales, threatIntel
whisper://quotaPlan, max query depth, uso actual del llamante

Los 8 Prompts Integrados

El servidor MCP incluye 8 prompts slash-style listos para usar:

/investigate-ip

Recorre IP → prefix → ASN → owner → threat intel → reverse-DNS en un solo pase.

Ejemplo: /investigate-ip 185.220.101.42

/map-attack-surface

Mapea la superficie de ataque externa de un dominio: subdominios, hosting, mail, SPF, nameservers.

Ejemplo: /map-attack-surface tesla.com

/compare-domains

Compara la infraestructura de dos o más dominios lado a lado.

Ejemplo: /compare-domains ejemplo.com competencia.com

/blast-radius

Análisis de impacto de fallo de ASN: prefijos, peers, dominios afectados si el ASN cae.

Ejemplo: /blast-radius AS16509

/threat-triage

Triage completo de indicador: feeds, score, nivel, contexto histórico.

Ejemplo: /threat-triage 185.220.101.1

/whois-pivot

Pivoteo de dominio via contactos WHOIS compartidos (registrar, email, teléfono, organización).

Ejemplo: /whois-pivot cloudflare.com

/bgp-investigation

Perfil completo de ASN: peers, prefijos, org registrada, país, conflictos MOAS, densidad de amenazas.

Ejemplo: /bgp-investigation AS13335

/typosquat-sweep

Barrido de brand protection: encuentra lookalikes registrados, los enriquece con feeds, ejecuta explain_indicator en los sospechosos, pivotea WHOIS.

Ejemplo: /typosquat-sweep paypal.com


Procedimientos Especiales (CALL)

Dentro de query() se pueden llamar estos procedimientos directamente en Cypher:

ProcedimientoEquivalente aPropósito
CALL explain("indicator")explain_indicatorAssessment de amenaza para IP/hostname/ASN/CIDR
CALL whisper.history("indicator")whisper_historySnapshots históricos WHOIS/BGP
CALL whisper.variants("name" [, "LABEL"] [, checkExisting])domain_variantsGeneración de variantes typosquat
CALL whisper.quota()Plan y uso actual del llamante
CALL db.labels()list_labelsLista todas las labels de nodo
CALL db.relationshipTypes()Lista todos los tipos de arista
CALL db.schema("json")Schema completo como JSON

whisper.variants() también funciona en posición de expresión: RETURN size(whisper.variants("paypal.com")) o MATCH (h:HOSTNAME {name: whisper.variants("paypal.com")[0].variant}) RETURN h


Labels del Grafo (20 tipos)

LabelDescripciónConteo aprox
HOSTNAMENombres de host/dominios2.6B
IPV4Direcciones IPv4619M
IPV6Direcciones IPv6
ANNOUNCED_PREFIXPrefijos BGP anunciados1.4M
ASNNúmeros de AS115K
ASN_NAMENombres de ASN
PREFIXBloques de asignación IP
COUNTRYPaíses
CITYCiudades
REGISTRARRegistradores WHOIS
EMAILEmails WHOIS237M
PHONETeléfonos WHOIS65M
ORGANIZATIONOrganizaciones WHOIS
FEED_SOURCEFuentes de threat intel~40
NAMESERVERServidores DNS autoritativos
MAIL_SERVERServidores de correo
WEB_CRAWLCrawls web
CERTIFICATECertificados TLS/SSL
TLDTop-level domains
FQDNFully-qualified domain names

Reglas de Seguridad en Queries

El servidor valida TODAS las queries antes de ejecutarlas. Violaciones devuelven VALIDATION_REJECTED:

  1. shortestPath debe tener límite: sin variable-length path sin límite dentro
  2. LIMIT ≤ 500: obligatorio
  3. No MATCH sin label: cada pattern debe tener label de nodo
  4. No disyunción de labels en misma variable: WHERE n:A OR n:B → rechazado (usar describe_label)
  5. Operadores de texto indexados solo en .name: CONTAINS / STARTS WITH / ENDS WITH solo en propiedad name
  6. No scans sin ancla: anclar en valor indexado
  7. Queries exploratorias deben incluir LIMIT

Modelo de Errores

El tool query devuelve un envelope de error tipado:

CampoSignificado
successtrue en éxito, false en error
errorMensaje legible
suggestionSolución concreta que el agente puede aplicar
errorCodeCódigo máquina (ver abajo)
retryableSi re-ejecutar podría funcionar

Códigos de error

CódigoCausaRetryable
DB_UNAVAILABLEBD de grafo inalcanzable
VALIDATION_REJECTEDQuery no pasa reglas de seguridadNo — corregir query
CYPHER_SYNTAX_ERRORCypher mal formadoNo — corregir query
DB_TIMEOUTQuery excedió tiempoSí — acotar
QUERY_TOO_EXPENSIVEQuery parada por presupuesto de elementos/filasNo — acotar

QUERY_TOO_EXPENSIVE es el guardia de tamaño, distinto de DB_TIMEOUT que es de duración.


Patrón de Introspección Recomendado

Cuando no sepas si la propiedad canónica es h.name o h.fqdn, o si anclar en HOSTNAME vs DOMAIN:

  1. Llama a list_labels primero → obtén labels y propiedades indexadas
  2. Llama a describe_label("HOSTNAME") → propiedades, tipos, aristas
  3. Escribe la query con conocimiento del schema

Ambos tools están cacheados 5 min y devuelven en milisegundos — no consumen quota.

Ejemplo de transcripción:

Usuario: ¿Qué labels tiene el grafo de Whisper?
Agente: [llama list_labels]
        → 20 labels. Las más grandes: HOSTNAME (2.6B), IPV4 (619M), ANNOUNCED_PREFIX (1.4M)

Usuario: Muéstrame las propiedades threat de un hostname.
Agente: [llama describe_label("HOSTNAME")]
        → properties: name (String, indexed), threatScore (Double), threatLevel (String),
          isThreat (Boolean), isC2 (Boolean), isPhishing (Boolean), isMalware (Boolean)...
        → out_edges: RESOLVES_TO → IPV4, CHILD_OF → HOSTNAME, HAS_REGISTRAR → REGISTRAR...
        → in_edges: NAMESERVER_FOR → HOSTNAME, MAIL_FOR → HOSTNAME...

Agente: [llama query]
        MATCH (h:HOSTNAME {name: "evil.example"})
        RETURN h.threatScore, h.threatLevel, h.isThreat, h.isC2, h.isPhishing, h.isMalware

Casos de Uso por Rol

SOC Analyst & Incident Responder

Triage Rápido — Trazar IP a Propietario de Red

MATCH (ip:IPV4 {name: "104.16.132.229"})
      -[:ANNOUNCED_BY]->(ap:ANNOUNCED_PREFIX)
      -[:ROUTES]->(a:ASN)
      -[:HAS_NAME]->(n:ASN_NAME)
RETURN ip.name AS ip, ap.name AS prefix, a.name AS asn, n.name AS network

104.16.132.229104.16.128.0/20AS13335CLOUDFLARENET

Verificar si un IP está en Feeds de Amenazas

MATCH (ip:IPV4 {name: "185.220.101.1"})-[:LISTED_IN]->(f:FEED_SOURCE)
RETURN ip.name, f.name

→ Dan Tor Exit, Tor Exit Nodes, IPsum

Threat Assessment Completo

CALL explain("185.220.101.1")

→ Score 4.95, INFO level, 3 feeds, desglose de factores, first/last seen

Reverse DNS — ¿Qué dominios apuntan aquí?

MATCH (ip:IPV4 {name: "104.16.132.229"})<-[:RESOLVES_TO]-(h:HOSTNAME)
RETURN h.name LIMIT 20

Contar dominios co-alojados

MATCH (ip:IPV4 {name: "104.16.132.229"})<-[:RESOLVES_TO]-(h:HOSTNAME)
RETURN count(h) AS cohosted

500 dominios → infraestructura CDN compartida. <20 → probablemente mismo operador.

Densidad de Amenazas en el Prefijo (Neighborhood Toxicity)

MATCH (ip:IPV4 {name: "3.69.87.14"})-[:BELONGS_TO]->(p:PREFIX)
RETURN p.name AS prefix, p.threatNeighborCount AS toxic_neighbors
LIMIT 1

3.64.0.0/12, 3363 vecinos tóxicos

MATCH (ip:IPV4 {name: "3.69.87.14"})-[:BELONGS_TO]->(p:PREFIX)<-[:BELONGS_TO]-(o:IPV4)
RETURN count(o) AS total_neighbors

→ 987,361 IPs totales → 0.34% densidad de amenazas

GeoIP — Localización

MATCH (ip:IPV4 {name: "109.111.100.154"})
      -[:LOCATED_IN]->(city:CITY)
      -[:HAS_COUNTRY]->(co:COUNTRY)
RETURN DISTINCT ip.name, city.name AS city, co.name AS country

BGP Country (cuando GeoIP no está disponible)

MATCH (ip:IPV4 {name: "8.8.8.8"})
      -[:ANNOUNCED_BY]->(ap:ANNOUNCED_PREFIX)
      -[:HAS_COUNTRY]->(co:COUNTRY)
RETURN ip.name, ap.name AS prefix, co.name AS country

8.8.8.0/24, US

WHOIS — Perfil de registro

MATCH (h:HOSTNAME {name: "cloudflare.com"})
OPTIONAL MATCH (h)-[:HAS_REGISTRAR]->(r:REGISTRAR)
OPTIONAL MATCH (h)-[:HAS_EMAIL]->(e:EMAIL)
OPTIONAL MATCH (h)-[:HAS_PHONE]->(p:PHONE)
RETURN h.name,
       collect(DISTINCT r.name) AS registrars,
       collect(DISTINCT e.name) AS emails,
       collect(DISTINCT p.name) AS phones

Nameservers — ¿Quién controla el DNS?

MATCH (ns:HOSTNAME)-[:NAMESERVER_FOR]->(h:HOSTNAME {name: "google.com"})
RETURN ns.name LIMIT 10

Traza Completa de Infraestructura

MATCH (h:HOSTNAME {name: "cloudflare.com"})
      -[:RESOLVES_TO]->(ip:IPV4)
      -[:ANNOUNCED_BY]->(ap:ANNOUNCED_PREFIX)
      -[:ROUTES]->(a:ASN)
      -[:HAS_NAME]->(n:ASN_NAME)
RETURN h.name AS host, ip.name AS ip, ap.name AS prefix,
       a.name AS asn, n.name AS network
LIMIT 10

Enriquecimiento Batch de IOCs

UNWIND ["185.220.101.1", "104.16.132.229", "8.8.8.8"] AS ip_addr
MATCH (ip:IPV4 {name: ip_addr})
      -[:ANNOUNCED_BY]->(ap:ANNOUNCED_PREFIX)
      -[:ROUTES]->(a:ASN)
RETURN ip_addr, ap.name AS prefix, a.name AS asn

Threat Intelligence Analyst

Encontrar infraestructura compartida via WHOIS

// Encontrar email de WHOIS
MATCH (h:HOSTNAME {name: "secure-login-update.com"})-[:HAS_EMAIL]->(e:EMAIL)
// Pivotar a otros dominios con ese email
MATCH (other:HOSTNAME)-[:HAS_EMAIL]->(e)
WHERE other.name <> "secure-login-update.com"
// Ver si comparten IPs
OPTIONAL MATCH (other)-[:RESOLVES_TO]->(ip:IPV4)
RETURN other.name, collect(DISTINCT ip.name) AS ips
LIMIT 20

Densidad de amenazas por ASN

MATCH (a:ASN {name: "AS60729"})
MATCH (a)<-[:ROUTES]-(ap:ANNOUNCED_PREFIX)
MATCH (ap)<-[:ANNOUNCED_BY]-(ip:IPV4)
WHERE ip.isThreat = true
RETURN a.name, count(DISTINCT ip) AS threatCount, count(DISTINCT ap) AS prefixCount

MOAS (Multiple Origin AS) Conflicts

// Un prefijo anunciado por múltiples ASNs
MATCH (ap:ANNOUNCED_PREFIX)<-[:ANNOUNCED_BY]-(:IPV4)-[:ANNOUNCED_BY]->(other_ap:ANNOUNCED_PREFIX)
WHERE ap.name = other_ap.name AND ap <> other_ap
MATCH (other_ap)-[:ROUTES]->(a:ASN)
RETURN ap.name, collect(DISTINCT a.name) AS asns

IPs en un CIDR que están en feeds

MATCH (ip:IPV4)-[:BELONGS_TO]->(p:PREFIX {name: "185.220.101.0/24"})
WHERE ip.isThreat = true
MATCH (ip)-[:LISTED_IN]->(f:FEED_SOURCE)
RETURN ip.name, collect(DISTINCT f.name) AS feeds

Cross-reference: Tor Exits con WHOIS

MATCH (f:FEED_SOURCE {name: "Dan Tor Exit"})<-[:LISTED_IN]-(ip:IPV4)
MATCH (ip)<-[:RESOLVES_TO]-(h:HOSTNAME)
OPTIONAL MATCH (h)-[:HAS_EMAIL]->(e:EMAIL)
OPTIONAL MATCH (h)-[:HAS_REGISTRAR]->(r:REGISTRAR)
RETURN h.name, ip.name, collect(DISTINCT e.name) AS emails, collect(DISTINCT r.name) AS registrars
LIMIT 20

Brand Protection & Anti-Phishing

Typosquat sweep básico

CALL whisper.variants("paypal.com")

→ Variantes registradas con método y confianza

Typosquat con todos los generados

CALL whisper.variants("paypal.com", "HOSTNAME", true)

→ Incluye variantes NO registradas

Typosquat + Threat Assessment

// Encontrar variantes y evaluarlas
CALL whisper.variants("paypal.com") YIELD variant, method, confidence
CALL explain(variant) YIELD score, level, sources
RETURN variant, method, confidence, score, level, sources
LIMIT 20

Typosquat + WHOIS pivot

CALL whisper.variants("paypal.com") YIELD variant
MATCH (h:HOSTNAME {name: variant})
OPTIONAL MATCH (h)-[:HAS_EMAIL]->(e:EMAIL)
OPTIONAL MATCH (h)-[:RESOLVES_TO]->(ip:IPV4)
RETURN variant, collect(DISTINCT e.name) AS emails, collect(DISTINCT ip.name) AS ips

Comparar variantes de múltiples marcas

UNWIND ["paypal.com", "amazon.com", "apple.com"] AS brand
CALL whisper.variants(brand) YIELD variant, method, confidence
RETURN brand, variant, method, confidence

Network & BGP Security

Perfil completo de ASN

MATCH (a:ASN {name: "AS13335"})
OPTIONAL MATCH (a)-[:HAS_NAME]->(n:ASN_NAME)
OPTIONAL MATCH (a)-[:PEERS_WITH]->(peer:ASN)
OPTIONAL MATCH (ap:ANNOUNCED_PREFIX)-[:ROUTES]->(a)
RETURN a.name, n.name AS network,
       count(DISTINCT peer) AS peerCount,
       count(DISTINCT ap) AS prefixCount

BGP Routing History

CALL whisper.history("8.8.8.8")

¿Qué ASNs peerean con Cloudflare Y Google?

MATCH (a:ASN {name: "AS13335"})-[:PEERS_WITH]->(common:ASN)<-[:PEERS_WITH]-(b:ASN {name: "AS15169"})
RETURN common.name

Análisis Blast Radius — si AS16509 (Amazon) cae

MATCH (a:ASN {name: "AS16509"})
MATCH (a)<-[:ROUTES]-(ap:ANNOUNCED_PREFIX)
OPTIONAL MATCH (ap)<-[:ANNOUNCED_BY]-(ip:IPV4)
OPTIONAL MATCH (ip)<-[:RESOLVES_TO]-(h:HOSTNAME)
OPTIONAL MATCH (a)-[:PEERS_WITH]->(peer:ASN)
RETURN count(DISTINCT ap) AS prefixes_affected,
       count(DISTINCT ip) AS ips_affected,
       count(DISTINCT h) AS domains_affected,
       count(DISTINCT peer) AS peers_affected

DNS & Email Security

Cadena SPF completa

// SPF includes de un dominio
MATCH (h:HOSTNAME {name: "shopify.com"})-[:HAS_SPF_INCLUDE]->(spf_target:HOSTNAME)
RETURN spf_target.name

Configuración email completa

MATCH (h:HOSTNAME {name: "example.com"})
OPTIONAL MATCH (h)-[:HAS_MX]->(mx:HOSTNAME)
OPTIONAL MATCH (h)-[:HAS_SPF_RECORD]->(spf:HOSTNAME)
OPTIONAL MATCH (ns:HOSTNAME)-[:MAIL_FOR]->(h)
RETURN h.name, collect(DISTINCT mx.name) AS mx_servers, collect(DISTINCT spf.name) AS spf_records

DNSSEC — ¿Está firmado?

MATCH (h:HOSTNAME {name: "cloudflare.com"})
RETURN h.name, h.hasDNSSEC, h.dnssecAlgorithm

% de DNSSEC bajo un nameserver

MATCH (ns:HOSTNAME)-[:NAMESERVER_FOR]->(h:HOSTNAME)
WHERE h.hasDNSSEC = true AND ns.name CONTAINS "cloudflare"
RETURN count(h) AS dnssec_domains

Compliance & Risk Assessment

¿Hostea algo en países sancionados?

MATCH (h:HOSTNAME {name: "company.com"})-[:RESOLVES_TO]->(ip:IPV4)
MATCH (ip)-[:LOCATED_IN]->(city:CITY)-[:HAS_COUNTRY]->(co:COUNTRY)
WHERE co.name IN ["RU", "IR", "KP", "CU", "SY"]
RETURN ip.name, city.name, co.name

Porcentaje de IPs de un ASN en país específico

MATCH (a:ASN {name: "AS60729"})<-[:ROUTES]-(ap:ANNOUNCED_PREFIX)
MATCH (ap)<-[:ANNOUNCED_BY]-(ip:IPV4)
MATCH (ip)-[:LOCATED_IN]->(city:CITY)-[:HAS_COUNTRY]->(co:COUNTRY {name: "RU"})
RETURN count(DISTINCT ip) AS ips_in_russia

Law Enforcement & Cybercrime

Pivoteo por teléfono WHOIS

MATCH (p:PHONE {name: "+1234567890"})<-[:HAS_PHONE]-(h:HOSTNAME)
OPTIONAL MATCH (h)-[:HAS_EMAIL]->(e:EMAIL)
OPTIONAL MATCH (h)-[:RESOLVES_TO]->(ip:IPV4)
RETURN h.name, collect(DISTINCT e.name) AS emails, collect(DISTINCT ip.name) AS ips

Dominios que comparten email Y rango IP

MATCH (h1:HOSTNAME {name: "known-bad.com"})-[:HAS_EMAIL]->(e:EMAIL)
MATCH (h2:HOSTNAME)-[:HAS_EMAIL]->(e)
WHERE h2.name <> "known-bad.com"
MATCH (h2)-[:RESOLVES_TO]->(ip:IPV4)
MATCH (ip)-[:BELONGS_TO]->(p:PREFIX)
MATCH (h1)-[:RESOLVES_TO]->(ip1:IPV4)
WHERE ip1.name IN p.name
RETURN h2.name, collect(DISTINCT ip.name) AS ips

Enlaces web — ¿Quién enlaza a un dominio sospechoso?

MATCH (h:HOSTNAME {name: "malware-distributor.example"})<-[:LINKS_TO]-(source:WEB_CRAWL)
MATCH (source)-[:CRAWLS]->(src_host:HOSTNAME)
RETURN src_host.name, source.url
LIMIT 50

Security Researchers

Comparar infraestructura de dos dominios

MATCH (h:HOSTNAME) WHERE h.name IN ["pandas-crossing.com", "afterlifeevents.com"]
OPTIONAL MATCH (h)-[:RESOLVES_TO]->(ip:IPV4)
OPTIONAL MATCH (ip)-[:ANNOUNCED_BY]->(ap:ANNOUNCED_PREFIX)-[:ROUTES]->(a:ASN)
OPTIONAL MATCH (h)-[:HAS_NAMESERVER]->(ns:HOSTNAME)
OPTIONAL MATCH (h)-[:HAS_EMAIL]->(e:EMAIL)
RETURN h.name, collect(DISTINCT ip.name) AS ips,
       collect(DISTINCT a.name) AS asns,
       collect(DISTINCT ns.name) AS nameservers,
       collect(DISTINCT e.name) AS emails

¿Dos dominios se enlazan mutuamente?

MATCH (h1:HOSTNAME {name: "site-a.com"})-[:LINKS_TO]->(h2:HOSTNAME {name: "site-b.com"})
RETURN h1.name, h2.name, "site-a links to site-b" AS relationship
UNION
MATCH (h1:HOSTNAME {name: "site-b.com"})-[:LINKS_TO]->(h2:HOSTNAME {name: "site-a.com"})
RETURN h1.name, h2.name, "site-b links to site-a" AS relationship

Cross-Cutting Recipes

Federar resultados de múltiples análisis

// Un mismo dominio: infraestructura + amenazas + WHOIS en 1 query
MATCH (h:HOSTNAME {name: "example.com"})
OPTIONAL MATCH (h)-[:RESOLVES_TO]->(ip:IPV4)
OPTIONAL MATCH (h)-[:HAS_EMAIL]->(e:EMAIL)
OPTIONAL MATCH (h)-[:HAS_REGISTRAR]->(r:REGISTRAR)
OPTIONAL MATCH (h)-[:LISTED_IN]->(f:FEED_SOURCE)
WITH h, collect(DISTINCT ip.name) AS ips, collect(DISTINCT e.name) AS emails,
     collect(DISTINCT r.name) AS registrars, collect(DISTINCT f.name) AS feeds
RETURN h.name, ips, emails, registrars, feeds

Timeline de cambios WHOIS

CALL whisper.history("google.com")

Lote de IPs → ASN + amenazas

UNWIND ["5.188.62.10", "45.33.32.156", "185.220.101.1"] AS target
MATCH (ip:IPV4 {name: target})
OPTIONAL MATCH (ip)-[:ANNOUNCED_BY]->(ap:ANNOUNCED_PREFIX)-[:ROUTES]->(a:ASN)
OPTIONAL MATCH (ip)-[:LISTED_IN]->(f:FEED_SOURCE)
RETURN target, ap.name AS prefix, a.name AS asn,
       collect(DISTINCT f.name) AS feeds

Preguntas de Ejemplo en Lenguaje Natural

Estas preguntas funcionan directamente con los prompts y tools del MCP:

Incident Response

  • “Investiga 185.220.101.42 — ¿quién lo posee, dónde está, está en feeds de amenazas, y qué más se aloja ahí?”
  • “Este dominio apareció en logs: secure-login-update.com. ¿Está vivo? ¿Quién lo registró? ¿El registrante tiene otros dominios?”
  • “Vemos tráfico a 104.16.132.229. Traza: IP a prefijo a ASN a org. Luego verifica si algún dominio co-alojado está marcado.”
  • “Aquí hay 20 IPs de nuestro SIEM. ¿Cuáles son Tor exits, C2 o están en listas negras?”

Threat Hunting

  • “Encuentra todos los dominios registrados por el mismo contacto WHOIS que secure-login-update.com ¿Alguno comparte IPs o nameservers?”
  • “Revisa AS60729 — ¿cuántos de sus prefijos tienen IPs en listas de amenazas? ¿Cuál es la densidad?”
  • “¿Hay conflictos MOAS en este prefijo? ¿Qué ASNs lo están anunciando?”
  • “Encuentra todas las IPs en 185.220.101.0/24 que aparecen en feeds de amenazas. Agrupa por categoría.”

Brand Protection

  • “Encuentra typosquats registrados de paypal.com.”
  • “Genera lookalikes de nuestra marca, luego verifica cuáles están en feeds de amenazas o resuelven a IPs activas.”
  • “¿Qué variantes registradas de microsoft.com comparten email de registrante o nameserver?”
  • “Barrido de typosquats de stripe.com — ¿quién registró los lookalikes y hay infraestructura marcada?”

Attack Surface

  • “Mapea tesla.com — subdominios, IPs, ASNs, nameservers, servidores de correo, includes SPF y registrante WHOIS.”
  • “¿Qué servicios terceros pueden enviar email como netflix.com? Recorre la cadena SPF completa.”
  • “Encuentra todos los subdominios de example.com, resuélvelos y agrupa por ASN. ¿Cuántos proveedores de hosting?”
  • “¿Dónde termina la cadena CNAME de www.example.com? ¿Quién hostea el destino final?”

WHOIS Pivoting

  • “Encuentra el registrante WHOIS de secure-login-update.com, luego todos los demás dominios que registró. ¿Alguno comparte infraestructura?”
  • “¿Qué dominios usan este email de contacto? Muestra sus IPs y ASNs, y marca los que están en listas.”
  • “¿Ha cambiado google.com de registrador? Muestra el histórico.”
  • “Compara WHOIS de estos cinco dominios — ¿mismo registrante? ¿Mismo email? ¿Mismo registrador?”

BGP & Routing

  • “Si AS16509 (Amazon) cae, ¿cuántos prefijos y peers se afectan? ¿Qué dominios se pierden?”
  • “¿Qué ASNs peerean con Cloudflare Y Google?”
  • “Muestra el histórico BGP de 8.8.8.0/24. ¿Ha cambiado el ASN anunciante?”
  • “Encuentra prefijos con conflictos MOAS anunciados por AS60729. ¿Alguno hostea IPs en listas de amenazas?”

Comparing Infrastructure

  • “¿Comparten infraestructura pandas-crossing.com y afterlifeevents.com?”
  • “Estos tres dominios phishing fueron reportados por separado. ¿Algún nameserver, IP, ASN o contacto WHOIS compartido?”
  • “Compara el hosting y setup de email de estos dos productos SaaS competidores.”
  • “Encuentra dominios que compartan el mismo email de registrante Y el mismo rango IP que un dominio conocido malo.”

Email & SPF

  • “¿Quién puede enviar email como shopify.com? Recorre la cadena SPF.”
  • “¿Qué dominios usan los mismos targets SPF include que este dominio phishing?”
  • “¿Tiene este dominio MX? ¿SPF? Dame la configuración email completa.”

GeoIP & Data Residency

  • “¿Dónde están todas las IPs a las que resuelve example.com? Lista por país.”
  • “¿Hostea está empresa algo en países sancionados? Revisa todas las IPs de sus dominios.”
  • “Encuentra todas las IPs en este ASN que geolocalizan a Rusia.”

History

  • “Muestra el histórico WHOIS de google.com — cambios de registrador, nameservers, ownership.”
  • “Histórico BGP de 8.8.8.8 — ¿ha cambiado el ASN o prefijo anunciante?”
  • “¿Cuándo se registró este dominio? ¿Ha cambiado de dueño?”

Enlaces Útiles


Nota: Todas las queries en está guía han sido validadas contra la documentación oficial de Whisper Security. El grafo contiene datos vivos — los resultados exactos (conteos, IPs, feeds) varían con el tiempo.