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>
7.5 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | params | output | tested | tests | test_file_path | file_path | |||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| fingerprint_web_stack | pipeline | py | pipelines | 1.0.0 | impure | def fingerprint_web_stack(url: str, timeout_s: float = 15.0, verify_tls: bool = True, max_html_bytes: int = 500_000, save: bool = True) -> dict | One-shot que detecta la tecnologia web (stack tecnologico estilo Wappalyzer) de una URL: hace el fetch HTTP de las senales (fetch_http_fingerprint) y matchea las firmas (detect_web_tech), devolviendo las tecnologias detectadas — servidor, lenguaje, CMS, framework web, frameworks JS, librerias, analytics, CDN, e-commerce, WAF — con categoria, version y confidence. Reemplaza el patron fetch_http_fingerprint -> detect_web_tech por una sola llamada. El equivalente registry de Wappalyzer / whatweb / un fingerprint de stack de una url. Opcionalmente archiva la evidencia (tabla TECNOLOGIA/CATEGORIA/VERSION/CONFIDENCE) en OSINT. Util para reconocimiento web, auditoria de superficie y averiguar que CMS framework servidor usa un sitio. |
|
|
false | error_py_core |
|
dict con status ('ok'|'error'), url, final_url (tras redirects), status_code (int), server (cabecera Server o ''), title (titulo de la pagina o ''), technologies (lista de dicts con name, category, version, confidence, evidence — tal cual de detect_web_tech), by_category (dict categoria -> lista de nombres), count (int), saved (dict de save_scan_to_osint con note_path/registered/scan_id, o None si save=False) y raw (tabla legible TECNOLOGIA/CATEGORIA/VERSION/CONFIDENCE con cabecera de url/status/server/title). Si el fetch HTTP falla (host no resuelve, conexion rechazada, timeout) -> {status:error, stage:fetch, url:..., fetch:<dict>}. Nunca lanza. | true |
|
python/functions/pipelines/fingerprint_web_stack_test.py | python/functions/pipelines/fingerprint_web_stack.py |
Ejemplo
from pipelines.fingerprint_web_stack import fingerprint_web_stack
# Fingerprint del stack tecnologico de un sitio, en 1 paso (sin archivar).
r = fingerprint_web_stack("https://example.com", save=False)
print(r["status"]) # "ok"
print(r["server"]) # "nginx/1.24.0"
print(r["count"]) # 5
for t in r["technologies"]:
print(t["name"], t["category"], t["version"], t["confidence"])
# WordPress cms 6.4 high
# nginx web-server 1.24.0 high
# PHP programming-language medium
print(r["by_category"]) # {"cms": ["WordPress"], "web-server": ["nginx"], ...}
from pipelines.fingerprint_web_stack import fingerprint_web_stack
# Con archivado en OSINT (default): deja una nota en el vault + POST al osint_db.
r = fingerprint_web_stack("https://midominio.example")
print(r["saved"]["note_path"]) # dominios/midominio.example/recon/web_tech-....md
# Por CLI: detecta el stack de un sitio.
./fn run fingerprint_web_stack https://example.com
# Flags: --no-save (no archiva OSINT), --no-verify-tls (cert self-signed, inseguro).
./fn run fingerprint_web_stack https://example.com --no-save
Cuando usarla
Cuando quieras en UN solo paso saber que tecnologia usa un sitio web (servidor,
CMS, frameworks JS, lenguaje, analytics, CDN, WAF) — el equivalente registry de
Wappalyzer. Reemplaza el patron fetch_http_fingerprint -> detect_web_tech
(un fetch + un matching). Tipico para: reconocimiento web inicial de un
objetivo, averiguar el CMS/framework de un sitio antes de un pentest
autorizado, auditar la superficie tecnologica de tus propios dominios, o
enriquecer una investigacion OSINT con el stack de un host.
Gotchas
- Fetch estatico: NO ejecuta JavaScript. Solo ve el HTML inicial que devuelve el servidor. Las SPAs que montan el framework (React/Vue/Angular/Svelte) en runtime suelen servir un HTML casi vacio, asi que esos frameworks pueden NO detectarse. Para sitios JS-pesados, un fingerprint con navegador real (CDP) veria mas; este pipeline es la version sin navegador.
- La tabla de firmas es un subconjunto de Wappalyzer, no exhaustiva. Un
tecnologia no listada en
detect_web_techno aparecera aunque este presente. Para ampliar cobertura, anade entradas aSIGNATURESendetect_web_tech. verify_tls=Falsees inseguro: desactiva la verificacion del certificado (MITM posible). Usalo solo contra hosts propios con cert self-signed.- Un WAF/anti-bot puede devolver un challenge (Cloudflare, Imperva...) en vez del sitio real: en ese caso las tecnologias detectadas seran las del WAF y el HTML del challenge, no las del sitio de fondo.
- save=True escribe en el vault OSINT (
~/Obsidian/osint) y hace POST al serviceosint_db(http://127.0.0.1:8771). Si el service esta caido,save_scan_to_osintdegrada a solo-nota (saved.registered=Falseconregister_warning); el pipeline no falla por eso. - Autorizacion legal: hacer fingerprint de hosts ajenos puede entrar en reconocimiento no autorizado. Respeta el scope y la autorizacion explicita; usalo sobre objetivos propios o consentidos.
- Pipeline impuro: hace red (fetch HTTP) y, con
save=True, FS/HTTP (vault + service). No es determinista entre ejecuciones. - Si el fetch HTTP falla del todo (
status != "ok": host no resuelve, conexion rechazada, timeout), el pipeline devuelve{"status":"error","stage":"fetch",...}y no intenta matchear firmas ni archivar nada. Un 403/404/500 NO es fallo de fetch: sigue siendo senal de fingerprint y se procesa con su status_code.
Notas
Pipeline que compone 3 funciones atomicas del dominio cybersecurity. No
reimplementa logica de fetch, matching de firmas ni persistencia: solo orquesta
fetch_http_fingerprint (recoleccion de senales, impura) + detect_web_tech
(matching de firmas, pura) y delega el guardado en save_scan_to_osint. El
raw de evidencia incluye una cabecera con url/final_url/status_code/server/
title y una tabla TECNOLOGIA/CATEGORIA/VERSION/CONFIDENCE; nunca embebe el HTML
entero ni valores de cookie (las cookies de fetch_http_fingerprint ya son solo
nombres). El target para el archivado OSINT se deriva del host de la URL
(urllib.parse.urlparse(...).hostname). Nunca lanza excepciones: todo fallo se
refleja en la clave status del dict devuelto.