Sign in

Bottleneck — Vulnhub Walkthrough

Hi, this is quite a fun box for me and was rated as intermediate in Proving Grounds, without further ado, let’s get started. Enjoy !

Network Enumeration

nmap -sCV -oA nmap/bottleneck

I filtered out the recommend exploit section to make it short :

Seems port 80 is open, let’s take a look :


I go through the page source but didn’t found any interesting. Hence i use ffuf with wordlistbig.txt and extension .php to find hidden directory/files.

ffuf -w /usr/share/wordlists/dirb/big.txt -u -e .php

I found a file called image_gallery.php

image_gallery.php [Status: 200, Size: 6381, Words: 1626, Lines: 169]

At first i thought that this page doesn’t vulnerable. But by looking at the Network section, i found out every time i refresh the page, there will be a GET request going out with parameter t and f.

We can guess that parameter f stands for file. i try decode it using base64 and got the result:

Yes, we are correct, i even found this file was in directory img

So i tried encoded base64 classic LFI payloads to grab /etc/passwd but failed. It return a 200 status code but with blank page.

After hours of searching, figured out that paramter t stands for timestamp and it was Unix time.

And soon i figured out that we need provide an exact timestamp as in machine in order to grab files. So i started to write a Python script to automate this.

First to figure out the exact timestamp on machine. We need to know the timestamp on our machine :

And i minus the timestamp on parameter t with our machine timestamp :

Because of few seconds goes by while i copy pasting, ill use 28800 to evaluate in my case.

Below was the Python script :

The content ofpayload.txt i used :

By running the Python script, i got the output :

Seems like there are something blocking us, probably WAF. But what if we grab image_gallery.php source code instead of /etc/passwd ?

So i changed the content of payload.txt to :

Run this script again and BOOM, we got it :

The reason why payload ../image_gallery.php worked because in early the bottleneck_dontbe.png was in img directory which means we need to step up a directory to grab image_gallery.php.

With the output we got, we noticed the existence of image_gallery_load.php, so let's grab it !


In this output of image_gallery_load.php , we can see its blocking few directories :


And that’s the reason why /etc/passwd wont work.

We can see if it detected directories in the blacklist, it will block it and end up doing this command:

exec('python /opt/ </var/log/soc/'.$logfile.' >/tmp/output 2>&1');

The above python command will output to /tmp/output . I try again changing content of payload.txt to grab for /tmp/output but failed. There are few reasons why it failed :

  1. Timestamp not correct
  2. Empty file
  3. Something in the machine keep erase the content of /tmp/output

I read the code again and noticed that reason 2 was the reason it failed because :

  • Our timestamp should be correct (Since its automated).
  • Reason 3 should be unlikely because its quite nonsense.

So why /tmp/output was empty? The reason was the exec function work when they detected blacklisted directories. Maybe the machine haven't detect any blacklisted directories or error so the /tmp/output was empty, maybe?

Let’s try it by changing the content of payload.txt again :

I also add a log poisoning PHP payload to see what happen.

I got an error output :

As you can see, the python source code was data = str(input('report: ')) and /tmp/output seems used to output the error.

I searched the web about python input exploit and found an interesting page. So i modify the content of payload.txt :

I setup a netcat listener on port 8888 and run the script :

BOOM ! i got the shell !


With command sudo -l, we found interesting command :

In /var/www/html/web_utils/ , a file called clear_logs has symlink to /opt/ , but /opt/ was owned by bytevsbyteand we don't have permission to edit the file :

Since we have the permission to edit clear_logs, let's change its symlink with command :

ln -fns /tmp/clear_logsc /var/www/html/web_utils/clear_logs

Edit the /tmp/clear_logsc :

echo -e '#!/bin/bash\n/bin/bash' > /tmp/clear_logsc

Set the permission to execute /tmp/clear_logsc :

chmod 777 /tmp/clear_logsc

Run the command and we will get bytevsbyte user :

sudo -u bytevsbyte /var/www/html/web_utils/clear_logs


We are now bytevsbyte, let's find file with SUID on it :

find / -perm -u=s -type f 2>/dev/null

We spotted an interesting file :


I’m not familiar with C code. i think it accept an argument (probably a file) and execute the argument file’s function test_this. Please let me know if my explanation got anything wrong. I'm still learning.

First at our main local machine, we create a C file called test_this.cwith the following code :

Then we run this command :

gcc -fPIC -shared test_this.c -o

In our main local machine :

python3 -m http.server 8099

In Bottleneck machine :

And we will get ROOT access !

Thank you so much for reading this ! Hope you enjoy a lot and see you again until next time !

Information Technology Student