P0pR0cK5's Blog

Pentest, Challenges, Tests and more ...

View on GitHub

Writeup Overthewire, Natas lvl 0-10

Retour

Overthewire : Natas

Aujourd’hui nous allons nous attaquer au challenge Natas du site Overthewire. Ce challenge est centré sur les applications web et va donc permettre à n’importe qui d’en comprendre les fondamentaux.

Natas0

La résolution du premier niveaux est plutôt simple, faites ctrl + maj + i pour lire le code source de la page :

Natas1

On va ici compliquer un peut les choses en bloquant le clic droit, la encore un ctrl + maj + i fera largement le travail :

Natas2

Passons aux choses sérieuses, il n’y à rien sur la page :

Bien entendus le code source ne nous aide pas mieux (quoi que …):

<html>
<!-- Header retiré car il ne contient rien qui nous interésse -->
<body>
<h1>natas2</h1>
<div id="content">
There is nothing on this page
<img src="files/pixel.png">
</div>
</body></html>

Plusieurs idées :

  • Vérifier les header HTTP ?
  • Est-ce qu’un mot de passe caché dans l’image pixel.png ?
  • Le path de l’image nous indique l’existence d’un dossier ` files `

On commence par le plus simple, vérifier si le dossier files est mal configuré :

Bingo ! Il semble que la configuration Apache autorise l’affichage du dossier files. En ouvrant ` users.txt ` on trouve ce que l’on cherche :

username:password
alice:BYNdCesZqW
bob:jw2ueICLvT
charlie:G5vCxkVV3m
natas3:sJIJNW6ucpu6HPZ1ZAchaDtwd7oGrD14
eve:zo4mJWyNj2
mallory:9urtcpzBmH

Natas3

Cette fois-ci ce n’est pas si simple; on se retrouve sur la même page qu’avant mais sans image :

En lisant le commentaire en vert on apprend que même Google n’est pas capable de trouver le mot de passe.

Qui dis Google dis également indexation et donc web crawler. Vous savez, ces robots qui parcourent le web dans l’objectif d’indexer tout ce qu’ils trouvent pour nos moteurs de recherches.

Il existe un moyen d’interdire à ces fameux robots de lire le contenus de certains fichiers grâce au fameux robots.txt. Voici le contenus de celui de natas3 :

User-agent: *
Disallow: /s3cr3t/

Si on lit bien, on voit que l’on indique clairement d’ignorer un fichier du nom de s3cr3t.

Si nous allions nous balader dedans ?!

Nous y sommes; voici le contenus du fichier users.txt :

natas4:Z9tkRkWmpt9Qr7XrR5jWRkgOU901swEZ

Natas 4

Nous voici maintenant face à une page qui nous annonce que l’accès est refusé car nous venons du site “” alors que seul les utilisateurs provenant de http://natas5.natas.labs.overthewire.org/ sont autorisé.

Hum… Réfléchissons, quel moyen technique permet de fournir des informations de ce genre ?

  • Les Cookies ?
  • Les header HTTP ?

Par défaut j’élimine les cookie car ces derniers serait dur à retrouver sans le code exécuté coté serveur.. On va donc se concentrer sur Les Headers.

On cherche ici tout header en rapport avec une page précédemment visité, Referer semble répondre à notre besoin. Si nous utilisions curl pour interroger notre page avec un header spécifique ?!

OUI, il existe des extensions pour ça mais c’est bien plus formateur de le faire via curl

curl --header "Referer:http://natas5.natas.labs.overthewire.org/" http://natas4.natas.labs.overthewire.org/

Ce premier essaie renvoie une erreur, j’ai oublié de spécifier les identifiants de connexions :

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head>
<title>401 Unauthorized</title>
</head><body>
<h1>Unauthorized</h1>
<p>This server could not verify that you
are authorized to access the document
requested.  Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
<hr>
<address>Apache/2.4.10 (Debian) Server at natas4.natas.labs.overthewire.org Port 80</address>
</body></html>

Maintenant on va spécifier les identifiants avec l’option -u :

curl -u natas4:Z9tkRkWmpt9Qr7XrR5jWRkgOU901swEZ --header "Referer:http://natas5.natas.labs.overthewire.org/" http://natas4.natas.labs.overthewire.org/ 

Voila l’identifiant pour le prochain niveau !

<html>
<head>
....
</head>
<body>
<h1>natas4</h1>
<div id="content">
Access granted. The password for natas5 is iX6IOfmpN7AYOQGPwtn3fXpbaJVJcHfq
<br/>
<div id="viewsource"><a href="index.php">Refresh page</a></div>
</div>
</body>
</html>

Natas 5

Dans ce niveau nous sommes face à une page qui nous indique que nous ne sommes pas connecté et que donc, nous ne sommes pas autorisé à accéder au site.

Comment un site fait-il pour savoir si je suis connecté ? Il existe plusieurs techniques mais les plus connus sont les cookie et les variables de sessions.

Si nous observions les cookie stocké par notre navigateur ?

Tiens, un cookie totalement non sécurisé ! En temps normal un cookie devrait être une clé plus ou moins complexe et non un booléen facile à modifier. Bien entendus nos amis développeurs s’accorderont à dire que le cookie seul ne fait pas grand chose et ils ont raison. Nous sommes surtout ici sur un cas totalement exagéré pour les besoins de l’exercice.

Si l’on change ce cookie à 1, voici ce que l’on obtiens :

Next level please ! Identifiants : natas6:aGoY4q2Dc6MgDq4oL4YtoKtyAg9PeHa1

Natas 6 :

On arrive donc sur un site qui nous demande d’entrée un mot de passe :

Un autre détail important est la présence d’un lien vers le code source de la page. Voici ce que l’on obtiens s’il on clique dessus :

<?
include "includes/secret.inc";
    if(array_key_exists("submit", $_POST)) {
        if($secret == $_POST['secret']) {
        print "Access granted. The password for natas7 is <censored>";
    } else {
        print "Wrong secret";
    }
    }
?>

On s’aperçoit qu’il s’agit ici de PHP.

En lisant le code on ne remarque pas de faille particulière dans les conditions Néanmoins, on remarque qu’une inclusion à lieu au début du code et que cette inclusion pointe vers un fichier secret.inc qui contient vraisemblablement la valeur de la variable $secret.

Le créateur du site à ici voulu cacher le mot de passe en le mettant dans un fichier à part sans se rendre compte que ce fichier pouvais être lu par le serveur web.

Si nous tentions de lire ce fichier ?

curl -u natas6:aGoY4q2Dc6MgDq4oL4YtoKtyAg9PeHa1 http://natas6.natas.labs.overthewire.org/includes/secret.inc
<?
$secret = "FOEIUWGHFEEUHOFUOIU";
?>

Nous voila rendus !

Identifiants : natas7:7z3hEENjQtflzgnT29q7wAvMNfZdh0i9

Natas 7 :

On arrive ici sur un nouvelle page avec deux jolies liens :

Observons le code source de la page :

<body>
<h1>natas7</h1>
<div id="content">
<a href="index.php?page=home">Home</a>
<a href="index.php?page=about">About</a>
<br>
<br>
this is the front page
<!-- hint: password for webuser natas8 is in /etc/natas_webpass/natas8 -->
</div>
</body>

On vois ici que les liens appellent le fichier index.php en lui passant un argument via l’URL. On voit également un commentaire qui nous explique ou se trouve le mot de passe pour le prochain niveau. En soit le passage d’argument ne pose pas de problème si on s’assure qu’aucunes données sensibles ne circule par ce biais.

Si nous testions de mettre n’importe quoi d’autre à la place d’un des paramètre ?

On vois ici une erreur de la part de PHP qui fait référence à un include impossible. Souvenez-vous du niveau précédent ou l’on utilisait déjà cette fonction. L’erreur qui est faites ici est de placer le paramètre de l’URL directement dans un include sans vérifier la validité de ce dernier.

L’incidence directe de cette négligence est de permettre d’inclure n’importe quoi dans la page et donc de possiblement l’afficher. Testons avec le chemin qui nous à été fournis en commentaire (/etc/natas_webpass/natas8):

Identifiants : natas8:DBfUBfqQG69KvJvJ1iAbMoIpwSNQ9bWe

Natas 8 :

Dans ce niveau, on arrive sur une page web qui nous demande un mot de passe :

Comme précédemment , on trouve un lien vers le code source de la page :

<?
$encodedSecret = "3d3d516343746d4d6d6c315669563362";
function encodeSecret($secret) {
    return bin2hex(strrev(base64_encode($secret)));
}
if(array_key_exists("submit", $_POST)) {
    if(encodeSecret($_POST['secret']) == $encodedSecret) {
    print "Access granted. The password for natas9 is <censored>";
    } else {
    print "Wrong secret";
    }
}
?>

Ici j’ai volontairement retiré le reste du code source car il n’était pas utile à la compréhension du problème.

Maintenant, nous constatons qu’une fonction d’encodage de mot de passe est déclaré sous le nom encodeSecret. Il est d’usage de hasher un mot de passe avant de l’utiliser car contrairement à du chiffrement, le hashage est irréversible.

Pour faire court on stock un mot de passe hasher pour rendre ce derniers illisible, il suffit ensuite de hasher le mot de passe saisit par un utilisateur et de le comparer avec celui que l’on a stocké pour autorisé l’accès.

On garantie ainsi qu’a aucun moment un mot de passe en clair n’est utilisé.

Bien entendus ici, aucun hashage n’est effectué on va donc pouvoir retrouver le mot de passe en faisant exactement le contraire de ce que fait la fonction d’encodage encodeSecret.

La technique utilisé par l’auteur est dites sécurisation par l’obscure. On crois être protégé car on cache les données importantes. Cela reviens à cacher une clé sous son paillasson.

Voici un bout de code permettant de résoudre notre challenge :

<?php

#Variable contenant le flag chiffré
$encodedSecret = "3d3d516343746d4d6d6c315669563362";

# Fonction d'encodage 
function encodeSecret($secret) {
    return bin2hex(strrev(base64_encode($secret)));
}

# Fonction de décodage 
function decodeSecret($secret2) {
    return base64_decode(strrev(hex2bin($secret2)));
}

# Encodage de la string "test"
echo encodeSecret("test");
echo "\n";
# Décodage de la string test encodé
echo decodeSecret(encodeSecret("test"));
# On retombe sur la même valeur donc notre fonction de déchiffrement fonctionne 
echo "\n";
# On fait de même avec la variable encodedSecret
echo decodeSecret("3d3d516343746d4d6d6c315669563362");
?>

On encode la string test et on obtiens : 3d3d41647a564764. On décode 3d3d41647a564764 et on obtiens test. Nous voila capable de coder et décoder !

Testons avec la variable $encodedSecret, on obtiens oubWYf2kBq :

Identifiants : natas9:W0mMhUcRRnG8dcghE4qvk3JA9lGt8nDl

Natas 9 :

Cette fois-ci on tombe sur une page qui nous propose de rechercher des mots contenant la suite de caractères que l’on saisit :

Même chose que tout à l’heure, on à un accès au code source :

<?
$key = "";

if(array_key_exists("needle", $_REQUEST)) {
    $key = $_REQUEST["needle"];
}

if($key != "") {
    passthru("grep -i $key dictionary.txt");
}
?>

Comme on le voit, le code fait appel à un bash pour utilisé grep mais une faille évidente à été négligé !

Faites echo "coucou" ; date dans une console bash et vous comprendrez :

Le point-virgule nous permet ici d’exécuter une commande a la suite de echo, testons avec notre application web en lui passant ; cat /etc/issue:

Magique ! Rappelons nous maintenant du chemin /etc/natas_webpass/ qui nous avait été donné plus tôt en faisant ; ls /etc/natas_webpass/ :

La solution est simple non ? En faisant ; cat /etc/natas_webpass/natas10 on obtiens notre mot de passe !

Identifiants : natas10:nOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu

Natas 10 :

Cette fois-ci on reprend le même concept que l’exercice précédent avec une petite subtilité supplémentaire :

<?
$key = "";

if(array_key_exists("needle", $_REQUEST)) {
    $key = $_REQUEST["needle"];
}

if($key != "") {
    if(preg_match('/[;|&]/',$key)) {
        print "Input contains an illegal character!";
    } else {
        passthru("grep -i $key dictionary.txt");
    }
}
?>

Comme on le voit, une expression régulière bloque ici les caractères & ; |**. On doit donc restreindre fortement son champ d’action pour résoudre ce challenge.

En bash , d’autre caractères spécifiques existent et ne sont pas bloquer ici. Parmi eux, le # qui permet de commenter une partie de la commande.

On va donc pouvoir ignorer dictionary.txt et le remplacer par autre chose. Pourquoi pas /etc/natas_webpass/natas11 ?

Que doit-on rechercher dans ce fichier ? natas11 ? Nous sommes dans le fichier qui contient le mot de passe donc utilisons un wildcard comme .*.

On va donc rechercher n’importe quel caractère dans le fichier /etc/natas_webpass/natas11 en saisissant .* /etc/natas_webpass/natas11 # :

Bingo !

Identifiants : natas11:U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK

Conclusion

On peux dire que ce challenge nous apporte de bonnes bases pour se rendre compte des failles les plus critiques des aplications web. Dans le prochain billet nous passerons aux choses serieuses avec des challenges à base de cryptographie.


Written on November 12, 2017 by


Retour