feat(recon): modo CDP en fingerprint_web_stack para detectar SPAs
Añade fetch_http_fingerprint_cdp_py_browser (domain browser): recoge el HTML renderizado tras ejecutar JavaScript usando un Chrome remoto via CDP, componiendo cdp_open_url_and_wait + cdp_eval. Devuelve la misma estructura que el fetch estático para que detect_web_tech lo consuma sin cambios. Integra use_cdp en el pipeline fingerprint_web_stack (v1.1.0): combina los headers reales del fetch estático con el HTML post-JS del CDP. Detecta frameworks de SPA (React/Vue/Angular/Next) que el fetch estático no ve porque montan el DOM en runtime. Si no hay Chrome en cdp_port, degrada al fetch estático con un warning (no rompe). cdp_port=9333 (Chrome aislado) recomendado para terceros, 9222 diario. Verificado en vivo (Chrome 9333): sobre una SPA cuyo marcador de framework solo aparece tras ejecutar JS, el estático detecta solo nginx; con use_cdp=True detecta además Next.js, React y Node.js. Tests: 48 verdes (error path sin Chrome + happy path mockeado + degradación). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,7 +22,8 @@ Comparte tag y dominio (`cybersecurity`) con el grupo `osint-passive` (recolecci
|
||||
| `scan_port_services_py_pipelines` | `scan_port_services(host, ports="common", timeout_s=1.0, workers=100, grab_banners=True, banner_timeout_s=3.0, save=True) -> dict` | **Pipeline one-shot nativo.** Escanea puertos y, por cada abierto, devuelve servicio esperado (IANA) + servicio/version real del banner. Compone `scan_tcp_ports` + `identify_port_service` + `grab_service_banner` (+ sink OSINT). Reemplaza el patron scan→identify→grab sin nmap. |
|
||||
| `fetch_http_fingerprint_py_cybersecurity` | `fetch_http_fingerprint(url, timeout_s=15.0, verify_tls=True, max_html_bytes=500000, user_agent=None) -> dict` | **Fetch de señales web (stdlib).** GET con UA de navegador, sigue redirects, descomprime gzip. Devuelve `headers` (lowercase), `cookies` (solo NOMBRES, sin valores), `html`, `title`, `server`, `status_code`, `final_url`, `raw`. Capa impura del fingerprint web. |
|
||||
| `detect_web_tech_py_cybersecurity` | `detect_web_tech(headers, html="", cookies=None, final_url="") -> dict` | **Pure. Detector de tecnologia web estilo Wappalyzer.** Matchea ~50 firmas embebidas (regex) contra headers/html/cookies → `technologies[{name, category, version, confidence, evidence}]`, `by_category`, `count`. Cubre server, lenguaje, CMS, frameworks JS, librerias, analytics, CDN, e-commerce, WAF. |
|
||||
| `fingerprint_web_stack_py_pipelines` | `fingerprint_web_stack(url, timeout_s=15.0, verify_tls=True, max_html_bytes=500000, save=True) -> dict` | **Pipeline one-shot = Wappalyzer del registry.** url → tecnologias detectadas. Compone `fetch_http_fingerprint` + `detect_web_tech` (+ sink OSINT). El camino canonico para fingerprint web. |
|
||||
| `fetch_http_fingerprint_cdp_py_browser` | `fetch_http_fingerprint_cdp(url, *, port=9222, wait_render_s=2.0, timeout_s=30.0, close_tab=True) -> dict` | **Fetch del HTML RENDERIZADO (post-JS) via CDP.** Navega en un Chrome remoto (compone `cdp_open_url_and_wait` + `cdp_eval`), espera el render y devuelve el `html` con el DOM ya montado por JS → detecta SPAs (React/Vue/Angular/Next) que el fetch estatico no ve. Mismo shape que `fetch_http_fingerprint` (headers={}, status_code=None: la red la aporta el estatico). |
|
||||
| `fingerprint_web_stack_py_pipelines` | `fingerprint_web_stack(url, timeout_s=15.0, verify_tls=True, max_html_bytes=500000, save=True, use_cdp=False, cdp_port=9222, wait_render_s=2.0) -> dict` | **Pipeline one-shot = Wappalyzer del registry.** url → tecnologias detectadas. Compone `fetch_http_fingerprint` + `detect_web_tech` (+ sink OSINT). Con `use_cdp=True` añade `fetch_http_fingerprint_cdp`: headers reales del estatico + HTML renderizado del CDP (detecta SPAs); degrada a estatico con warning si no hay Chrome. El camino canonico para fingerprint web. |
|
||||
|
||||
### OSINT pasivo relacionado
|
||||
|
||||
@@ -128,7 +129,22 @@ PYEOF
|
||||
|
||||
Las dos capas tambien sueltas: `fetch_http_fingerprint(url)` para inspeccionar cabeceras+html+cookies crudos de una URL, y `detect_web_tech(headers, html, cookies)` (pura) para matchear firmas sobre señales ya recogidas (testeable sin red).
|
||||
|
||||
> Limite: un fetch estatico NO ejecuta JavaScript. Una SPA que monta su framework en runtime (React/Vue con HTML inicial vacio) puede no detectarse. Para esos casos, recoger el DOM renderizado via el grupo `browser` (CDP) y pasar ese html a `detect_web_tech`.
|
||||
**Modo CDP (SPAs): detectar mas eficientemente el HTML renderizado.** Un fetch estatico NO ejecuta JavaScript: una SPA (React/Vue/Angular/Next con HTML inicial casi vacio) monta su DOM en runtime y el estatico la pierde. Con `use_cdp=True` el pipeline usa `fetch_http_fingerprint_cdp` (Chrome remoto via CDP) para analizar el DOM ya renderizado, combinando los headers reales del estatico con el HTML post-JS.
|
||||
|
||||
```bash
|
||||
cd /home/enmanuel/fn_registry
|
||||
python/.venv/bin/python3 - <<'PYEOF'
|
||||
import sys
|
||||
sys.path.insert(0, "python/functions")
|
||||
from pipelines.fingerprint_web_stack import fingerprint_web_stack
|
||||
|
||||
# cdp_port=9333 = Chrome aislado del browser_mcp (recomendado para terceros); 9222 = navegador diario.
|
||||
res = fingerprint_web_stack("https://una-spa.com", use_cdp=True, cdp_port=9333, save=False)
|
||||
print(res["html_source"], "->", [t["name"] for t in res["technologies"]])
|
||||
PYEOF
|
||||
```
|
||||
|
||||
Ganancia verificada en vivo: sobre una SPA cuyo marcador de framework solo aparece tras ejecutar JS, el estatico detecta solo `nginx`; con `use_cdp=True` detecta ademas `Next.js`, `React`, `Node.js`. Si no hay Chrome en `cdp_port`, degrada al fetch estatico con un `warning` (no falla).
|
||||
|
||||
## Integracion OSINT
|
||||
|
||||
|
||||
Reference in New Issue
Block a user