feat(recon): grupo de reconocimiento de red + servicios + fingerprint web
Añade el capability group `recon` (dominio cybersecurity + pipelines, Python),
con la política de archivado OSINT y página madre docs/capabilities/recon.md.
Lookups y sondeo (wrappers de CLI):
- whois_lookup, rdap_lookup, dns_records, ping_host, traceroute_host, nmap_scan
- save_scan_to_osint (sink común) + recon_osint (pipeline one-shot scan+archivado)
Escaneo de puertos/servicios nativo (stdlib, sin nmap ni sudo):
- scan_tcp_ports: connect-scan TCP concurrente (open/closed/filtered)
- grab_service_banner: banner grab + identificación de servicio/versión real
- identify_port_service: puro, puerto -> servicio IANA esperado (~120 puertos)
- scan_port_services: pipeline one-shot (scan -> identify + banner por puerto abierto)
Fingerprint de tecnología web (estilo Wappalyzer), patrón pura/impura:
- fetch_http_fingerprint: GET stdlib, recoge headers/html/cookies (solo nombres)
- detect_web_tech: puro, matchea ~50 firmas regex -> tecnologías por categoría
- fingerprint_web_stack: pipeline one-shot url -> tecnologías
Todas devuelven dict {status} sin lanzar. Tests: 43 verdes, sin red externa.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
---
|
||||
name: recon_osint
|
||||
kind: pipeline
|
||||
lang: py
|
||||
domain: pipelines
|
||||
version: "1.1.0"
|
||||
purity: impure
|
||||
signature: "def recon_osint(target: str, scan_type: str = 'whois', save: bool = True, profile: str = 'quick', record_types: list[str] | None = None, count: int = 4, max_hops: int = 30, timeout_s: int | None = None, confirm: bool = False) -> dict"
|
||||
description: "One-shot que ejecuta un escaneo de red atomico (whois/rdap/dns/ping/traceroute/nmap) y SIEMPRE lo archiva en OSINT. Materializa la politica 'todo escaneo se guarda en osint': convierte el patron de 2 llamadas (scan atomico + sink) en 1 sola."
|
||||
tags: [recon, osint, pipeline, cybersecurity, osint-passive, sink]
|
||||
uses_functions:
|
||||
- whois_lookup_py_cybersecurity
|
||||
- rdap_lookup_py_cybersecurity
|
||||
- dns_records_py_cybersecurity
|
||||
- ping_host_py_cybersecurity
|
||||
- traceroute_host_py_cybersecurity
|
||||
- nmap_scan_py_cybersecurity
|
||||
- save_scan_to_osint_py_cybersecurity
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_py_core"
|
||||
imports: []
|
||||
params:
|
||||
- name: target
|
||||
desc: "Dominio, host o IP objetivo del escaneo (ej. google.com, scanme.nmap.org, 8.8.8.8)."
|
||||
- name: scan_type
|
||||
desc: "Tipo de escaneo a ejecutar. Uno de: whois, rdap, dns, ping, traceroute, nmap. Default 'whois'."
|
||||
- name: save
|
||||
desc: "Si True (default) archiva el resultado en OSINT via save_scan_to_osint; si False solo ejecuta el escaneo y no toca el vault."
|
||||
- name: profile
|
||||
desc: "Perfil de nmap (solo aplica a scan_type='nmap'): quick, full-tcp, vuln, etc. Default 'quick'."
|
||||
- name: record_types
|
||||
desc: "Lista de tipos de registro DNS a consultar (solo scan_type='dns'), ej. ['A','MX','TXT']. None usa los defaults del atomico."
|
||||
- name: count
|
||||
desc: "Numero de paquetes ICMP a enviar (solo scan_type='ping'). Default 4."
|
||||
- name: max_hops
|
||||
desc: "Numero maximo de saltos a sondear (solo scan_type='traceroute'). Default 30."
|
||||
- name: timeout_s
|
||||
desc: "Timeout en segundos. Si se pasa, se propaga al escaneo atomico; None deja que cada atomico use su default. Sube este valor para nmap full-tcp/vuln."
|
||||
- name: confirm
|
||||
desc: "Confirmacion explicita para el escaneo activo de nmap (solo aplica a scan_type='nmap'); se propaga a nmap_scan(confirm=...). Default False: nmap rechaza targets publicos/desconocidos no autorizados (status error + needs_confirm). Pasar True solo con autorizacion. Se ignora para whois/rdap/dns/ping/traceroute. CLI: flag --confirm (y --allowlist a,b,c que activa confirm si el target esta autorizado)."
|
||||
output: "dict con status ('ok'|'error'), target, scan_type, scan (dict crudo del atomico) y osint (dict de save_scan_to_osint con note_path/registered/scan_id, o None si save=False). scan_type invalido -> {status:error, stage:validate, valid:[...]}. Escaneo fallido -> {status:error, stage:scan, scan:<dict>} sin intentar guardar. Nunca lanza."
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "python/functions/pipelines/recon_osint.py"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```python
|
||||
from pipelines.recon_osint import recon_osint
|
||||
|
||||
# WHOIS de un dominio: ejecuta el lookup y lo archiva en OSINT (1 paso).
|
||||
r = recon_osint("google.com", "whois")
|
||||
print(r["status"]) # "ok"
|
||||
print(r["osint"]["note_path"]) # ruta de la nota creada en el vault osint
|
||||
```
|
||||
|
||||
```python
|
||||
from pipelines.recon_osint import recon_osint
|
||||
|
||||
# Escaneo nmap rapido de un host autorizado, archivado en OSINT.
|
||||
r = recon_osint("scanme.nmap.org", "nmap", profile="quick")
|
||||
print(r["scan"]["open_ports"]) # puertos abiertos detectados
|
||||
print(r["osint"]["registered"]) # True si el service osint_db lo registro
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Para lanzar un escaneo de red y archivarlo en OSINT en un solo paso. Usalo en
|
||||
vez de llamar el atomico (`whois_lookup`, `nmap_scan`, ...) + `save_scan_to_osint`
|
||||
por separado. Garantiza que el resultado queda en el vault: es la materializacion
|
||||
de la politica "todo escaneo que lancemos se guarda en osint".
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Hereda los gotchas de cada escaneo atomico que compone:
|
||||
- **nmap**: guard anti-escaneo no autorizado — un target publico/desconocido
|
||||
se rechaza (status error + needs_confirm) salvo que pases `confirm=True`
|
||||
(o, por CLI, `--confirm` / `--allowlist`). Los privados/local proceden sin
|
||||
confirm. Solo escanea objetivos para los que tengas autorizacion legal;
|
||||
escaneos sin permiso pueden ser ilegales. Requiere `nmap` instalado.
|
||||
- **ping / traceroute**: el ICMP puede estar filtrado por firewalls; un
|
||||
`loss_pct` 100% o pocos `hops` no implican que el host este caido, solo que
|
||||
no responde a ICMP.
|
||||
- **whois / rdap**: dependen de la disponibilidad y rate-limit del servidor
|
||||
WHOIS/RDAP del TLD; respuestas truncadas o vacias son posibles.
|
||||
- **dns**: resuelve contra el resolver del sistema; resultados varian segun el
|
||||
DNS configurado.
|
||||
- Requiere el service `osint_db` vivo (`http://127.0.0.1:8771`) para el registro
|
||||
estructurado; si no responde, `save_scan_to_osint` degrada a guardar solo la
|
||||
nota en el vault (sin entrada en DuckDB). El pipeline no falla por eso.
|
||||
- Para nmap largos (`full-tcp`, `vuln`) pasa `profile` + un `timeout_s` alto y
|
||||
considera lanzarlo en background; el default `timeout_s` del atomico nmap es
|
||||
amplio (1800s) pero un escaneo completo puede excederlo.
|
||||
- Si el escaneo atomico falla (`status == "error"`), el pipeline devuelve
|
||||
`{"status":"error","stage":"scan",...}` y **no** intenta guardar nada en OSINT.
|
||||
- Pipeline impuro: hace red (escaneos) y FS/HTTP (vault + service). No es
|
||||
determinista entre ejecuciones.
|
||||
|
||||
## Notas
|
||||
|
||||
Pipeline que compone 7 funciones atomicas del dominio `cybersecurity`. No
|
||||
reimplementa logica de escaneo ni de persistencia; solo despacha, normaliza un
|
||||
`summary` por tipo de escaneo y delega el guardado. Nunca lanza excepciones:
|
||||
todo fallo se refleja en la clave `status` del dict devuelto.
|
||||
|
||||
## Capability growth log
|
||||
|
||||
- v1.1.0 (2026-06-14) — param `confirm` propagado a `nmap_scan(confirm=...)`
|
||||
(solo scan_type='nmap') para el guard anti-escaneo-no-autorizado; CLI gana
|
||||
flag `--confirm` y `--allowlist a,b,c` (activa confirm si el target esta
|
||||
autorizado). Sin el flag, confirm=False (compatibilidad intacta).
|
||||
Reference in New Issue
Block a user