935008ec3f
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>
132 lines
8.2 KiB
Markdown
132 lines
8.2 KiB
Markdown
---
|
|
name: nmap_scan
|
|
kind: function
|
|
lang: py
|
|
domain: cybersecurity
|
|
version: "1.1.0"
|
|
purity: impure
|
|
signature: "def nmap_scan(target: str, profile: str = 'quick', ports: str | None = None, extra_args: list[str] | None = None, out_dir: str | None = None, timeout_s: int = 1800, confirm: bool = False, allowlist: list[str] | None = None) -> dict"
|
|
description: "Wrapper de `nmap` por perfiles para reconocimiento de red. Ejecuta nmap como subprocess forzando salida XML (-oX), la parsea con ElementTree y devuelve puertos abiertos y hosts vivos de forma estructurada. Funcion estrella de recon: corre en primer plano (quick, top1000, service) y segundo plano para scans largos (full-tcp, vuln, udp-top). NO lanza: devuelve dict status ok/error. Sin sudo por defecto (connect-scan TCP)."
|
|
tags: [recon, nmap, portscan, cybersecurity]
|
|
params:
|
|
- name: target
|
|
desc: "Host, IP o rango CIDR a escanear (ej. 'scanme.nmap.org', '192.168.1.10', o '192.168.1.0/24' con el perfil discovery). Vacio devuelve status error."
|
|
- name: profile
|
|
desc: "Clave de PROFILES que determina los flags de nmap. quick=(-T4 -F) top 100 puertos rapido; top1000=(-T4) los 1000 puertos default; full-tcp=(-p- -T4) los 65535 TCP, LARGO; service=(-sV -sC -T4) deteccion de version + scripts default; udp-top=(-sU --top-ports 100 -T4) UDP top 100, LARGO y suele requerir sudo; vuln=(-sV --script vuln -T4) scripts de vulnerabilidades, LARGO; discovery=(-sn) ping sweep / host discovery de una subred; aggressive=(-A -T4) OS+version+script+traceroute (el -O interno puede pedir sudo); os=(-O) OS detection, REQUIERE sudo/root. Perfil invalido devuelve status error listando los validos."
|
|
- name: ports
|
|
desc: "Especificacion de puertos para -p (ej. '22,80,443' o '1-1000'). Si se pasa, anade '-p <ports>' al comando. None deja los puertos que defina el perfil."
|
|
- name: extra_args
|
|
desc: "Lista de flags adicionales de nmap a anadir tal cual al comando (ej. ['--open', '-Pn']). None no anade nada."
|
|
- name: out_dir
|
|
desc: "Directorio donde guardar el XML. Si se pasa, se crea y el XML se guarda como nmap-<profile>-<target>-<timestamp>.xml (util para scans largos en background y conservar el resultado). None usa un archivo temporal."
|
|
- name: timeout_s
|
|
desc: "Segundos maximos de ejecucion del subprocess. Default 1800 (30 min). Para scans largos (full-tcp, vuln, udp-top) subir este valor; superarlo devuelve status error con mensaje claro."
|
|
- name: confirm
|
|
desc: "Confirmacion explicita para escanear un target publico o desconocido. Default False: si el target no es claramente privado/local (10.x, 192.168.x, 127.x, localhost, *.local/.lan/.internal/.home/.corp) y no esta en allowlist, el escaneo se rechaza con status error y needs_confirm=True (proteccion anti-escaneo no autorizado). Pasar True solo con autorizacion. No hace DNS lookup (sin red)."
|
|
- name: allowlist
|
|
desc: "Lista de targets autorizados. Un target pasa el guard sin confirm si coincide exactamente con una entrada o termina en ella (ej. ['scanme.nmap.org'] o ['example.com']). None o lista vacia no autoriza nada."
|
|
output: "dict. ok: {status:'ok', target, profile, command (cmd ejecutado), open_ports:[{port:int,proto,state,service,product,version}] (solo open/open|filtered), hosts_up:[ips] (host discovery), host_status, xml_path (siempre presente), raw (stdout de nmap, siempre presente), elapsed_s:float, started (ISO)}. error: {status:'error', error:str}. Si el guard rechaza el target (publico/desconocido sin confirm ni allowlist) el error tambien incluye needs_confirm:True. Nunca lanza excepciones."
|
|
uses_functions: []
|
|
uses_types: []
|
|
returns: []
|
|
returns_optional: false
|
|
error_type: "error_py_core"
|
|
imports: []
|
|
tested: true
|
|
tests:
|
|
- test_parse_xml_extrae_puertos_abiertos_y_hosts_up
|
|
- test_guard_publico_sin_confirm_rechaza_y_no_ejecuta
|
|
- test_guard_privado_procede_y_parsea
|
|
- test_guard_confirm_true_sobre_publico_procede
|
|
- test_guard_allowlist_procede
|
|
- test_perfil_invalido_devuelve_error
|
|
- test_target_vacio_devuelve_error
|
|
- test_target_is_private_clasifica
|
|
test_file_path: "python/functions/cybersecurity/nmap_scan_test.py"
|
|
file_path: "python/functions/cybersecurity/nmap_scan.py"
|
|
---
|
|
|
|
## Ejemplo
|
|
|
|
```python
|
|
import sys, os
|
|
sys.path.insert(0, os.path.join("python", "functions"))
|
|
from cybersecurity import nmap_scan
|
|
|
|
# 1) Scan rapido en primer plano contra el host oficial de pruebas de nmap
|
|
# (scanme.nmap.org es legal escanear).
|
|
res = nmap_scan("scanme.nmap.org", profile="quick", timeout_s=120)
|
|
if res["status"] == "ok":
|
|
for p in res["open_ports"]:
|
|
print(p["port"], p["proto"], p["service"], p["product"], p["version"])
|
|
else:
|
|
print("error:", res["error"])
|
|
|
|
# 2) Scan LARGO de los 65535 puertos TCP guardando el XML en out_dir.
|
|
# Lanzar en segundo plano (background) por la duracion; el XML queda en disco.
|
|
res = nmap_scan(
|
|
"scanme.nmap.org",
|
|
profile="full-tcp",
|
|
out_dir="/tmp/nmap-runs",
|
|
timeout_s=7200, # 2h: full-tcp puede tardar minutos a horas
|
|
allowlist=["scanme.nmap.org"], # autorizado -> pasa el guard sin confirm
|
|
)
|
|
print(res["status"], res.get("xml_path"))
|
|
|
|
# 3) Guard de seguridad: un target publico SIN confirm ni allowlist se rechaza.
|
|
res = nmap_scan("8.8.8.8") # publico, sin confirm
|
|
print(res["status"], res.get("needs_confirm")) # "error" True
|
|
|
|
# Para escanear un publico autorizado: confirm=True (o anadirlo a allowlist).
|
|
res = nmap_scan("8.8.8.8", confirm=True)
|
|
# Un target privado/local NO requiere confirm:
|
|
res = nmap_scan("192.168.1.10") # procede directamente
|
|
```
|
|
|
|
## Cuando usarla
|
|
|
|
Usala para el reconocimiento de puertos y servicios de un host: mapear la
|
|
superficie de ataque antes de un pentest autorizado, descubrir que servicios
|
|
y versiones expone una IP, o barrer una subred con `profile="discovery"` para
|
|
ver que hosts estan vivos. Es la funcion estrella de recon del registry.
|
|
|
|
Para scans largos (`full-tcp`, `vuln`, `udp-top`) lanza la llamada en SEGUNDO
|
|
PLANO: tardan de minutos a horas. Pasa `out_dir` para conservar el XML en disco
|
|
y sube `timeout_s` (p.ej. 7200) para que no aborte por timeout.
|
|
|
|
## Gotchas
|
|
|
|
- GUARD anti-escaneo no autorizado: por defecto (`confirm=False`) la funcion
|
|
RECHAZA con status error + `needs_confirm=True` cualquier target que no sea
|
|
claramente privado/local (rangos privados, loopback, link-local, `localhost`,
|
|
`*.local/.lan/.internal/.home/.corp`). Para escanear un target publico o un
|
|
hostname desconocido tienes que pasar `confirm=True` o incluirlo en
|
|
`allowlist` (match exacto o por sufijo). El guard NO hace DNS lookup (sin red,
|
|
KISS): un hostname publico se considera "indecidible" y cae al lado seguro
|
|
(requiere confirm). Esto NO sustituye tu responsabilidad legal — solo evita
|
|
disparos accidentales contra infra ajena.
|
|
- LEGAL: solo escanea hosts que sean tuyos o para los que tengas autorizacion
|
|
explicita. `scanme.nmap.org` es el host oficial de pruebas de nmap, legal
|
|
escanear; cualquier otro objetivo de terceros sin permiso puede ser delito.
|
|
- Privilegios: los perfiles `os` (-O), `udp-top` (-sU) y parte de `aggressive`
|
|
(-O interno) requieren sudo/root. Sin privilegios nmap cae a connect-scan TCP
|
|
(-sT) y esos modos fallan o quedan incompletos — esta funcion no usa sudo.
|
|
- Duracion: `full-tcp` (65535 puertos), `vuln` (scripts NSE) y `udp-top` (UDP
|
|
es lento) tardan minutos a horas. Sube `timeout_s` y/o lanza en background con
|
|
`out_dir`; superar `timeout_s` devuelve status error.
|
|
- Deteccion: firewalls / IDS / WAF pueden detectar y bloquear el escaneo (sobre
|
|
todo `aggressive`, `vuln` y `-T4`). El resultado puede venir filtrado o
|
|
incompleto si el objetivo defiende activamente.
|
|
- `discovery` (-sn) espera notacion de host o subred en CIDR (ej.
|
|
"192.168.1.0/24"); puebla `hosts_up`, no `open_ports`.
|
|
- No lanza excepciones: siempre revisa `res["status"]` antes de leer
|
|
`open_ports`/`hosts_up`. `raw` y `xml_path` solo estan garantizados en ok.
|
|
|
|
## Capability growth log
|
|
|
|
- v1.1.0 (2026-06-14) — guard `confirm`/`allowlist` anti-escaneo-no-autorizado:
|
|
targets publicos/desconocidos se rechazan (status error + needs_confirm) salvo
|
|
confirm=True o estar en allowlist; privados/local proceden sin confirm. Sin DNS
|
|
lookup. Anadidos tests (8 casos: parseo XML, guard publico/privado/confirm/
|
|
allowlist, perfil invalido, target vacio, clasificacion _target_is_private).
|