Skip to content

Over the Wire – Natas 2-3 – Directory Listing

On continue notre série sur la suite de challenges Natas avec les niveaux 2 et 3.

Pour rappel, histoire de donner un peu plus de consistance à ces articles , je compte, pour chaque challenge, rédiger un script Python qui permettra d’automatiser la détection ou l’exploitation des vulnérabilités présentées. Également, nous étudierons les recommandations associées à chaque vulnérabilité exploitée (lorsque cela sera pertinent). L’objectif étant de voir comment exploiter une vulnérabilité pour mieux s’en protéger, cela en étudiant aussi bien l’attaque que la défense.

Natas 2 – Exploitation

URL du challenge : http://natas2.natas.labs.overthewire.org/

Nous arrivons ici sur une page web tout à fait standard, si l’on jette un œil à son code source (voir les niveaux précédents), on peut distinguer la présence d’un attribut <img> qui permet d’inclure une image. Rien d’extraordinaire :

Page web du challenge et son code source

Cependant, après quelques instants à tourner en rond, on peut s’intéresser à cette image, et notamment au répertoire où elle est située. L’image s’appelle pixel.png et ne présente rien d’intéressant. Le répertoire qui contient cette image est lui plus intéressant, lorsque l’on tente d’y accéder (on supprime le nom de l’image de l’URL), on aperçoit ceci :

Affiche du contenu du répertoire web

Il s’agit d’une vulnérabilité de type Directory listing, c’est un défaut de configuration du service web qui permet à un utilisateur de lister le contenu « brut » des répertoires du service web. Cela expose ainsi potentiellement des informations techniques (le nom de la machine, du service web et sa version), mais aussi des fichiers qui n’ont pas forcément vocation à être consultés. Je décrit plus précisément le directory listing, ses impacts et ses corrections dans cet article : Qu’est ce que le Directory Browsing/Listing ?

Pour être plus exacte, il peut y avoir affichage du nom de la technologie et de sa version sans nécessairement passer par du Directory Listing. Et à l’inverse, on peut avoir du Directory Listing sans affichage d’une technologie ou d’une version précise, voir cet article : Qu’est ce que le Banner Grabbing ?

On accède au contenu du répertoire donc, on découvre un nouveau fichier qui se nomme user.txt :

Accès au fichier user.txt

Ce fichier n’est indiqué nul part dans l’application web. Autrement dit, il n’est pas référencé (pointé par un lien, une image, ou autre). Une autre manière de le trouver aurait été :

  1. de référencer tous les répertoires de l’application web, par bruteforce ou par étude des liens qu’elle présente;
  2. d’effectuer une énumération des fichiers et extensions possibles (communs) à partir d’un dictionnaire dans ces répertoires.

On obtient donc dans ce fichier le mot de passe vers le niveau suivant.

Natas 3 – Exploitation

URL du challenge : http://natas3.natas.labs.overthewire.org/

Le niveau 3 expose une vulnérabilité ou mauvaise pratique différente du niveau 2, mais le même script Python peut être utilisé pour exploiter ces deux vulnérabilités. En arrivant sur la page principale, on ne remarque pas grand chose :

Page d’accueil du challenge Natas 03

Il faut s’intéresser, après un peu de recherche, au fichier robots.txt, qui est un fichier dont le contenu est dédié aux robots d’indexation (Google, Bing, etc.)

Le protocole d’exclusion des robots est une ressource de format texte qui peut être placée à la racine d’un site web, et qui contient une liste des ressources du site qui ne sont pas censées être indexées par les robots d’indexation des moteurs de recherche. Par convention, les robots consultent robots.txt avant d’indexer un site Web. Sur le serveur Web, cette ressource est fréquemment enregistrée dans un fichier texte appelé robots.txt.

Source : https://fr.wikipedia.org/wiki/Protocole_d%27exclusion_des_robots

Ce fichier contient donc par définition des liens que le propriétaire d’un site web souhaite cacher des résultats des moteurs de recherche. Il est donc logique que l’attaquant s’y intéresse. Voici le contenu du fichier robots.txt sur le challenge Natas 3 :

Contenu du fichier robots.txt

Le nom du fichier est assez explicite pour nous faire comprendre que nous sommes sur la bonne piste, si l’on visite le répertoire indiqué :

Encore une fois, le fichier user.txt contient le mot de passe vers le niveau suivant :

Contenu du fichier /s3cre3t/users.txt

Exploitation via un script Python

L’idée du script Python à créer ici et donc d’analyser le code source d’un page, d’y référencer tous les liens présent (image, liens internes) , d’analyser tous les dossiers existants et de les requêter afin d’y trouver un « Index of« , signe de la présence d’un Directory Listing.

Après avoir fait ma première requête, j’utilise un expression régulière pour récupérer toutes les balises, elles commencent par un « < » et finissent par un « > ».

A nouveau, pour tester vos expressions régulières, je vous conseille le site suivant : regex101.com

Parmi les balises récupérées, je filtre celles qui présentent un lien, principalement les balises contenant des href, comme les liens, et des src, comme les images. Puis je construis à partir de cette base de liens une liste des répertoires de la page web . Pour faire simple et pouvoir réutiliser ce bout de code, je l’ai mis dans une fonction, qui prend en entrée le contenu d’une réponse web (objet géré par la bibliothèque request) :

def getLink(HTMLResponse):
	"""
		Build a folder list to check based on URL in the source code
		return :
			- list containing URL of found folder.
	"""
	resList = HTMLResponse.text.split('\n')
	linkList = list();

	# Parse HTML response and get all link
	for line in resList:
		# For each line, regex on "<(/*)>" (HTML tag)
		htmlTag = re.findall("<(.*?)>", line)

		# finding "src" and "href" and add the to linkList for further processing
		for x in htmlTag:
			urls = re.search('(src|href)=[\'"]?([^\'" >]+)', x)
			if urls:
				sanitizedURL= urls.group(2)
				if not sanitizedURL.startswith("h"):
					sanitizedURL = url+str(sanitizedURL)
				linkList.append(sanitizedURL)

		folderList = list();
		for link in linkList:
			folder = re.search('(.*)\/', link)
			if folder:
				if folder.group(0) not in folderList:
					folderList.append(folder.group(0))

	return folderList

Nous pourrons ensuite afficher les répertoires « vulnérables » (ou plutôt mal configurés), effectuer une requête sur chacun d’eux et pour chaque, regarder si le contenu du code source récupéré contient un « Index of« :

def lookForIndexOf(fList):
	"""
		look for "index of" in each URL
		- return : list
	"""
	indexOfFolder = list()
	for folderURL in fList:
		# Only check link on the targetted domain
		if url in folderURL:
			# print("[DEBUG] Checking folder ["+folderURL+"]")
			try: 
				res = requests.get(folderURL, auth=HTTPBasicAuth(user, password))
				# list Directory listing found
				if "Index of" in res.text:
					indexOfFolder.append(folderURL)
					# Custom for natas, look for "user.txt" file in listed directory
					lookForUser(res)					
			except AssertionError as error:
				print("[-] issue with URL "+folderURL+"")
				print(error)
	return indexOfFolder

Pour résoudre le challenge 3 en plus du challenge 2 avec le même script, il me suffit de parcourir le contenu du fichier robots.txt à la recherche de répertoires qui seront eux aussi analysés. Je me base donc sur ce fichier pour alimenter ma liste de dossiers à vérifier :

def getRobots(fList):

	"""
		extract folder for robots.txt. Take a list in input and just update it
		return:
			- list
	"""
	res = requests.get(url+"/robots.txt", auth=HTTPBasicAuth(user, password), stream=True)
	if res.status_code == 200:
		for line in res.text.splitlines():
			disallowedURL = re.search('^Disallow: (.*)', line)
			if disallowedURL:
				fList.append(url+str(disallowedURL.group(1)))
	else:
		print("[-] No robots.txt (return code "+str(res.status_code)+")")
	return fList

Le script complet, et peut être amélioré depuis l’écriture de l’article, est disponible à cet endroit : https://github.com/ogma-sec/natas_scripts/blob/master/natas-02-03.py

Dans ce script, j’ai ajouté une fonction propre au challenge natas qui se charge de regarder si un fichier user.txt est présent dans la liste des fichiers listés, qui va le récupérer si c’est le cas, et qui fait appel à ma fonction de récupération du flag précédemment écrite (natas.findPasswordInString) :

def lookForUser(HTMLResponse):
	"""
		Custom for natas, look for "user.txt" file in listed directory
		return:
			- nothing
	"""
	resList = HTMLResponse.text.split('\n')
	for line in resList :
		if "users.txt" in line:
			res2 = requests.get(HTMLResponse.url+"/users.txt", auth=HTTPBasicAuth(user, password))
			b, p = natas.findPasswordInString(res2.text)
			if b:
				print("[+] Password found ! ["+str(p)+"] ")
				natas.updateLevel(challNumber + 1, p)
				print("[+] Level "+str(challNumber + 1)+" updated")
			break	

Ce script fonctionne comme attendu :

Exécution de mon script Python pour résoudre automatiquement les challenges natas 2 et 3

Cependant il ne traite qu’un cas bien précis et peut difficilement fonctionner efficacement sur des sites plus important. L’outil dirhunt que j’ai présenté dans cet article (https://ogma-sec.fr/dirhunt-enumeration-des-repertoires-web-sans-brute-force/) récemment est beaucoup plus complet et peut être utilisé ici. Le seul bémol de dirhunt pour le moment est qu’il ne gère pas l’authentification via des options. Cependant, l’authentification HTTP Basic a la particularité de pouvoir être utilisée directement dans l’URL comme ceci :

http://monLogin:monPassword@monsite.fr

Concernant l’authentification HTTP Basic, en production, ceci n’est bien évidemment pas recommandé du tout, ceci pour plusieurs raison :

  • Le mot de passe est affiché à l’écran, n’importe qui autour de vous pourrait donc le consulter.
  • L’URL qui contient les informations d’authentification va se retrouver dans votre cache navigateur, et pourra donc être consultée dans le futur par une personne ayant pris le contrôle de votre poste.
  • De la même manière, ces informations vont transiter sur les proxy potentiellement présents entre vous et le serveur, ainsi que dans leurs journaux.

Bref, vous n’avez aucune garantie que ces informations ne se trouvent pas un jour stockées dans un endroit non sécurisé dont vous n’avez pas le contrôle. D’une manière générale, aucune information sensible (mot de passe, jeton, etc.) ne doit être stocké dans l’URL, voir cet article de l’OWASP : Information exposure through query strings in url

Après cet aparté, voici comment dirhunt, qui relève également les « Index of » des répertoires scannés, aurait pu être utilisé pour ces deux challenges :

Utilisation de dirhunt pour résoudre natas 2

Également, j’ai remarqué que pour des sites très petit (comme les challenges natas), dirhunt ne prend pas le temps d’exécuter tout ses modules et le fichier robots.txt n’est pas vérifié. J’ai remonté ce problème à l’auteur qui va tenter de corriger cela dans la prochaine version (7). Dans les faits je n’ai donc pu résoudre que le niveau 2 avec dirhunt (pour l’instant), celui-ci me remonte avec succès la présence d’un Index Of sur l’un des répertoires de l’application web visée. Celui-ci reste en réalité très utile lorsque l’on s’intéresse à de vraies application web.

Bonnes pratiques de sécurité

La bonne pratique de sécurité ici veut que le directory listing soit désactivé par le service web, cela par un durcissement de sa configuration. La politique par défaut sur tous les répertoires de toutes les applications web doit prévoir une configuration dans ce sens. Il peut exister des exceptions, justifiées par un besoin métier. C’est par exemple le cas des dépôts Linux, dont le contenu est plus facilement explorable en utilisant cette fonctionnalité :

Exemple de directory listing volontaire sur le site debian.org

Ces exceptions doivent alors être accordées sur des répertoires précis de l’application web. L’OWASP traite de ce sujet ici :
https://www.owasp.org/index.php/File_System#Insecure_Indexing

J’expose dans cet article les configurations techniques permettant de durcir les services web Apache et Microsoft IIS : Qu’est ce que le Directory Browsing/Listing ?

Également, stocker des informations sensibles dans un fichier accessible par tous (même non référencé) et une très mauvaise idée. On ne peut en effet garantir que personne ne trouvera jamais ce fichier même s’il n’est pas référencé. Une erreur de configuration ou un message d’erreur un peu trop verbeux pourrait exposer ce fichier et ainsi causer la fuite des identifiants utilisateurs. Il serait ici judicieux de stocker ces informations hors de la racine du service web afin qu’elles ne soient pas accessibles par les utilisateurs.

Enfin, les liens indiqués dans le fichiers robots.txt ne doivent pas être accessibles si vous les jugés sensibles. Un robots d’indexation (ou crawler) n’y accédera pas mais l’attaquant sera toujours plus curieux et cherchera à savoir pourquoi ces interdictions sont mises en place. Il ne s’agit donc pas d’un endroit adéquat pour inscrire des fichiers ou répertoires à cacher. Préférez une interdiction d’accès (via la gestion des droits de vos applications métiers ou par fichier .htaccess).

Pour terminer, voici des exemples de cas réels d’exploitation d’un Directory Listing :

Partager :
Published inChallenges et CTFs

One Comment

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *